ac8e0d66c897671cf51e4c0f5169825e057eadb2
[WebKit-https.git] / Source / JavaScriptCore / runtime / TypedArrayAdaptors.h
1 /*
2  * Copyright (C) 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 TypedArrayAdaptors_h
27 #define TypedArrayAdaptors_h
28
29 #include "JSCJSValue.h"
30 #include "TypedArrayType.h"
31 #include <wtf/MathExtras.h>
32
33 namespace JSC {
34
35 template<
36     typename TypeArg, typename ViewTypeArg, typename JSViewTypeArg,
37     TypedArrayType typeValueArg>
38 struct IntegralTypedArrayAdaptor {
39     typedef TypeArg Type;
40     typedef ViewTypeArg ViewType;
41     typedef JSViewTypeArg JSViewType;
42     static const TypedArrayType typeValue = typeValueArg;
43     constexpr static const TypeArg minValue = std::numeric_limits<TypeArg>::lowest();
44     constexpr static const TypeArg maxValue = std::numeric_limits<TypeArg>::max();
45
46     static JSValue toJSValue(Type value)
47     {
48         return jsNumber(value);
49     }
50     
51     static double toDouble(Type value)
52     {
53         return static_cast<double>(value);
54     }
55     
56     static Type toNativeFromInt32(int32_t value)
57     {
58         return static_cast<Type>(value);
59     }
60     
61     static Type toNativeFromUint32(uint32_t value)
62     {
63         return static_cast<Type>(value);
64     }
65     
66     static Type toNativeFromDouble(double value)
67     {
68         int32_t result = static_cast<int32_t>(value);
69         if (static_cast<double>(result) != value)
70             result = toInt32(value);
71         return static_cast<Type>(result);
72     }
73     
74     template<typename OtherAdaptor>
75     static typename OtherAdaptor::Type convertTo(Type value)
76     {
77         if (typeValue == TypeUint32)
78             return OtherAdaptor::toNativeFromUint32(value);
79         return OtherAdaptor::toNativeFromInt32(value);
80     }
81
82     static bool toNativeFromInt32(int32_t value, Type& result)
83     {
84         if ((value >= 0 && static_cast<uint32_t>(value) > static_cast<uint32_t>(maxValue)) || value < static_cast<int32_t>(minValue))
85             return false;
86
87         result = static_cast<Type>(value);
88
89         return true;
90     }
91
92     static bool toNativeFromUint32(uint32_t value, Type& result)
93     {
94         if (value > static_cast<uint32_t>(maxValue))
95             return false;
96
97         result = static_cast<Type>(value);
98
99         return true;
100     }
101
102     static bool toNativeFromDouble(double value, Type& result)
103     {
104         Type integer = static_cast<Type>(value);
105         if (static_cast<double>(integer) != value)
106             return false;
107
108         if (value < 0)
109             return toNativeFromInt32(static_cast<int32_t>(value), result);
110         
111         return toNativeFromUint32(static_cast<uint32_t>(value), result);
112     }
113 };
114
115 template<
116     typename TypeArg, typename ViewTypeArg, typename JSViewTypeArg,
117     TypedArrayType typeValueArg>
118 struct FloatTypedArrayAdaptor {
119     typedef TypeArg Type;
120     typedef ViewTypeArg ViewType;
121     typedef JSViewTypeArg JSViewType;
122     static const TypedArrayType typeValue = typeValueArg;
123     constexpr static const TypeArg minValue = std::numeric_limits<TypeArg>::lowest();
124     constexpr static const TypeArg maxValue = std::numeric_limits<TypeArg>::max();
125
126     static JSValue toJSValue(Type value)
127     {
128         return jsDoubleNumber(purifyNaN(value));
129     }
130
131     static double toDouble(Type value)
132     {
133         return static_cast<double>(value);
134     }
135
136     static Type toNativeFromInt32(int32_t value)
137     {
138         return static_cast<Type>(value);
139     }
140
141     static Type toNativeFromUint32(uint32_t value)
142     {
143         return static_cast<Type>(value);
144     }
145
146     static Type toNativeFromDouble(double value)
147     {
148         return static_cast<Type>(value);
149     }
150
151     template<typename OtherAdaptor>
152     static typename OtherAdaptor::Type convertTo(Type value)
153     {
154         return OtherAdaptor::toNativeFromDouble(value);
155     }
156
157     static bool toNativeFromInt32(int32_t value, Type& result)
158     {
159         result = static_cast<Type>(value);
160         return true;
161     }
162
163     static Type toNativeFromDouble(double value, Type& result)
164     {
165         if (std::isnan(value) || std::isinf(value)) {
166             result = static_cast<Type>(value);
167             return true;
168         }
169
170         Type valueResult = static_cast<Type>(value);
171
172         if (static_cast<double>(valueResult) != value)
173             return false;
174
175         if (value < minValue || value > maxValue)
176             return false;
177
178         result = valueResult;
179         return true;
180     }
181 };
182
183 struct Int8Adaptor;
184 struct Int16Adaptor;
185 struct Int32Adaptor;
186 struct Uint8Adaptor;
187 struct Uint8ClampedAdaptor;
188 struct Uint16Adaptor;
189 struct Uint32Adaptor;
190 struct Float32Adaptor;
191 struct Float64Adaptor;
192
193 template<typename Adaptor> class GenericTypedArrayView;
194 typedef GenericTypedArrayView<Int8Adaptor> Int8Array;
195 typedef GenericTypedArrayView<Int16Adaptor> Int16Array;
196 typedef GenericTypedArrayView<Int32Adaptor> Int32Array;
197 typedef GenericTypedArrayView<Uint8Adaptor> Uint8Array;
198 typedef GenericTypedArrayView<Uint8ClampedAdaptor> Uint8ClampedArray;
199 typedef GenericTypedArrayView<Uint16Adaptor> Uint16Array;
200 typedef GenericTypedArrayView<Uint32Adaptor> Uint32Array;
201 typedef GenericTypedArrayView<Float32Adaptor> Float32Array;
202 typedef GenericTypedArrayView<Float64Adaptor> Float64Array;
203
204 template<typename Adaptor> class JSGenericTypedArrayView;
205 typedef JSGenericTypedArrayView<Int8Adaptor> JSInt8Array;
206 typedef JSGenericTypedArrayView<Int16Adaptor> JSInt16Array;
207 typedef JSGenericTypedArrayView<Int32Adaptor> JSInt32Array;
208 typedef JSGenericTypedArrayView<Uint8Adaptor> JSUint8Array;
209 typedef JSGenericTypedArrayView<Uint8ClampedAdaptor> JSUint8ClampedArray;
210 typedef JSGenericTypedArrayView<Uint16Adaptor> JSUint16Array;
211 typedef JSGenericTypedArrayView<Uint32Adaptor> JSUint32Array;
212 typedef JSGenericTypedArrayView<Float32Adaptor> JSFloat32Array;
213 typedef JSGenericTypedArrayView<Float64Adaptor> JSFloat64Array;
214
215 struct Int8Adaptor : IntegralTypedArrayAdaptor<int8_t, Int8Array, JSInt8Array, TypeInt8> { };
216 struct Int16Adaptor : IntegralTypedArrayAdaptor<int16_t, Int16Array, JSInt16Array, TypeInt16> { };
217 struct Int32Adaptor : IntegralTypedArrayAdaptor<int32_t, Int32Array, JSInt32Array, TypeInt32> { };
218 struct Uint8Adaptor : IntegralTypedArrayAdaptor<uint8_t, Uint8Array, JSUint8Array, TypeUint8> { };
219 struct Uint16Adaptor : IntegralTypedArrayAdaptor<uint16_t, Uint16Array, JSUint16Array, TypeUint16> { };
220 struct Uint32Adaptor : IntegralTypedArrayAdaptor<uint32_t, Uint32Array, JSUint32Array, TypeUint32> { };
221 struct Float32Adaptor : FloatTypedArrayAdaptor<float, Float32Array, JSFloat32Array, TypeFloat32> { };
222 struct Float64Adaptor : FloatTypedArrayAdaptor<double, Float64Array, JSFloat64Array, TypeFloat64> { };
223
224 struct Uint8ClampedAdaptor {
225     typedef uint8_t Type;
226     typedef Uint8ClampedArray ViewType;
227     typedef JSUint8ClampedArray JSViewType;
228     static const TypedArrayType typeValue = TypeUint8Clamped;
229     constexpr static const uint8_t minValue = std::numeric_limits<uint8_t>::lowest();
230     constexpr static const uint8_t maxValue = std::numeric_limits<uint8_t>::max();
231
232     static JSValue toJSValue(uint8_t value)
233     {
234         return jsNumber(value);
235     }
236
237     static double toDouble(uint8_t value)
238     {
239         return static_cast<double>(value);
240     }
241
242     static Type toNativeFromInt32(int32_t value)
243     {
244         return clamp(value);
245     }
246
247     static Type toNativeFromUint32(uint32_t value)
248     {
249         return std::min(static_cast<uint32_t>(255), value);
250     }
251
252     static Type toNativeFromDouble(double value)
253     {
254         if (std::isnan(value) || value < 0)
255             return 0;
256         if (value > 255)
257             return 255;
258         return static_cast<uint8_t>(lrint(value));
259     }
260
261     template<typename OtherAdaptor>
262     static typename OtherAdaptor::Type convertTo(uint8_t value)
263     {
264         return OtherAdaptor::toNativeFromInt32(value);
265     }
266     
267     static bool toNativeFromInt32(int32_t value, Type& result)
268     {
269         if (value > maxValue || value < minValue)
270             return false;
271
272         result = static_cast<Type>(value);
273
274         return true;
275     }
276
277     static bool toNativeFromDouble(double value, uint8_t& result)
278     {
279         uint8_t integer = static_cast<uint8_t>(value);
280         if (static_cast<double>(integer) != value)
281             return false;
282
283         result = integer;
284         return true;
285     }
286
287 private:
288     static uint8_t clamp(int32_t value)
289     {
290         if (value < 0)
291             return 0;
292         if (value > 255)
293             return 255;
294         return static_cast<uint8_t>(value);
295     }
296 };
297
298 } // namespace JSC
299
300 #endif // TypedArrayAdaptors_h
301