]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/ArrayBufferView.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / runtime / ArrayBufferView.h
1 /*
2 * Copyright (C) 2009, 2013 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 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 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 ArrayBufferView_h
27 #define ArrayBufferView_h
28
29 #include "ArrayBuffer.h"
30 #include "TypedArrayType.h"
31 #include <algorithm>
32 #include <limits.h>
33 #include <wtf/PassRefPtr.h>
34 #include <wtf/RefCounted.h>
35 #include <wtf/RefPtr.h>
36
37 namespace JSC {
38
39 class JSArrayBufferView;
40 class JSGlobalObject;
41 class ExecState;
42
43 class ArrayBufferView : public RefCounted<ArrayBufferView> {
44 public:
45 virtual TypedArrayType getType() const = 0;
46
47 bool isNeutered() const
48 {
49 return !m_buffer || m_buffer->isNeutered();
50 }
51
52 PassRefPtr<ArrayBuffer> buffer() const
53 {
54 if (isNeutered())
55 return 0;
56 return m_buffer;
57 }
58
59 void* baseAddress() const
60 {
61 if (isNeutered())
62 return 0;
63 return m_baseAddress;
64 }
65
66 unsigned byteOffset() const
67 {
68 if (isNeutered())
69 return 0;
70 return m_byteOffset;
71 }
72
73 virtual unsigned byteLength() const = 0;
74
75 JS_EXPORT_PRIVATE void setNeuterable(bool flag);
76 bool isNeuterable() const { return m_isNeuterable; }
77
78 JS_EXPORT_PRIVATE virtual ~ArrayBufferView();
79
80 // Helper to verify that a given sub-range of an ArrayBuffer is
81 // within range.
82 // FIXME: This should distinguish between alignment errors and bounds errors.
83 // https://bugs.webkit.org/show_bug.cgi?id=125391
84 template <typename T>
85 static bool verifySubRange(
86 PassRefPtr<ArrayBuffer> buffer,
87 unsigned byteOffset,
88 unsigned numElements)
89 {
90 unsigned byteLength = buffer->byteLength();
91 if (sizeof(T) > 1 && byteOffset % sizeof(T))
92 return false;
93 if (byteOffset > byteLength)
94 return false;
95 unsigned remainingElements = (byteLength - byteOffset) / sizeof(T);
96 if (numElements > remainingElements)
97 return false;
98 return true;
99 }
100
101 virtual JSArrayBufferView* wrap(ExecState*, JSGlobalObject*) = 0;
102
103 protected:
104 JS_EXPORT_PRIVATE ArrayBufferView(PassRefPtr<ArrayBuffer>, unsigned byteOffset);
105
106 inline bool setImpl(ArrayBufferView*, unsigned byteOffset);
107
108 inline bool setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset);
109
110 inline bool zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength);
111
112 static inline void calculateOffsetAndLength(
113 int start, int end, unsigned arraySize,
114 unsigned* offset, unsigned* length);
115
116 // Input offset is in number of elements from this array's view;
117 // output offset is in number of bytes from the underlying buffer's view.
118 template <typename T>
119 static void clampOffsetAndNumElements(
120 PassRefPtr<ArrayBuffer> buffer,
121 unsigned arrayByteOffset,
122 unsigned *offset,
123 unsigned *numElements)
124 {
125 unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T);
126 if (*offset > maxOffset) {
127 *offset = buffer->byteLength();
128 *numElements = 0;
129 return;
130 }
131 *offset = arrayByteOffset + *offset * sizeof(T);
132 *offset = std::min(buffer->byteLength(), *offset);
133 unsigned remainingElements = (buffer->byteLength() - *offset) / sizeof(T);
134 *numElements = std::min(remainingElements, *numElements);
135 }
136
137 // This is the address of the ArrayBuffer's storage, plus the byte offset.
138 void* m_baseAddress;
139
140 unsigned m_byteOffset : 31;
141 bool m_isNeuterable : 1;
142
143 private:
144 friend class ArrayBuffer;
145 RefPtr<ArrayBuffer> m_buffer;
146 };
147
148 bool ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset)
149 {
150 if (byteOffset > byteLength()
151 || byteOffset + array->byteLength() > byteLength()
152 || byteOffset + array->byteLength() < byteOffset) {
153 // Out of range offset or overflow
154 return false;
155 }
156
157 char* base = static_cast<char*>(baseAddress());
158 memmove(base + byteOffset, array->baseAddress(), array->byteLength());
159 return true;
160 }
161
162 bool ArrayBufferView::setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset)
163 {
164 if (byteOffset > byteLength()
165 || byteOffset + dataByteLength > byteLength()
166 || byteOffset + dataByteLength < byteOffset) {
167 // Out of range offset or overflow
168 return false;
169 }
170
171 char* base = static_cast<char*>(baseAddress());
172 memmove(base + byteOffset, data, dataByteLength);
173 return true;
174 }
175
176 bool ArrayBufferView::zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength)
177 {
178 if (byteOffset > byteLength()
179 || byteOffset + rangeByteLength > byteLength()
180 || byteOffset + rangeByteLength < byteOffset) {
181 // Out of range offset or overflow
182 return false;
183 }
184
185 char* base = static_cast<char*>(baseAddress());
186 memset(base + byteOffset, 0, rangeByteLength);
187 return true;
188 }
189
190 void ArrayBufferView::calculateOffsetAndLength(
191 int start, int end, unsigned arraySize, unsigned* offset, unsigned* length)
192 {
193 if (start < 0)
194 start += arraySize;
195 if (start < 0)
196 start = 0;
197 if (end < 0)
198 end += arraySize;
199 if (end < 0)
200 end = 0;
201 if (static_cast<unsigned>(end) > arraySize)
202 end = arraySize;
203 if (end < start)
204 end = start;
205 *offset = static_cast<unsigned>(start);
206 *length = static_cast<unsigned>(end - start);
207 }
208
209 } // namespace JSC
210
211 using JSC::ArrayBufferView;
212
213 #endif // ArrayBufferView_h