]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/ArrayBufferView.h
JavaScriptCore-7601.1.46.3.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 byte offset is size aligned.
81 static bool verifyByteOffsetAlignment(unsigned byteOffset, size_t size)
82 {
83 return !(byteOffset & (size - 1));
84 }
85
86 // Helper to verify that a given sub-range of an ArrayBuffer is
87 // within range.
88 static bool verifySubRangeLength(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned numElements, size_t size)
89 {
90 unsigned byteLength = buffer->byteLength();
91 if (byteOffset > byteLength)
92 return false;
93 unsigned remainingElements = (byteLength - byteOffset) / size;
94 if (numElements > remainingElements)
95 return false;
96 return true;
97 }
98
99 virtual JSArrayBufferView* wrap(ExecState*, JSGlobalObject*) = 0;
100
101 protected:
102 JS_EXPORT_PRIVATE ArrayBufferView(PassRefPtr<ArrayBuffer>, unsigned byteOffset);
103
104 inline bool setImpl(ArrayBufferView*, unsigned byteOffset);
105
106 inline bool setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset);
107
108 inline bool zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength);
109
110 static inline void calculateOffsetAndLength(
111 int start, int end, unsigned arraySize,
112 unsigned* offset, unsigned* length);
113
114 // Input offset is in number of elements from this array's view;
115 // output offset is in number of bytes from the underlying buffer's view.
116 template <typename T>
117 static void clampOffsetAndNumElements(
118 PassRefPtr<ArrayBuffer> buffer,
119 unsigned arrayByteOffset,
120 unsigned *offset,
121 unsigned *numElements)
122 {
123 unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T);
124 if (*offset > maxOffset) {
125 *offset = buffer->byteLength();
126 *numElements = 0;
127 return;
128 }
129 *offset = arrayByteOffset + *offset * sizeof(T);
130 *offset = std::min(buffer->byteLength(), *offset);
131 unsigned remainingElements = (buffer->byteLength() - *offset) / sizeof(T);
132 *numElements = std::min(remainingElements, *numElements);
133 }
134
135 // This is the address of the ArrayBuffer's storage, plus the byte offset.
136 void* m_baseAddress;
137
138 unsigned m_byteOffset : 31;
139 bool m_isNeuterable : 1;
140
141 private:
142 friend class ArrayBuffer;
143 RefPtr<ArrayBuffer> m_buffer;
144 };
145
146 bool ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset)
147 {
148 if (byteOffset > byteLength()
149 || byteOffset + array->byteLength() > byteLength()
150 || byteOffset + array->byteLength() < byteOffset) {
151 // Out of range offset or overflow
152 return false;
153 }
154
155 char* base = static_cast<char*>(baseAddress());
156 memmove(base + byteOffset, array->baseAddress(), array->byteLength());
157 return true;
158 }
159
160 bool ArrayBufferView::setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset)
161 {
162 if (byteOffset > byteLength()
163 || byteOffset + dataByteLength > byteLength()
164 || byteOffset + dataByteLength < byteOffset) {
165 // Out of range offset or overflow
166 return false;
167 }
168
169 char* base = static_cast<char*>(baseAddress());
170 memmove(base + byteOffset, data, dataByteLength);
171 return true;
172 }
173
174 bool ArrayBufferView::zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength)
175 {
176 if (byteOffset > byteLength()
177 || byteOffset + rangeByteLength > byteLength()
178 || byteOffset + rangeByteLength < byteOffset) {
179 // Out of range offset or overflow
180 return false;
181 }
182
183 char* base = static_cast<char*>(baseAddress());
184 memset(base + byteOffset, 0, rangeByteLength);
185 return true;
186 }
187
188 void ArrayBufferView::calculateOffsetAndLength(
189 int start, int end, unsigned arraySize, unsigned* offset, unsigned* length)
190 {
191 if (start < 0)
192 start += arraySize;
193 if (start < 0)
194 start = 0;
195 if (end < 0)
196 end += arraySize;
197 if (end < 0)
198 end = 0;
199 if (static_cast<unsigned>(end) > arraySize)
200 end = arraySize;
201 if (end < start)
202 end = start;
203 *offset = static_cast<unsigned>(start);
204 *length = static_cast<unsigned>(end - start);
205 }
206
207 } // namespace JSC
208
209 using JSC::ArrayBufferView;
210
211 #endif // ArrayBufferView_h