cmarrin@apple.com | 2461612 | 2009-09-08 13:01:34 +0000 | [diff] [blame] | 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 | |
kbr@google.com | 3706f9b | 2010-05-14 22:37:05 +0000 | [diff] [blame] | 26 | #ifndef ArrayBufferView_h |
| 27 | #define ArrayBufferView_h |
cmarrin@apple.com | 2461612 | 2009-09-08 13:01:34 +0000 | [diff] [blame] | 28 | |
eric@webkit.org | 3979f2d | 2012-03-07 08:50:54 +0000 | [diff] [blame] | 29 | #include <wtf/ArrayBuffer.h> |
kbr@google.com | af47200 | 2010-08-05 18:33:48 +0000 | [diff] [blame] | 30 | |
| 31 | #include <algorithm> |
antonm@chromium.org | 44bc467 | 2010-04-14 12:12:28 +0000 | [diff] [blame] | 32 | #include <limits.h> |
cmarrin@apple.com | 2461612 | 2009-09-08 13:01:34 +0000 | [diff] [blame] | 33 | #include <wtf/PassRefPtr.h> |
| 34 | #include <wtf/RefCounted.h> |
| 35 | #include <wtf/RefPtr.h> |
cmarrin@apple.com | 2461612 | 2009-09-08 13:01:34 +0000 | [diff] [blame] | 36 | |
oliver@apple.com | d05cffe | 2011-11-15 01:52:20 +0000 | [diff] [blame] | 37 | namespace WTF { |
adamk@chromium.org | 0471813 | 2011-11-09 01:51:35 +0000 | [diff] [blame] | 38 | |
kevino@webkit.org | 342534c | 2012-02-29 17:44:34 +0000 | [diff] [blame] | 39 | class WTF_EXPORT_PRIVATE_RTTI ArrayBufferView : public RefCounted<ArrayBufferView> { |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 40 | public: |
commit-queue@webkit.org | d8d6c69 | 2012-07-27 00:25:04 +0000 | [diff] [blame] | 41 | enum ViewType { |
| 42 | TypeInt8, |
| 43 | TypeUint8, |
| 44 | TypeUint8Clamped, |
| 45 | TypeInt16, |
| 46 | TypeUint16, |
| 47 | TypeInt32, |
| 48 | TypeUint32, |
| 49 | TypeFloat32, |
| 50 | TypeFloat64, |
| 51 | TypeDataView |
| 52 | }; |
| 53 | virtual ViewType getType() const = 0; |
cmarrin@apple.com | 2461612 | 2009-09-08 13:01:34 +0000 | [diff] [blame] | 54 | |
kbr@google.com | 3706f9b | 2010-05-14 22:37:05 +0000 | [diff] [blame] | 55 | PassRefPtr<ArrayBuffer> buffer() const |
kbr@google.com | b3ff644 | 2010-05-10 17:53:21 +0000 | [diff] [blame] | 56 | { |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 57 | return m_buffer; |
| 58 | } |
cmarrin@apple.com | 2461612 | 2009-09-08 13:01:34 +0000 | [diff] [blame] | 59 | |
kbr@google.com | b3ff644 | 2010-05-10 17:53:21 +0000 | [diff] [blame] | 60 | void* baseAddress() const |
| 61 | { |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 62 | return m_baseAddress; |
| 63 | } |
cmarrin@apple.com | 2461612 | 2009-09-08 13:01:34 +0000 | [diff] [blame] | 64 | |
kbr@google.com | b3ff644 | 2010-05-10 17:53:21 +0000 | [diff] [blame] | 65 | unsigned byteOffset() const |
| 66 | { |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 67 | return m_byteOffset; |
| 68 | } |
cmarrin@apple.com | 2461612 | 2009-09-08 13:01:34 +0000 | [diff] [blame] | 69 | |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 70 | virtual unsigned byteLength() const = 0; |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 71 | |
kevino@webkit.org | f19517d | 2012-03-29 19:22:02 +0000 | [diff] [blame] | 72 | WTF_EXPORT_PRIVATE_NO_RTTI virtual ~ArrayBufferView(); |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 73 | |
| 74 | protected: |
kevino@webkit.org | f19517d | 2012-03-29 19:22:02 +0000 | [diff] [blame] | 75 | WTF_EXPORT_PRIVATE_NO_RTTI ArrayBufferView(PassRefPtr<ArrayBuffer>, unsigned byteOffset); |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 76 | |
oliver@apple.com | 9ce01c6 | 2011-11-28 23:40:08 +0000 | [diff] [blame] | 77 | inline bool setImpl(ArrayBufferView*, unsigned byteOffset); |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 78 | |
oliver@apple.com | 9ce01c6 | 2011-11-28 23:40:08 +0000 | [diff] [blame] | 79 | inline bool setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset); |
crogers@google.com | 29d0a38 | 2010-09-09 22:22:17 +0000 | [diff] [blame] | 80 | |
oliver@apple.com | 9ce01c6 | 2011-11-28 23:40:08 +0000 | [diff] [blame] | 81 | inline bool zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength); |
crogers@google.com | 29d0a38 | 2010-09-09 22:22:17 +0000 | [diff] [blame] | 82 | |
oliver@apple.com | 9ce01c6 | 2011-11-28 23:40:08 +0000 | [diff] [blame] | 83 | static inline void calculateOffsetAndLength(int start, int end, unsigned arraySize, |
kbr@google.com | b3ff644 | 2010-05-10 17:53:21 +0000 | [diff] [blame] | 84 | unsigned* offset, unsigned* length); |
eric@webkit.org | cb99c71 | 2010-03-20 01:58:11 +0000 | [diff] [blame] | 85 | |
kbr@google.com | cb5a233 | 2010-03-01 21:20:31 +0000 | [diff] [blame] | 86 | // Helper to verify that a given sub-range of an ArrayBuffer is |
| 87 | // within range. |
| 88 | template <typename T> |
kbr@google.com | 3706f9b | 2010-05-14 22:37:05 +0000 | [diff] [blame] | 89 | static bool verifySubRange(PassRefPtr<ArrayBuffer> buffer, |
kbr@google.com | cb5a233 | 2010-03-01 21:20:31 +0000 | [diff] [blame] | 90 | unsigned byteOffset, |
| 91 | unsigned numElements) |
| 92 | { |
| 93 | if (!buffer) |
| 94 | return false; |
| 95 | if (sizeof(T) > 1 && byteOffset % sizeof(T)) |
| 96 | return false; |
| 97 | if (byteOffset > buffer->byteLength()) |
| 98 | return false; |
| 99 | unsigned remainingElements = (buffer->byteLength() - byteOffset) / sizeof(T); |
| 100 | if (numElements > remainingElements) |
| 101 | return false; |
| 102 | return true; |
| 103 | } |
| 104 | |
eric@webkit.org | c6e1e9b | 2010-04-14 05:29:23 +0000 | [diff] [blame] | 105 | // Input offset is in number of elements from this array's view; |
| 106 | // output offset is in number of bytes from the underlying buffer's view. |
kbr@google.com | cb5a233 | 2010-03-01 21:20:31 +0000 | [diff] [blame] | 107 | template <typename T> |
kbr@google.com | 3706f9b | 2010-05-14 22:37:05 +0000 | [diff] [blame] | 108 | static void clampOffsetAndNumElements(PassRefPtr<ArrayBuffer> buffer, |
eric@webkit.org | c6e1e9b | 2010-04-14 05:29:23 +0000 | [diff] [blame] | 109 | unsigned arrayByteOffset, |
| 110 | unsigned *offset, |
kbr@google.com | cb5a233 | 2010-03-01 21:20:31 +0000 | [diff] [blame] | 111 | unsigned *numElements) |
| 112 | { |
eric@webkit.org | c6e1e9b | 2010-04-14 05:29:23 +0000 | [diff] [blame] | 113 | unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T); |
| 114 | if (*offset > maxOffset) { |
| 115 | *offset = buffer->byteLength(); |
| 116 | *numElements = 0; |
| 117 | return; |
| 118 | } |
| 119 | *offset = arrayByteOffset + *offset * sizeof(T); |
| 120 | *offset = std::min(buffer->byteLength(), *offset); |
| 121 | unsigned remainingElements = (buffer->byteLength() - *offset) / sizeof(T); |
kbr@google.com | cb5a233 | 2010-03-01 21:20:31 +0000 | [diff] [blame] | 122 | *numElements = std::min(remainingElements, *numElements); |
| 123 | } |
| 124 | |
kevino@webkit.org | f19517d | 2012-03-29 19:22:02 +0000 | [diff] [blame] | 125 | WTF_EXPORT_PRIVATE_NO_RTTI virtual void neuter(); |
dslomov@google.com | 529e530 | 2011-11-04 21:43:56 +0000 | [diff] [blame] | 126 | |
kbr@google.com | 3706f9b | 2010-05-14 22:37:05 +0000 | [diff] [blame] | 127 | // This is the address of the ArrayBuffer's storage, plus the byte offset. |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 128 | void* m_baseAddress; |
| 129 | |
| 130 | unsigned m_byteOffset; |
| 131 | |
| 132 | private: |
dslomov@google.com | 529e530 | 2011-11-04 21:43:56 +0000 | [diff] [blame] | 133 | friend class ArrayBuffer; |
kbr@google.com | 3706f9b | 2010-05-14 22:37:05 +0000 | [diff] [blame] | 134 | RefPtr<ArrayBuffer> m_buffer; |
dslomov@google.com | 529e530 | 2011-11-04 21:43:56 +0000 | [diff] [blame] | 135 | ArrayBufferView* m_prevView; |
| 136 | ArrayBufferView* m_nextView; |
cmarrin@apple.com | a4ae328 | 2009-11-16 21:30:15 +0000 | [diff] [blame] | 137 | }; |
| 138 | |
oliver@apple.com | 9ce01c6 | 2011-11-28 23:40:08 +0000 | [diff] [blame] | 139 | bool ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset) |
| 140 | { |
| 141 | if (byteOffset > byteLength() |
| 142 | || byteOffset + array->byteLength() > byteLength() |
| 143 | || byteOffset + array->byteLength() < byteOffset) { |
| 144 | // Out of range offset or overflow |
| 145 | return false; |
| 146 | } |
| 147 | |
| 148 | char* base = static_cast<char*>(baseAddress()); |
| 149 | memmove(base + byteOffset, array->baseAddress(), array->byteLength()); |
| 150 | return true; |
| 151 | } |
| 152 | |
| 153 | bool ArrayBufferView::setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset) |
| 154 | { |
| 155 | if (byteOffset > byteLength() |
| 156 | || byteOffset + dataByteLength > byteLength() |
| 157 | || byteOffset + dataByteLength < byteOffset) { |
| 158 | // Out of range offset or overflow |
| 159 | return false; |
| 160 | } |
| 161 | |
| 162 | char* base = static_cast<char*>(baseAddress()); |
| 163 | memmove(base + byteOffset, data, dataByteLength); |
| 164 | return true; |
| 165 | } |
| 166 | |
| 167 | bool ArrayBufferView::zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength) |
| 168 | { |
| 169 | if (byteOffset > byteLength() |
| 170 | || byteOffset + rangeByteLength > byteLength() |
| 171 | || byteOffset + rangeByteLength < byteOffset) { |
| 172 | // Out of range offset or overflow |
| 173 | return false; |
| 174 | } |
| 175 | |
| 176 | char* base = static_cast<char*>(baseAddress()); |
| 177 | memset(base + byteOffset, 0, rangeByteLength); |
| 178 | return true; |
| 179 | } |
| 180 | |
| 181 | void ArrayBufferView::calculateOffsetAndLength(int start, int end, unsigned arraySize, |
| 182 | unsigned* offset, unsigned* length) |
| 183 | { |
| 184 | if (start < 0) |
| 185 | start += arraySize; |
| 186 | if (start < 0) |
| 187 | start = 0; |
| 188 | if (end < 0) |
| 189 | end += arraySize; |
| 190 | if (end < 0) |
| 191 | end = 0; |
commit-queue@webkit.org | b1da189 | 2012-03-06 15:30:51 +0000 | [diff] [blame] | 192 | if (static_cast<unsigned>(end) > arraySize) |
| 193 | end = arraySize; |
oliver@apple.com | 9ce01c6 | 2011-11-28 23:40:08 +0000 | [diff] [blame] | 194 | if (end < start) |
| 195 | end = start; |
| 196 | *offset = static_cast<unsigned>(start); |
| 197 | *length = static_cast<unsigned>(end - start); |
| 198 | } |
| 199 | |
oliver@apple.com | d05cffe | 2011-11-15 01:52:20 +0000 | [diff] [blame] | 200 | } // namespace WTF |
| 201 | |
| 202 | using WTF::ArrayBufferView; |
cmarrin@apple.com | 2461612 | 2009-09-08 13:01:34 +0000 | [diff] [blame] | 203 | |
kbr@google.com | 3706f9b | 2010-05-14 22:37:05 +0000 | [diff] [blame] | 204 | #endif // ArrayBufferView_h |