Merge "Fix build break by removing TIZEN_RECORDING_SURFACE_SET" into tizen_2.1
[framework/web/webkit-efl.git] / Source / WTF / wtf / ArrayBuffer.h
1 /*
2  * Copyright (C) 2009 Apple 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef ArrayBuffer_h
27 #define ArrayBuffer_h
28
29 #include <wtf/HashSet.h>
30 #include <wtf/PassRefPtr.h>
31 #include <wtf/RefCounted.h>
32 #include <wtf/Vector.h>
33
34 namespace WTF {
35
36 class ArrayBuffer;
37 class ArrayBufferView;
38
39 class ArrayBufferContents {
40     WTF_MAKE_NONCOPYABLE(ArrayBufferContents);
41 public:
42     ArrayBufferContents() 
43         : m_data(0)
44         , m_sizeInBytes(0)
45     { }
46
47     inline ~ArrayBufferContents();
48
49     void* data() { return m_data; }
50     unsigned sizeInBytes() { return m_sizeInBytes; }
51
52 private:
53     ArrayBufferContents(void* data, unsigned sizeInBytes) 
54         : m_data(data)
55         , m_sizeInBytes(sizeInBytes)
56     { }
57
58     friend class ArrayBuffer;
59
60     enum InitializationPolicy {
61         ZeroInitialize,
62         DontInitialize
63     };
64
65     static inline void tryAllocate(unsigned numElements, unsigned elementByteSize, InitializationPolicy, ArrayBufferContents&);
66     void transfer(ArrayBufferContents& other)
67     {
68         ASSERT(!other.m_data);
69         other.m_data = m_data;
70         other.m_sizeInBytes = m_sizeInBytes;
71         m_data = 0;
72         m_sizeInBytes = 0;
73     }
74
75     void* m_data;
76     unsigned m_sizeInBytes;
77 };
78
79 class ArrayBuffer : public RefCounted<ArrayBuffer> {
80 public:
81     static inline PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize);
82     static inline PassRefPtr<ArrayBuffer> create(ArrayBuffer*);
83     static inline PassRefPtr<ArrayBuffer> create(const void* source, unsigned byteLength);
84     static inline PassRefPtr<ArrayBuffer> create(ArrayBufferContents&);
85
86     // Only for use by Uint8ClampedArray::createUninitialized.
87     static inline PassRefPtr<ArrayBuffer> createUninitialized(unsigned numElements, unsigned elementByteSize);
88
89     inline void* data();
90     inline const void* data() const;
91     inline unsigned byteLength() const;
92
93     inline PassRefPtr<ArrayBuffer> slice(int begin, int end) const;
94     inline PassRefPtr<ArrayBuffer> slice(int begin) const;
95
96     void addView(ArrayBufferView*);
97     void removeView(ArrayBufferView*);
98
99     WTF_EXPORT_PRIVATE bool transfer(ArrayBufferContents&, Vector<RefPtr<ArrayBufferView> >& neuteredViews);
100     bool isNeutered() { return !m_contents.m_data; }
101
102     ~ArrayBuffer() { }
103
104 private:
105     static inline PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
106
107     inline ArrayBuffer(ArrayBufferContents&);
108     inline PassRefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const;
109     inline unsigned clampIndex(int index) const;
110     static inline int clampValue(int x, int left, int right);
111
112     ArrayBufferContents m_contents;
113     ArrayBufferView* m_firstView;
114 };
115
116 int ArrayBuffer::clampValue(int x, int left, int right)
117 {
118     ASSERT(left <= right);
119     if (x < left)
120         x = left;
121     if (right < x)
122         x = right;
123     return x;
124 }
125
126 PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize)
127 {
128     return create(numElements, elementByteSize, ArrayBufferContents::ZeroInitialize);
129 }
130
131 PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBuffer* other)
132 {
133     return ArrayBuffer::create(other->data(), other->byteLength());
134 }
135
136 PassRefPtr<ArrayBuffer> ArrayBuffer::create(const void* source, unsigned byteLength)
137 {
138     ArrayBufferContents contents;
139     ArrayBufferContents::tryAllocate(byteLength, 1, ArrayBufferContents::ZeroInitialize, contents);
140     if (!contents.m_data)
141         return 0;
142     RefPtr<ArrayBuffer> buffer = adoptRef(new ArrayBuffer(contents));
143     memcpy(buffer->data(), source, byteLength);
144     return buffer.release();
145 }
146
147 PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBufferContents& contents)
148 {
149     return adoptRef(new ArrayBuffer(contents));
150 }
151
152 PassRefPtr<ArrayBuffer> ArrayBuffer::createUninitialized(unsigned numElements, unsigned elementByteSize)
153 {
154     return create(numElements, elementByteSize, ArrayBufferContents::DontInitialize);
155 }
156
157 PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
158 {
159     ArrayBufferContents contents;
160     ArrayBufferContents::tryAllocate(numElements, elementByteSize, policy, contents);
161     if (!contents.m_data)
162         return 0;
163     return adoptRef(new ArrayBuffer(contents));
164 }
165
166 ArrayBuffer::ArrayBuffer(ArrayBufferContents& contents)
167     : m_firstView(0)
168 {
169     contents.transfer(m_contents);
170 }
171
172 void* ArrayBuffer::data()
173 {
174     return m_contents.m_data;
175 }
176
177 const void* ArrayBuffer::data() const
178 {
179     return m_contents.m_data;
180 }
181
182 unsigned ArrayBuffer::byteLength() const
183 {
184     return m_contents.m_sizeInBytes;
185 }
186
187 PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin, int end) const
188 {
189     return sliceImpl(clampIndex(begin), clampIndex(end));
190 }
191
192 PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin) const
193 {
194     return sliceImpl(clampIndex(begin), byteLength());
195 }
196
197 PassRefPtr<ArrayBuffer> ArrayBuffer::sliceImpl(unsigned begin, unsigned end) const
198 {
199     unsigned size = begin <= end ? end - begin : 0;
200     return ArrayBuffer::create(static_cast<const char*>(data()) + begin, size);
201 }
202
203 unsigned ArrayBuffer::clampIndex(int index) const
204 {
205     unsigned currentLength = byteLength();
206     if (index < 0)
207         index = currentLength + index;
208     return clampValue(index, 0, currentLength);
209 }
210
211 void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy, ArrayBufferContents& result)
212 {
213     // Do not allow 32-bit overflow of the total size.
214     // FIXME: Why not? The tryFastCalloc function already checks its arguments,
215     // and will fail if there is any overflow, so why should we include a
216     // redudant unnecessarily restrictive check here?
217     if (numElements) {
218         unsigned totalSize = numElements * elementByteSize;
219         if (totalSize / numElements != elementByteSize) {
220             result.m_data = 0;
221             return;
222         }
223     }
224     bool allocationSucceeded = false;
225     if (policy == ZeroInitialize)
226         allocationSucceeded = WTF::tryFastCalloc(numElements, elementByteSize).getValue(result.m_data);
227     else {
228         ASSERT(policy == DontInitialize);
229         allocationSucceeded = WTF::tryFastMalloc(numElements * elementByteSize).getValue(result.m_data);
230     }
231
232     if (allocationSucceeded) {
233         result.m_sizeInBytes = numElements * elementByteSize;
234         return;
235     }
236     result.m_data = 0;
237 }
238
239 ArrayBufferContents::~ArrayBufferContents()
240 {
241     WTF::fastFree(m_data);
242 }
243
244 } // namespace WTF
245
246 using WTF::ArrayBuffer;
247
248 #endif // ArrayBuffer_h