Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / canvas / DataView.cpp
1 /*
2  * Copyright (C) 2010 Google 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "core/html/canvas/DataView.h"
28
29 #include "bindings/core/v8/ExceptionState.h"
30 #include "core/dom/ExceptionCode.h"
31 #include "platform/CheckedInt.h"
32 #include "wtf/CPU.h"
33
34 namespace {
35
36 template<typename T>
37 union Value {
38     T data;
39     char bytes[sizeof(T)];
40 };
41
42 }
43
44 namespace blink {
45
46 PassRefPtr<DataView> DataView::create(unsigned length)
47 {
48     RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(length, sizeof(uint8_t));
49     if (!buffer.get())
50         return nullptr;
51     return create(buffer, 0, length);
52 }
53
54 PassRefPtr<DataView> DataView::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned byteLength)
55 {
56     if (byteOffset > buffer->byteLength())
57         return nullptr;
58     CheckedInt<uint32_t> checkedOffset(byteOffset);
59     CheckedInt<uint32_t> checkedLength(byteLength);
60     CheckedInt<uint32_t> checkedMax = checkedOffset + checkedLength;
61     if (!checkedMax.isValid() || checkedMax.value() > buffer->byteLength())
62         return nullptr;
63     return adoptRef(new DataView(buffer, byteOffset, byteLength));
64 }
65
66 DataView::DataView(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned byteLength)
67     : ArrayBufferView(buffer, byteOffset)
68     , m_byteLength(byteLength)
69 {
70 }
71
72 static bool needToFlipBytes(bool littleEndian)
73 {
74 #if CPU(BIG_ENDIAN)
75     return littleEndian;
76 #else
77     return !littleEndian;
78 #endif
79 }
80
81 inline void swapBytes(char* p, char* q)
82 {
83     char temp = *p;
84     *p = *q;
85     *q = temp;
86 }
87
88 static void flipBytesFor16Bits(char* p)
89 {
90     swapBytes(p, p + 1);
91 }
92
93 static void flipBytesFor32Bits(char* p)
94 {
95     swapBytes(p, p + 3);
96     swapBytes(p + 1, p + 2);
97 }
98
99 static void flipBytesFor64Bits(char* p)
100 {
101     swapBytes(p, p + 7);
102     swapBytes(p + 1, p + 6);
103     swapBytes(p + 2, p + 5);
104     swapBytes(p + 3, p + 4);
105 }
106
107 static void flipBytesIfNeeded(char* value, size_t size, bool littleEndian)
108 {
109     if (!needToFlipBytes(littleEndian))
110         return;
111
112     switch (size) {
113     case 1:
114         // Nothing to do.
115         break;
116     case 2:
117         flipBytesFor16Bits(value);
118         break;
119     case 4:
120         flipBytesFor32Bits(value);
121         break;
122     case 8:
123         flipBytesFor64Bits(value);
124         break;
125     default:
126         ASSERT_NOT_REACHED();
127         break;
128     }
129 }
130
131 template<typename T>
132 T DataView::getData(unsigned byteOffset, bool littleEndian, ExceptionState& exceptionState) const
133 {
134     if (beyondRange<T>(byteOffset)) {
135         exceptionState.throwDOMException(IndexSizeError, "The provided offset (" + String::number(byteOffset) + ") is outside the allowed range.");
136         return 0;
137     }
138
139     // We do not want to load the data directly since it would cause a bus error on architectures that don't support unaligned loads.
140     Value<T> value;
141     memcpy(value.bytes, static_cast<const char*>(m_baseAddress) + byteOffset, sizeof(T));
142     flipBytesIfNeeded(value.bytes, sizeof(T), littleEndian);
143     return value.data;
144 }
145
146 template<typename T>
147 void DataView::setData(unsigned byteOffset, T value, bool littleEndian, ExceptionState& exceptionState)
148 {
149     if (beyondRange<T>(byteOffset)) {
150         exceptionState.throwDOMException(IndexSizeError, "The provided offset (" + String::number(byteOffset) + ") is outside the allowed range.");
151         return;
152     }
153
154     // We do not want to store the data directly since it would cause a bus error on architectures that don't support unaligned stores.
155     Value<T> tempValue;
156     tempValue.data = value;
157     flipBytesIfNeeded(tempValue.bytes, sizeof(T), littleEndian);
158     memcpy(static_cast<char*>(m_baseAddress) + byteOffset, tempValue.bytes, sizeof(T));
159 }
160
161 int8_t DataView::getInt8(unsigned byteOffset, ExceptionState& exceptionState)
162 {
163     return getData<int8_t>(byteOffset, false, exceptionState);
164 }
165
166 uint8_t DataView::getUint8(unsigned byteOffset, ExceptionState& exceptionState)
167 {
168     return getData<uint8_t>(byteOffset, false, exceptionState);
169 }
170
171 int16_t DataView::getInt16(unsigned byteOffset, bool littleEndian, ExceptionState& exceptionState)
172 {
173     return getData<int16_t>(byteOffset, littleEndian, exceptionState);
174 }
175
176 uint16_t DataView::getUint16(unsigned byteOffset, bool littleEndian, ExceptionState& exceptionState)
177 {
178     return getData<uint16_t>(byteOffset, littleEndian, exceptionState);
179 }
180
181 int32_t DataView::getInt32(unsigned byteOffset, bool littleEndian, ExceptionState& exceptionState)
182 {
183     return getData<int32_t>(byteOffset, littleEndian, exceptionState);
184 }
185
186 uint32_t DataView::getUint32(unsigned byteOffset, bool littleEndian, ExceptionState& exceptionState)
187 {
188     return getData<uint32_t>(byteOffset, littleEndian, exceptionState);
189 }
190
191 float DataView::getFloat32(unsigned byteOffset, bool littleEndian, ExceptionState& exceptionState)
192 {
193     return getData<float>(byteOffset, littleEndian, exceptionState);
194 }
195
196 double DataView::getFloat64(unsigned byteOffset, bool littleEndian, ExceptionState& exceptionState)
197 {
198     return getData<double>(byteOffset, littleEndian, exceptionState);
199 }
200
201 void DataView::setInt8(unsigned byteOffset, int8_t value, ExceptionState& exceptionState)
202 {
203     setData<int8_t>(byteOffset, value, false, exceptionState);
204 }
205
206 void DataView::setUint8(unsigned byteOffset, uint8_t value, ExceptionState& exceptionState)
207 {
208     setData<uint8_t>(byteOffset, value, false, exceptionState);
209 }
210
211 void DataView::setInt16(unsigned byteOffset, short value, bool littleEndian, ExceptionState& exceptionState)
212 {
213     setData<int16_t>(byteOffset, value, littleEndian, exceptionState);
214 }
215
216 void DataView::setUint16(unsigned byteOffset, uint16_t value, bool littleEndian, ExceptionState& exceptionState)
217 {
218     setData<uint16_t>(byteOffset, value, littleEndian, exceptionState);
219 }
220
221 void DataView::setInt32(unsigned byteOffset, int32_t value, bool littleEndian, ExceptionState& exceptionState)
222 {
223     setData<int32_t>(byteOffset, value, littleEndian, exceptionState);
224 }
225
226 void DataView::setUint32(unsigned byteOffset, uint32_t value, bool littleEndian, ExceptionState& exceptionState)
227 {
228     setData<uint32_t>(byteOffset, value, littleEndian, exceptionState);
229 }
230
231 void DataView::setFloat32(unsigned byteOffset, float value, bool littleEndian, ExceptionState& exceptionState)
232 {
233     setData<float>(byteOffset, value, littleEndian, exceptionState);
234 }
235
236 void DataView::setFloat64(unsigned byteOffset, double value, bool littleEndian, ExceptionState& exceptionState)
237 {
238     setData<double>(byteOffset, value, littleEndian, exceptionState);
239 }
240
241 void DataView::neuter()
242 {
243     ArrayBufferView::neuter();
244     m_byteLength = 0;
245 }
246
247 } // namespace blink