0a6d873482df7c93d8dca08550b9aa4e2171d8cf
[WebKit-https.git] / Source / WebCore / platform / audio / AudioArray.h
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #ifndef AudioArray_h
30 #define AudioArray_h
31
32 #include <string.h>
33 #include <wtf/FastMalloc.h>
34 #include <wtf/Vector.h>
35
36 namespace WebCore {
37
38 template<typename T>
39 class AudioArray {
40 public:
41     AudioArray() : m_allocation(0), m_alignedData(0), m_size(0) { }
42     explicit AudioArray(size_t n) : m_allocation(0), m_alignedData(0), m_size(0)
43     {
44         allocate(n);
45     }
46
47     ~AudioArray()
48     {
49         fastFree(m_allocation);
50     }
51
52     // It's OK to call allocate() multiple times, but data will *not* be copied from an initial allocation
53     // if re-allocated. Allocations are zero-initialized.
54     void allocate(size_t n)
55     {
56         // Although n is a size_t, its true limit is max unsigned because we use unsigned in zeroRange()
57         // and copyToRange(). Also check for integer overflow.
58         if (n > std::numeric_limits<unsigned>::max() / sizeof(T))
59             CRASH();
60       
61         unsigned initialSize = sizeof(T) * n;
62
63 #if USE(WEBAUDIO_FFMPEG)
64         const size_t alignment = 32;
65 #else
66         const size_t alignment = 16;
67 #endif
68
69         if (m_allocation)
70             fastFree(m_allocation);
71         
72         bool isAllocationGood = false;
73         
74         while (!isAllocationGood) {
75             // Initially we try to allocate the exact size, but if it's not aligned
76             // then we'll have to reallocate and from then on allocate extra.
77             static size_t extraAllocationBytes = 0;
78
79             // Again, check for integer overflow.
80             if (initialSize + extraAllocationBytes < initialSize)
81                 CRASH();
82
83             T* allocation = static_cast<T*>(fastMalloc(initialSize + extraAllocationBytes));
84             if (!allocation)
85                 CRASH();
86             T* alignedData = alignedAddress(allocation, alignment);
87
88             if (alignedData == allocation || extraAllocationBytes == alignment) {
89                 m_allocation = allocation;
90                 m_alignedData = alignedData;
91                 m_size = n;
92                 isAllocationGood = true;
93                 zero();
94             } else {
95                 extraAllocationBytes = alignment; // always allocate extra after the first alignment failure.
96                 fastFree(allocation);
97             }
98         }
99     }
100
101     T* data() { return m_alignedData; }
102     const T* data() const { return m_alignedData; }
103     size_t size() const { return m_size; }
104
105     T& at(size_t i)
106     {
107         // Note that although it is a size_t, m_size is now guaranteed to be
108         // no greater than max unsigned. This guarantee is enforced in allocate().
109         ASSERT_WITH_SECURITY_IMPLICATION(i < size());
110         return data()[i];
111     }
112
113     T& operator[](size_t i) { return at(i); }
114
115     void zero()
116     {
117         // This multiplication is made safe by the check in allocate().
118         memset(this->data(), 0, sizeof(T) * this->size());
119     }
120
121     void zeroRange(unsigned start, unsigned end)
122     {
123         bool isSafe = (start <= end) && (end <= this->size());
124         ASSERT(isSafe);
125         if (!isSafe)
126             return;
127
128         // This expression cannot overflow because end - start cannot be
129         // greater than m_size, which is safe due to the check in allocate().
130         memset(this->data() + start, 0, sizeof(T) * (end - start));
131     }
132
133     void copyToRange(const T* sourceData, unsigned start, unsigned end)
134     {
135         bool isSafe = (start <= end) && (end <= this->size());
136         ASSERT(isSafe);
137         if (!isSafe)
138             return;
139
140         // This expression cannot overflow because end - start cannot be
141         // greater than m_size, which is safe due to the check in allocate().
142         memcpy(this->data() + start, sourceData, sizeof(T) * (end - start));
143     }
144
145     template<typename MemoryObjectInfo>
146     void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
147     {
148         typename MemoryObjectInfo::ClassInfo info(memoryObjectInfo, this);
149         info.addRawBuffer(m_allocation, m_size * sizeof(T), "AudioArrayData", "allocation");
150         info.ignoreMember(m_alignedData);
151     }
152
153 private:
154     static T* alignedAddress(T* address, intptr_t alignment)
155     {
156         intptr_t value = reinterpret_cast<intptr_t>(address);
157         return reinterpret_cast<T*>((value + alignment - 1) & ~(alignment - 1));
158     }
159
160     T* m_allocation;
161     T* m_alignedData;
162     size_t m_size;
163 };
164
165 typedef AudioArray<float> AudioFloatArray;
166 typedef AudioArray<double> AudioDoubleArray;
167
168 } // WebCore
169
170 #endif // AudioArray_h