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