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