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