1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci#include <math.h> 17425bb815Sopenharmony_ci 18425bb815Sopenharmony_ci#include "ecma-globals.h" 19425bb815Sopenharmony_ci#include "ecma-helpers.h" 20425bb815Sopenharmony_ci#include "jrt-libc-includes.h" 21425bb815Sopenharmony_ci#include "lit-char-helpers.h" 22425bb815Sopenharmony_ci#include "lit-magic-strings.h" 23425bb815Sopenharmony_ci 24425bb815Sopenharmony_ci/** \addtogroup ecma ECMA 25425bb815Sopenharmony_ci * @{ 26425bb815Sopenharmony_ci * 27425bb815Sopenharmony_ci * \addtogroup ecmahelpers Helpers for operations with ECMA data types 28425bb815Sopenharmony_ci * @{ 29425bb815Sopenharmony_ci */ 30425bb815Sopenharmony_ci 31425bb815Sopenharmony_ci#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) 32425bb815Sopenharmony_ci 33425bb815Sopenharmony_ci/** 34425bb815Sopenharmony_ci * \addtogroup ecmahelpersbigintegers Helpers for operations intermediate 128-bit integers 35425bb815Sopenharmony_ci * @{ 36425bb815Sopenharmony_ci */ 37425bb815Sopenharmony_ci 38425bb815Sopenharmony_ci/** 39425bb815Sopenharmony_ci * 128-bit integer type 40425bb815Sopenharmony_ci */ 41425bb815Sopenharmony_citypedef struct 42425bb815Sopenharmony_ci{ 43425bb815Sopenharmony_ci uint64_t lo; /**< low 64 bits */ 44425bb815Sopenharmony_ci uint64_t hi; /**< high 64 bits */ 45425bb815Sopenharmony_ci} ecma_uint128_t; 46425bb815Sopenharmony_ci 47425bb815Sopenharmony_ci/** 48425bb815Sopenharmony_ci * Round high part of 128-bit integer to uint64_t 49425bb815Sopenharmony_ci * 50425bb815Sopenharmony_ci * @return rounded high to uint64_t 51425bb815Sopenharmony_ci */ 52425bb815Sopenharmony_cistatic uint64_t 53425bb815Sopenharmony_ciecma_round_high_to_uint64 (ecma_uint128_t *num_p) 54425bb815Sopenharmony_ci{ 55425bb815Sopenharmony_ci uint64_t masked_lo = num_p->lo & ~(1ULL << 63u); 56425bb815Sopenharmony_ci uint64_t masked_hi = num_p->hi & 0x1; 57425bb815Sopenharmony_ci 58425bb815Sopenharmony_ci if ((num_p->lo >> 63u != 0) 59425bb815Sopenharmony_ci && (masked_lo > 0 || masked_hi != 0)) 60425bb815Sopenharmony_ci { 61425bb815Sopenharmony_ci return (num_p->hi + 1); 62425bb815Sopenharmony_ci } 63425bb815Sopenharmony_ci return num_p->hi; 64425bb815Sopenharmony_ci} /* ecma_round_high_to_uint64 */ 65425bb815Sopenharmony_ci 66425bb815Sopenharmony_ci/** 67425bb815Sopenharmony_ci * Check if 128-bit integer is zero 68425bb815Sopenharmony_ci */ 69425bb815Sopenharmony_ci#define ECMA_UINT128_IS_ZERO(name) \ 70425bb815Sopenharmony_ci (name.hi == 0 && name.lo == 0) 71425bb815Sopenharmony_ci 72425bb815Sopenharmony_ci/** 73425bb815Sopenharmony_ci * Left shift 128-bit integer by max 63 bits 74425bb815Sopenharmony_ci */ 75425bb815Sopenharmony_ci#define ECMA_UINT128_LEFT_SHIFT_MAX63(name, shift) \ 76425bb815Sopenharmony_ci{ \ 77425bb815Sopenharmony_ci name.hi = (name.hi << (shift)) | (name.lo >> (64 - (shift))); \ 78425bb815Sopenharmony_ci name.lo <<= (shift); \ 79425bb815Sopenharmony_ci} 80425bb815Sopenharmony_ci 81425bb815Sopenharmony_ci/** 82425bb815Sopenharmony_ci * Right shift 128-bit integer by max 63 bits 83425bb815Sopenharmony_ci */ 84425bb815Sopenharmony_ci#define ECMA_UINT128_RIGHT_SHIFT_MAX63(name, shift) \ 85425bb815Sopenharmony_ci{ \ 86425bb815Sopenharmony_ci name.lo = (name.lo >> (shift)) | (name.hi << (64 - (shift))); \ 87425bb815Sopenharmony_ci name.hi >>= (shift); \ 88425bb815Sopenharmony_ci} 89425bb815Sopenharmony_ci 90425bb815Sopenharmony_ci/** 91425bb815Sopenharmony_ci * Add 128-bit integer 92425bb815Sopenharmony_ci */ 93425bb815Sopenharmony_ci#define ECMA_UINT128_ADD(name_add_to, name_to_add) \ 94425bb815Sopenharmony_ci{ \ 95425bb815Sopenharmony_ci name_add_to.hi += name_to_add.hi; \ 96425bb815Sopenharmony_ci name_add_to.lo += name_to_add.lo; \ 97425bb815Sopenharmony_ci if (name_add_to.lo < name_to_add.lo) \ 98425bb815Sopenharmony_ci { \ 99425bb815Sopenharmony_ci name_add_to.hi++; \ 100425bb815Sopenharmony_ci } \ 101425bb815Sopenharmony_ci} 102425bb815Sopenharmony_ci 103425bb815Sopenharmony_ci/** 104425bb815Sopenharmony_ci * Multiply 128-bit integer by 10 105425bb815Sopenharmony_ci */ 106425bb815Sopenharmony_ci#define ECMA_UINT128_MUL10(name) \ 107425bb815Sopenharmony_ci{ \ 108425bb815Sopenharmony_ci ECMA_UINT128_LEFT_SHIFT_MAX63 (name, 1u); \ 109425bb815Sopenharmony_ci \ 110425bb815Sopenharmony_ci ecma_uint128_t name ## _tmp = name; \ 111425bb815Sopenharmony_ci \ 112425bb815Sopenharmony_ci ECMA_UINT128_LEFT_SHIFT_MAX63 (name ## _tmp, 2u); \ 113425bb815Sopenharmony_ci \ 114425bb815Sopenharmony_ci ECMA_UINT128_ADD (name, name ## _tmp); \ 115425bb815Sopenharmony_ci} 116425bb815Sopenharmony_ci 117425bb815Sopenharmony_ci/** 118425bb815Sopenharmony_ci * Divide 128-bit integer by 10 119425bb815Sopenharmony_ci * 120425bb815Sopenharmony_ci * N = N3 *2^96 + N2 *2^64 + N1 *2^32 + N0 *2^0 // 128-bit dividend 121425bb815Sopenharmony_ci * T = T3 *2^-32 + T2 *2^-64 + T1 *2^-96 + T0 *2^-128 // 128-bit divisor reciprocal, 1/10 * 2^-128 122425bb815Sopenharmony_ci * 123425bb815Sopenharmony_ci * N * T = N3*T3 *2^64 + N2*T3 *2^32 + N1*T3 *2^0 + N0*T3 *2^-32 124425bb815Sopenharmony_ci * + N3*T2 *2^32 + N2*T2 *2^0 + N1*T2 *2^-32 + N0*T2 *2^-64 125425bb815Sopenharmony_ci * + N3*T1 *2^0 + N2*T1 *2^-32 + N1*T1 *2^-64 + N0*T1 *2^-96 126425bb815Sopenharmony_ci * + N3*T0 *2^-32 + N2*T0 *2^-64 + N1*T0 *2^-96 + N0*T0 *2^-128 127425bb815Sopenharmony_ci * 128425bb815Sopenharmony_ci * Q3=carry Q2=^+carry Q1=^+carry Q0=^+carry fraction=^... 129425bb815Sopenharmony_ci * 130425bb815Sopenharmony_ci * Q = Q3 *2^96 + Q2 *2^64 + Q1 *2^32 + Q0 *2^0 // 128-bit quotient 131425bb815Sopenharmony_ci */ 132425bb815Sopenharmony_ci#define ECMA_UINT128_DIV10(name) \ 133425bb815Sopenharmony_ci{ \ 134425bb815Sopenharmony_ci /* estimation of reciprocal of 10, 128 bits right of the binary point (T1 == T2) */ \ 135425bb815Sopenharmony_ci const uint64_t tenth_l = 0x9999999aul; \ 136425bb815Sopenharmony_ci const uint64_t tenth_m = 0x99999999ul; \ 137425bb815Sopenharmony_ci const uint64_t tenth_h = 0x19999999ul; \ 138425bb815Sopenharmony_ci \ 139425bb815Sopenharmony_ci uint64_t l0 = ((uint32_t) name.lo) * tenth_l; \ 140425bb815Sopenharmony_ci uint64_t l1 = (name.lo >> 32u) * tenth_l; \ 141425bb815Sopenharmony_ci uint64_t l2 = ((uint32_t) name.hi) * tenth_l; \ 142425bb815Sopenharmony_ci uint64_t l3 = (name.hi >> 32u) * tenth_l; \ 143425bb815Sopenharmony_ci uint64_t m0 = ((uint32_t) name.lo) * tenth_m; \ 144425bb815Sopenharmony_ci uint64_t m1 = (name.lo >> 32u) * tenth_m; \ 145425bb815Sopenharmony_ci uint64_t m2 = ((uint32_t) name.hi) * tenth_m; \ 146425bb815Sopenharmony_ci uint64_t m3 = (name.hi >> 32u) * tenth_m; \ 147425bb815Sopenharmony_ci uint64_t h0 = ((uint32_t) name.lo) * tenth_h; \ 148425bb815Sopenharmony_ci uint64_t h1 = (name.lo >> 32u) * tenth_h; \ 149425bb815Sopenharmony_ci uint64_t h2 = ((uint32_t) name.hi) * tenth_h; \ 150425bb815Sopenharmony_ci uint64_t h3 = (name.hi >> 32u) * tenth_h; \ 151425bb815Sopenharmony_ci \ 152425bb815Sopenharmony_ci uint64_t q0 = l0 >> 32u; \ 153425bb815Sopenharmony_ci q0 += (uint32_t) l1; \ 154425bb815Sopenharmony_ci q0 += (uint32_t) m0; \ 155425bb815Sopenharmony_ci \ 156425bb815Sopenharmony_ci q0 >>= 32u; \ 157425bb815Sopenharmony_ci q0 += l1 >> 32u; \ 158425bb815Sopenharmony_ci q0 += m0 >> 32u; \ 159425bb815Sopenharmony_ci q0 += (uint32_t) l2; \ 160425bb815Sopenharmony_ci q0 += (uint32_t) m1; \ 161425bb815Sopenharmony_ci q0 += (uint32_t) m0; \ 162425bb815Sopenharmony_ci \ 163425bb815Sopenharmony_ci q0 >>= 32u; \ 164425bb815Sopenharmony_ci q0 += l2 >> 32u; \ 165425bb815Sopenharmony_ci q0 += m1 >> 32u; \ 166425bb815Sopenharmony_ci q0 += m0 >> 32u; \ 167425bb815Sopenharmony_ci q0 += (uint32_t) l3; \ 168425bb815Sopenharmony_ci q0 += (uint32_t) m2; \ 169425bb815Sopenharmony_ci q0 += (uint32_t) m1; \ 170425bb815Sopenharmony_ci q0 += (uint32_t) h0; \ 171425bb815Sopenharmony_ci \ 172425bb815Sopenharmony_ci q0 >>=32u; \ 173425bb815Sopenharmony_ci q0 += l3 >> 32u; \ 174425bb815Sopenharmony_ci q0 += m2 >> 32u; \ 175425bb815Sopenharmony_ci q0 += m1 >> 32u; \ 176425bb815Sopenharmony_ci q0 += h0 >> 32u; \ 177425bb815Sopenharmony_ci q0 += (uint32_t) m3; \ 178425bb815Sopenharmony_ci q0 += (uint32_t) m2; \ 179425bb815Sopenharmony_ci q0 += (uint32_t) h1; \ 180425bb815Sopenharmony_ci \ 181425bb815Sopenharmony_ci uint64_t q1 = q0 >> 32u; \ 182425bb815Sopenharmony_ci q1 += m3 >> 32u; \ 183425bb815Sopenharmony_ci q1 += m2 >> 32u; \ 184425bb815Sopenharmony_ci q1 += h1 >> 32u; \ 185425bb815Sopenharmony_ci q1 += (uint32_t) m3; \ 186425bb815Sopenharmony_ci q1 += (uint32_t) h2; \ 187425bb815Sopenharmony_ci \ 188425bb815Sopenharmony_ci uint64_t q32 = q1 >> 32u; \ 189425bb815Sopenharmony_ci q32 += m3 >> 32u; \ 190425bb815Sopenharmony_ci q32 += h2 >> 32u; \ 191425bb815Sopenharmony_ci q32 += h3; \ 192425bb815Sopenharmony_ci \ 193425bb815Sopenharmony_ci name.lo = (q1 << 32u) | ((uint32_t) q0); \ 194425bb815Sopenharmony_ci name.hi = q32; \ 195425bb815Sopenharmony_ci} 196425bb815Sopenharmony_ci 197425bb815Sopenharmony_ci#if defined (__GNUC__) || defined (__clang__) 198425bb815Sopenharmony_ci 199425bb815Sopenharmony_ci/** 200425bb815Sopenharmony_ci * Count leading zeros in the topmost 64 bits of a 128-bit integer. 201425bb815Sopenharmony_ci */ 202425bb815Sopenharmony_ci#define ECMA_UINT128_CLZ_MAX63(name) \ 203425bb815Sopenharmony_ci __builtin_clzll (name.hi) 204425bb815Sopenharmony_ci 205425bb815Sopenharmony_ci/** 206425bb815Sopenharmony_ci * Count leading zeros in the topmost 4 bits of a 128-bit integer. 207425bb815Sopenharmony_ci */ 208425bb815Sopenharmony_ci#define ECMA_UINT128_CLZ_MAX4(name) \ 209425bb815Sopenharmony_ci __builtin_clzll (name.hi) 210425bb815Sopenharmony_ci 211425bb815Sopenharmony_ci#else /* !__GNUC__ && !__clang__ */ 212425bb815Sopenharmony_ci 213425bb815Sopenharmony_ci/** 214425bb815Sopenharmony_ci * Count leading zeros in a 64-bit integer. The behaviour is undefined for 0. 215425bb815Sopenharmony_ci * 216425bb815Sopenharmony_ci * @return number of leading zeros. 217425bb815Sopenharmony_ci */ 218425bb815Sopenharmony_cistatic inline int JERRY_ATTR_ALWAYS_INLINE 219425bb815Sopenharmony_ciecma_uint64_clz (uint64_t n) /**< integer to count leading zeros in */ 220425bb815Sopenharmony_ci{ 221425bb815Sopenharmony_ci JERRY_ASSERT (n != 0); 222425bb815Sopenharmony_ci 223425bb815Sopenharmony_ci int cnt = 0; 224425bb815Sopenharmony_ci uint64_t one = 0x8000000000000000ull; 225425bb815Sopenharmony_ci while ((n & one) == 0) 226425bb815Sopenharmony_ci { 227425bb815Sopenharmony_ci cnt++; 228425bb815Sopenharmony_ci one >>= 1; 229425bb815Sopenharmony_ci } 230425bb815Sopenharmony_ci return cnt; 231425bb815Sopenharmony_ci} /* ecma_uint64_clz */ 232425bb815Sopenharmony_ci 233425bb815Sopenharmony_ci/** 234425bb815Sopenharmony_ci * Number of leading zeros in 4-bit integers. 235425bb815Sopenharmony_ci */ 236425bb815Sopenharmony_cistatic const uint8_t ecma_uint4_clz[] = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; 237425bb815Sopenharmony_ci 238425bb815Sopenharmony_ci/** 239425bb815Sopenharmony_ci * Count leading zeros in the topmost 64 bits of a 128-bit integer. 240425bb815Sopenharmony_ci */ 241425bb815Sopenharmony_ci#define ECMA_UINT128_CLZ_MAX63(name) \ 242425bb815Sopenharmony_ci ecma_uint64_clz (name.hi) 243425bb815Sopenharmony_ci 244425bb815Sopenharmony_ci/** 245425bb815Sopenharmony_ci * Count leading zeros in the topmost 4 bits of a 128-bit integer. 246425bb815Sopenharmony_ci */ 247425bb815Sopenharmony_ci#define ECMA_UINT128_CLZ_MAX4(name) \ 248425bb815Sopenharmony_ci ecma_uint4_clz[name.hi >> 60] 249425bb815Sopenharmony_ci 250425bb815Sopenharmony_ci#endif /* __GNUC__ || __clang__ */ 251425bb815Sopenharmony_ci 252425bb815Sopenharmony_ci/** 253425bb815Sopenharmony_ci * @} 254425bb815Sopenharmony_ci */ 255425bb815Sopenharmony_ci 256425bb815Sopenharmony_ci/** 257425bb815Sopenharmony_ci * Number.MAX_VALUE exponent part when using 64 bit float representation. 258425bb815Sopenharmony_ci */ 259425bb815Sopenharmony_ci#define NUMBER_MAX_DECIMAL_EXPONENT 308 260425bb815Sopenharmony_ci/** 261425bb815Sopenharmony_ci * Number.MIN_VALUE exponent part when using 64 bit float representation. 262425bb815Sopenharmony_ci */ 263425bb815Sopenharmony_ci#define NUMBER_MIN_DECIMAL_EXPONENT -324 264425bb815Sopenharmony_ci 265425bb815Sopenharmony_ci#elif !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) 266425bb815Sopenharmony_ci 267425bb815Sopenharmony_ci/** 268425bb815Sopenharmony_ci * Number.MAX_VALUE exponent part when using 32 bit float representation. 269425bb815Sopenharmony_ci */ 270425bb815Sopenharmony_ci#define NUMBER_MAX_DECIMAL_EXPONENT 38 271425bb815Sopenharmony_ci/** 272425bb815Sopenharmony_ci * Number.MIN_VALUE exponent part when using 32 bit float representation. 273425bb815Sopenharmony_ci */ 274425bb815Sopenharmony_ci#define NUMBER_MIN_DECIMAL_EXPONENT -45 275425bb815Sopenharmony_ci 276425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ 277425bb815Sopenharmony_ci 278425bb815Sopenharmony_ci/** 279425bb815Sopenharmony_ci * Value of epsilon 280425bb815Sopenharmony_ci */ 281425bb815Sopenharmony_ci#define EPSILON 0.0000001 282425bb815Sopenharmony_ci 283425bb815Sopenharmony_ci/** 284425bb815Sopenharmony_ci * ECMA-defined conversion from string to number for different radixes (2, 8, 16). 285425bb815Sopenharmony_ci * 286425bb815Sopenharmony_ci * See also: 287425bb815Sopenharmony_ci * ECMA-262 v5 9.3.1 288425bb815Sopenharmony_ci * ECMA-262 v6 7.1.3.1 289425bb815Sopenharmony_ci * 290425bb815Sopenharmony_ci * @return NaN - if the conversion fails 291425bb815Sopenharmony_ci * converted number - otherwise 292425bb815Sopenharmony_ci */ 293425bb815Sopenharmony_cistatic ecma_number_t 294425bb815Sopenharmony_ciecma_utf8_string_to_number_by_radix (const lit_utf8_byte_t *str_p, /**< utf-8 string */ 295425bb815Sopenharmony_ci const lit_utf8_byte_t *end_p, /**< end of utf-8 string */ 296425bb815Sopenharmony_ci uint32_t radix) /**< radix */ 297425bb815Sopenharmony_ci{ 298425bb815Sopenharmony_ci JERRY_ASSERT (radix == 2 || radix == 8 || radix == 16); 299425bb815Sopenharmony_ci ecma_number_t num = ECMA_NUMBER_ZERO; 300425bb815Sopenharmony_ci 301425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 302425bb815Sopenharmony_ci if (radix <= 8) 303425bb815Sopenharmony_ci { 304425bb815Sopenharmony_ci lit_code_point_t upper_limit = LIT_CHAR_0 + radix; 305425bb815Sopenharmony_ci 306425bb815Sopenharmony_ci for (const lit_utf8_byte_t * iter_p = str_p; iter_p <= end_p; iter_p++) 307425bb815Sopenharmony_ci { 308425bb815Sopenharmony_ci int32_t digit_value; 309425bb815Sopenharmony_ci 310425bb815Sopenharmony_ci if (*iter_p >= LIT_CHAR_0 && *iter_p < upper_limit) 311425bb815Sopenharmony_ci { 312425bb815Sopenharmony_ci digit_value = (*iter_p - LIT_CHAR_0); 313425bb815Sopenharmony_ci } 314425bb815Sopenharmony_ci else 315425bb815Sopenharmony_ci { 316425bb815Sopenharmony_ci return ecma_number_make_nan (); 317425bb815Sopenharmony_ci } 318425bb815Sopenharmony_ci 319425bb815Sopenharmony_ci num = num * radix + (ecma_number_t) digit_value; 320425bb815Sopenharmony_ci } 321425bb815Sopenharmony_ci 322425bb815Sopenharmony_ci return num; 323425bb815Sopenharmony_ci } 324425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 325425bb815Sopenharmony_ci 326425bb815Sopenharmony_ci for (const lit_utf8_byte_t * iter_p = str_p; iter_p <= end_p; iter_p++) 327425bb815Sopenharmony_ci { 328425bb815Sopenharmony_ci int32_t digit_value; 329425bb815Sopenharmony_ci 330425bb815Sopenharmony_ci if (*iter_p >= LIT_CHAR_0 331425bb815Sopenharmony_ci && *iter_p <= LIT_CHAR_9) 332425bb815Sopenharmony_ci { 333425bb815Sopenharmony_ci digit_value = (*iter_p - LIT_CHAR_0); 334425bb815Sopenharmony_ci } 335425bb815Sopenharmony_ci else if (*iter_p >= LIT_CHAR_LOWERCASE_A 336425bb815Sopenharmony_ci && *iter_p <= LIT_CHAR_LOWERCASE_F) 337425bb815Sopenharmony_ci { 338425bb815Sopenharmony_ci digit_value = 10 + (*iter_p - LIT_CHAR_LOWERCASE_A); 339425bb815Sopenharmony_ci } 340425bb815Sopenharmony_ci else if (*iter_p >= LIT_CHAR_UPPERCASE_A 341425bb815Sopenharmony_ci && *iter_p <= LIT_CHAR_UPPERCASE_F) 342425bb815Sopenharmony_ci { 343425bb815Sopenharmony_ci digit_value = 10 + (*iter_p - LIT_CHAR_UPPERCASE_A); 344425bb815Sopenharmony_ci } 345425bb815Sopenharmony_ci else 346425bb815Sopenharmony_ci { 347425bb815Sopenharmony_ci return ecma_number_make_nan (); 348425bb815Sopenharmony_ci } 349425bb815Sopenharmony_ci 350425bb815Sopenharmony_ci num = num * radix + (ecma_number_t) digit_value; 351425bb815Sopenharmony_ci } 352425bb815Sopenharmony_ci 353425bb815Sopenharmony_ci return num; 354425bb815Sopenharmony_ci} /* ecma_utf8_string_to_number_by_radix */ 355425bb815Sopenharmony_ci 356425bb815Sopenharmony_ci/** 357425bb815Sopenharmony_ci * ECMA-defined conversion of string to Number. 358425bb815Sopenharmony_ci * 359425bb815Sopenharmony_ci * See also: 360425bb815Sopenharmony_ci * ECMA-262 v5, 9.3.1 361425bb815Sopenharmony_ci * 362425bb815Sopenharmony_ci * @return NaN - if the conversion fails 363425bb815Sopenharmony_ci * converted number - otherwise 364425bb815Sopenharmony_ci */ 365425bb815Sopenharmony_ciecma_number_t 366425bb815Sopenharmony_ciecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */ 367425bb815Sopenharmony_ci lit_utf8_size_t str_size) /**< string size */ 368425bb815Sopenharmony_ci{ 369425bb815Sopenharmony_ci /* TODO: Check license issues */ 370425bb815Sopenharmony_ci 371425bb815Sopenharmony_ci if (str_size == 0) 372425bb815Sopenharmony_ci { 373425bb815Sopenharmony_ci return ECMA_NUMBER_ZERO; 374425bb815Sopenharmony_ci } 375425bb815Sopenharmony_ci 376425bb815Sopenharmony_ci ecma_string_trim_helper (&str_p, &str_size); 377425bb815Sopenharmony_ci const lit_utf8_byte_t *end_p = str_p + (str_size - 1); 378425bb815Sopenharmony_ci 379425bb815Sopenharmony_ci if (str_size < 1) 380425bb815Sopenharmony_ci { 381425bb815Sopenharmony_ci return ECMA_NUMBER_ZERO; 382425bb815Sopenharmony_ci } 383425bb815Sopenharmony_ci 384425bb815Sopenharmony_ci if (end_p >= str_p + 2 385425bb815Sopenharmony_ci && str_p[0] == LIT_CHAR_0) 386425bb815Sopenharmony_ci { 387425bb815Sopenharmony_ci switch (LEXER_TO_ASCII_LOWERCASE (str_p[1])) 388425bb815Sopenharmony_ci { 389425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_X : 390425bb815Sopenharmony_ci { 391425bb815Sopenharmony_ci return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 16); 392425bb815Sopenharmony_ci } 393425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_O : 394425bb815Sopenharmony_ci { 395425bb815Sopenharmony_ci return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 8); 396425bb815Sopenharmony_ci } 397425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_B : 398425bb815Sopenharmony_ci { 399425bb815Sopenharmony_ci return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 2); 400425bb815Sopenharmony_ci } 401425bb815Sopenharmony_ci default: 402425bb815Sopenharmony_ci { 403425bb815Sopenharmony_ci break; 404425bb815Sopenharmony_ci } 405425bb815Sopenharmony_ci } 406425bb815Sopenharmony_ci } 407425bb815Sopenharmony_ci 408425bb815Sopenharmony_ci bool sign = false; /* positive */ 409425bb815Sopenharmony_ci 410425bb815Sopenharmony_ci if (*str_p == LIT_CHAR_PLUS) 411425bb815Sopenharmony_ci { 412425bb815Sopenharmony_ci str_p++; 413425bb815Sopenharmony_ci } 414425bb815Sopenharmony_ci else if (*str_p == LIT_CHAR_MINUS) 415425bb815Sopenharmony_ci { 416425bb815Sopenharmony_ci sign = true; /* negative */ 417425bb815Sopenharmony_ci 418425bb815Sopenharmony_ci str_p++; 419425bb815Sopenharmony_ci } 420425bb815Sopenharmony_ci 421425bb815Sopenharmony_ci if (str_p > end_p) 422425bb815Sopenharmony_ci { 423425bb815Sopenharmony_ci return ecma_number_make_nan (); 424425bb815Sopenharmony_ci } 425425bb815Sopenharmony_ci 426425bb815Sopenharmony_ci /* Checking if significant part of parse string is equal to "Infinity" */ 427425bb815Sopenharmony_ci const lit_utf8_byte_t *infinity_zt_str_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING_INFINITY_UL); 428425bb815Sopenharmony_ci 429425bb815Sopenharmony_ci JERRY_ASSERT (strlen ((const char *) infinity_zt_str_p) == 8); 430425bb815Sopenharmony_ci 431425bb815Sopenharmony_ci if ((end_p - str_p) == (8 - 1) && memcmp (infinity_zt_str_p, str_p, 8) == 0) 432425bb815Sopenharmony_ci { 433425bb815Sopenharmony_ci return ecma_number_make_infinity (sign); 434425bb815Sopenharmony_ci } 435425bb815Sopenharmony_ci 436425bb815Sopenharmony_ci uint64_t fraction_uint64 = 0; 437425bb815Sopenharmony_ci uint32_t digits = 0; 438425bb815Sopenharmony_ci int32_t e = 0; 439425bb815Sopenharmony_ci bool digit_seen = false; 440425bb815Sopenharmony_ci 441425bb815Sopenharmony_ci /* Parsing digits before dot (or before end of digits part if there is no dot in number) */ 442425bb815Sopenharmony_ci while (str_p <= end_p) 443425bb815Sopenharmony_ci { 444425bb815Sopenharmony_ci int32_t digit_value; 445425bb815Sopenharmony_ci 446425bb815Sopenharmony_ci if (*str_p >= LIT_CHAR_0 447425bb815Sopenharmony_ci && *str_p <= LIT_CHAR_9) 448425bb815Sopenharmony_ci { 449425bb815Sopenharmony_ci digit_seen = true; 450425bb815Sopenharmony_ci digit_value = (*str_p - LIT_CHAR_0); 451425bb815Sopenharmony_ci } 452425bb815Sopenharmony_ci else 453425bb815Sopenharmony_ci { 454425bb815Sopenharmony_ci break; 455425bb815Sopenharmony_ci } 456425bb815Sopenharmony_ci 457425bb815Sopenharmony_ci if (digits != 0 || digit_value != 0) 458425bb815Sopenharmony_ci { 459425bb815Sopenharmony_ci if (digits < ECMA_NUMBER_MAX_DIGITS) 460425bb815Sopenharmony_ci { 461425bb815Sopenharmony_ci fraction_uint64 = fraction_uint64 * 10 + (uint32_t) digit_value; 462425bb815Sopenharmony_ci digits++; 463425bb815Sopenharmony_ci } 464425bb815Sopenharmony_ci else 465425bb815Sopenharmony_ci { 466425bb815Sopenharmony_ci e++; 467425bb815Sopenharmony_ci } 468425bb815Sopenharmony_ci } 469425bb815Sopenharmony_ci 470425bb815Sopenharmony_ci str_p++; 471425bb815Sopenharmony_ci } 472425bb815Sopenharmony_ci 473425bb815Sopenharmony_ci if (str_p <= end_p 474425bb815Sopenharmony_ci && *str_p == LIT_CHAR_DOT) 475425bb815Sopenharmony_ci { 476425bb815Sopenharmony_ci str_p++; 477425bb815Sopenharmony_ci 478425bb815Sopenharmony_ci if (!digit_seen && str_p > end_p) 479425bb815Sopenharmony_ci { 480425bb815Sopenharmony_ci return ecma_number_make_nan (); 481425bb815Sopenharmony_ci } 482425bb815Sopenharmony_ci 483425bb815Sopenharmony_ci /* Parsing number's part that is placed after dot */ 484425bb815Sopenharmony_ci while (str_p <= end_p) 485425bb815Sopenharmony_ci { 486425bb815Sopenharmony_ci int32_t digit_value; 487425bb815Sopenharmony_ci 488425bb815Sopenharmony_ci if (*str_p >= LIT_CHAR_0 489425bb815Sopenharmony_ci && *str_p <= LIT_CHAR_9) 490425bb815Sopenharmony_ci { 491425bb815Sopenharmony_ci digit_seen = true; 492425bb815Sopenharmony_ci digit_value = (*str_p - LIT_CHAR_0); 493425bb815Sopenharmony_ci } 494425bb815Sopenharmony_ci else 495425bb815Sopenharmony_ci { 496425bb815Sopenharmony_ci break; 497425bb815Sopenharmony_ci } 498425bb815Sopenharmony_ci 499425bb815Sopenharmony_ci if (digits < ECMA_NUMBER_MAX_DIGITS) 500425bb815Sopenharmony_ci { 501425bb815Sopenharmony_ci if (digits != 0 || digit_value != 0) 502425bb815Sopenharmony_ci { 503425bb815Sopenharmony_ci fraction_uint64 = fraction_uint64 * 10 + (uint32_t) digit_value; 504425bb815Sopenharmony_ci digits++; 505425bb815Sopenharmony_ci } 506425bb815Sopenharmony_ci 507425bb815Sopenharmony_ci e--; 508425bb815Sopenharmony_ci } 509425bb815Sopenharmony_ci 510425bb815Sopenharmony_ci str_p++; 511425bb815Sopenharmony_ci } 512425bb815Sopenharmony_ci } 513425bb815Sopenharmony_ci 514425bb815Sopenharmony_ci /* Parsing exponent literal */ 515425bb815Sopenharmony_ci int32_t e_in_lit = 0; 516425bb815Sopenharmony_ci bool e_in_lit_sign = false; 517425bb815Sopenharmony_ci 518425bb815Sopenharmony_ci if (str_p <= end_p 519425bb815Sopenharmony_ci && (*str_p == LIT_CHAR_LOWERCASE_E 520425bb815Sopenharmony_ci || *str_p == LIT_CHAR_UPPERCASE_E)) 521425bb815Sopenharmony_ci { 522425bb815Sopenharmony_ci str_p++; 523425bb815Sopenharmony_ci 524425bb815Sopenharmony_ci if (!digit_seen || str_p > end_p) 525425bb815Sopenharmony_ci { 526425bb815Sopenharmony_ci return ecma_number_make_nan (); 527425bb815Sopenharmony_ci } 528425bb815Sopenharmony_ci 529425bb815Sopenharmony_ci if (*str_p == LIT_CHAR_PLUS) 530425bb815Sopenharmony_ci { 531425bb815Sopenharmony_ci str_p++; 532425bb815Sopenharmony_ci } 533425bb815Sopenharmony_ci else if (*str_p == LIT_CHAR_MINUS) 534425bb815Sopenharmony_ci { 535425bb815Sopenharmony_ci e_in_lit_sign = true; 536425bb815Sopenharmony_ci str_p++; 537425bb815Sopenharmony_ci } 538425bb815Sopenharmony_ci 539425bb815Sopenharmony_ci if (str_p > end_p) 540425bb815Sopenharmony_ci { 541425bb815Sopenharmony_ci return ecma_number_make_nan (); 542425bb815Sopenharmony_ci } 543425bb815Sopenharmony_ci 544425bb815Sopenharmony_ci while (str_p <= end_p) 545425bb815Sopenharmony_ci { 546425bb815Sopenharmony_ci int32_t digit_value; 547425bb815Sopenharmony_ci 548425bb815Sopenharmony_ci if (*str_p >= LIT_CHAR_0 549425bb815Sopenharmony_ci && *str_p <= LIT_CHAR_9) 550425bb815Sopenharmony_ci { 551425bb815Sopenharmony_ci digit_value = (*str_p - LIT_CHAR_0); 552425bb815Sopenharmony_ci } 553425bb815Sopenharmony_ci else 554425bb815Sopenharmony_ci { 555425bb815Sopenharmony_ci return ecma_number_make_nan (); 556425bb815Sopenharmony_ci } 557425bb815Sopenharmony_ci 558425bb815Sopenharmony_ci e_in_lit = e_in_lit * 10 + digit_value; 559425bb815Sopenharmony_ci int32_t e_check = e + (int32_t) digits - 1 + (e_in_lit_sign ? -e_in_lit : e_in_lit); 560425bb815Sopenharmony_ci 561425bb815Sopenharmony_ci if (e_check > NUMBER_MAX_DECIMAL_EXPONENT) 562425bb815Sopenharmony_ci { 563425bb815Sopenharmony_ci return ecma_number_make_infinity (sign); 564425bb815Sopenharmony_ci } 565425bb815Sopenharmony_ci else if (e_check < NUMBER_MIN_DECIMAL_EXPONENT) 566425bb815Sopenharmony_ci { 567425bb815Sopenharmony_ci return sign ? -ECMA_NUMBER_ZERO : ECMA_NUMBER_ZERO; 568425bb815Sopenharmony_ci } 569425bb815Sopenharmony_ci 570425bb815Sopenharmony_ci str_p++; 571425bb815Sopenharmony_ci } 572425bb815Sopenharmony_ci } 573425bb815Sopenharmony_ci 574425bb815Sopenharmony_ci /* Adding value of exponent literal to exponent value */ 575425bb815Sopenharmony_ci if (e_in_lit_sign) 576425bb815Sopenharmony_ci { 577425bb815Sopenharmony_ci e -= e_in_lit; 578425bb815Sopenharmony_ci } 579425bb815Sopenharmony_ci else 580425bb815Sopenharmony_ci { 581425bb815Sopenharmony_ci e += e_in_lit; 582425bb815Sopenharmony_ci } 583425bb815Sopenharmony_ci 584425bb815Sopenharmony_ci bool e_sign; 585425bb815Sopenharmony_ci 586425bb815Sopenharmony_ci if (e < 0) 587425bb815Sopenharmony_ci { 588425bb815Sopenharmony_ci e_sign = true; 589425bb815Sopenharmony_ci e = -e; 590425bb815Sopenharmony_ci } 591425bb815Sopenharmony_ci else 592425bb815Sopenharmony_ci { 593425bb815Sopenharmony_ci e_sign = false; 594425bb815Sopenharmony_ci } 595425bb815Sopenharmony_ci 596425bb815Sopenharmony_ci if (str_p <= end_p) 597425bb815Sopenharmony_ci { 598425bb815Sopenharmony_ci return ecma_number_make_nan (); 599425bb815Sopenharmony_ci } 600425bb815Sopenharmony_ci 601425bb815Sopenharmony_ci JERRY_ASSERT (str_p == end_p + 1); 602425bb815Sopenharmony_ci 603425bb815Sopenharmony_ci if (fraction_uint64 == 0) 604425bb815Sopenharmony_ci { 605425bb815Sopenharmony_ci return sign ? -ECMA_NUMBER_ZERO : ECMA_NUMBER_ZERO; 606425bb815Sopenharmony_ci } 607425bb815Sopenharmony_ci 608425bb815Sopenharmony_ci#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) 609425bb815Sopenharmony_ci /* 610425bb815Sopenharmony_ci * 128-bit mantissa storage 611425bb815Sopenharmony_ci * 612425bb815Sopenharmony_ci * Normalized: |4 bits zero|124-bit mantissa with highest bit set to 1| 613425bb815Sopenharmony_ci */ 614425bb815Sopenharmony_ci ecma_uint128_t fraction_uint128 = { 0, fraction_uint64 }; 615425bb815Sopenharmony_ci 616425bb815Sopenharmony_ci /* Normalizing mantissa */ 617425bb815Sopenharmony_ci int shift = 4 - ECMA_UINT128_CLZ_MAX63 (fraction_uint128); 618425bb815Sopenharmony_ci if (shift < 0) 619425bb815Sopenharmony_ci { 620425bb815Sopenharmony_ci ECMA_UINT128_LEFT_SHIFT_MAX63 (fraction_uint128, -shift); 621425bb815Sopenharmony_ci } 622425bb815Sopenharmony_ci else 623425bb815Sopenharmony_ci { 624425bb815Sopenharmony_ci ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, shift); 625425bb815Sopenharmony_ci } 626425bb815Sopenharmony_ci int32_t binary_exponent = 1 + shift; 627425bb815Sopenharmony_ci 628425bb815Sopenharmony_ci if (!e_sign) 629425bb815Sopenharmony_ci { 630425bb815Sopenharmony_ci /* positive or zero decimal exponent */ 631425bb815Sopenharmony_ci JERRY_ASSERT (e >= 0); 632425bb815Sopenharmony_ci 633425bb815Sopenharmony_ci while (e > 0) 634425bb815Sopenharmony_ci { 635425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 4); 636425bb815Sopenharmony_ci 637425bb815Sopenharmony_ci ECMA_UINT128_MUL10 (fraction_uint128); 638425bb815Sopenharmony_ci 639425bb815Sopenharmony_ci e--; 640425bb815Sopenharmony_ci 641425bb815Sopenharmony_ci /* Normalizing mantissa */ 642425bb815Sopenharmony_ci shift = 4 - ECMA_UINT128_CLZ_MAX4 (fraction_uint128); 643425bb815Sopenharmony_ci JERRY_ASSERT (shift >= 0); 644425bb815Sopenharmony_ci ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, shift); 645425bb815Sopenharmony_ci binary_exponent += shift; 646425bb815Sopenharmony_ci } 647425bb815Sopenharmony_ci } 648425bb815Sopenharmony_ci else 649425bb815Sopenharmony_ci { 650425bb815Sopenharmony_ci /* negative decimal exponent */ 651425bb815Sopenharmony_ci JERRY_ASSERT (e != 0); 652425bb815Sopenharmony_ci 653425bb815Sopenharmony_ci while (e > 0) 654425bb815Sopenharmony_ci { 655425bb815Sopenharmony_ci /* Denormalizing mantissa, moving highest 1 to bit 127 */ 656425bb815Sopenharmony_ci shift = ECMA_UINT128_CLZ_MAX4 (fraction_uint128); 657425bb815Sopenharmony_ci JERRY_ASSERT (shift <= 4); 658425bb815Sopenharmony_ci ECMA_UINT128_LEFT_SHIFT_MAX63 (fraction_uint128, shift); 659425bb815Sopenharmony_ci binary_exponent -= shift; 660425bb815Sopenharmony_ci 661425bb815Sopenharmony_ci JERRY_ASSERT (!ECMA_UINT128_IS_ZERO (fraction_uint128)); 662425bb815Sopenharmony_ci 663425bb815Sopenharmony_ci ECMA_UINT128_DIV10 (fraction_uint128); 664425bb815Sopenharmony_ci 665425bb815Sopenharmony_ci e--; 666425bb815Sopenharmony_ci } 667425bb815Sopenharmony_ci 668425bb815Sopenharmony_ci /* Normalizing mantissa */ 669425bb815Sopenharmony_ci shift = 4 - ECMA_UINT128_CLZ_MAX4 (fraction_uint128); 670425bb815Sopenharmony_ci JERRY_ASSERT (shift >= 0); 671425bb815Sopenharmony_ci ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, shift); 672425bb815Sopenharmony_ci binary_exponent += shift; 673425bb815Sopenharmony_ci 674425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 4); 675425bb815Sopenharmony_ci } 676425bb815Sopenharmony_ci 677425bb815Sopenharmony_ci JERRY_ASSERT (!ECMA_UINT128_IS_ZERO (fraction_uint128)); 678425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 4); 679425bb815Sopenharmony_ci 680425bb815Sopenharmony_ci /* 681425bb815Sopenharmony_ci * Preparing mantissa for conversion to 52-bit representation, converting it to: 682425bb815Sopenharmony_ci * 683425bb815Sopenharmony_ci * |11 zero bits|1|116 mantissa bits| 684425bb815Sopenharmony_ci */ 685425bb815Sopenharmony_ci ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, 7u); 686425bb815Sopenharmony_ci binary_exponent += 7; 687425bb815Sopenharmony_ci 688425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 11); 689425bb815Sopenharmony_ci 690425bb815Sopenharmony_ci fraction_uint64 = ecma_round_high_to_uint64 (&fraction_uint128); 691425bb815Sopenharmony_ci 692425bb815Sopenharmony_ci return ecma_number_make_from_sign_mantissa_and_exponent (sign, fraction_uint64, binary_exponent); 693425bb815Sopenharmony_ci#elif !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) 694425bb815Sopenharmony_ci /* Less precise conversion */ 695425bb815Sopenharmony_ci ecma_number_t num = (ecma_number_t) (uint32_t) fraction_uint64; 696425bb815Sopenharmony_ci 697425bb815Sopenharmony_ci ecma_number_t m = e_sign ? (ecma_number_t) 0.1 : (ecma_number_t) 10.0; 698425bb815Sopenharmony_ci 699425bb815Sopenharmony_ci while (e) 700425bb815Sopenharmony_ci { 701425bb815Sopenharmony_ci if (e % 2) 702425bb815Sopenharmony_ci { 703425bb815Sopenharmony_ci num *= m; 704425bb815Sopenharmony_ci } 705425bb815Sopenharmony_ci 706425bb815Sopenharmony_ci m *= m; 707425bb815Sopenharmony_ci e /= 2; 708425bb815Sopenharmony_ci } 709425bb815Sopenharmony_ci 710425bb815Sopenharmony_ci return num; 711425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ 712425bb815Sopenharmony_ci} /* ecma_utf8_string_to_number */ 713425bb815Sopenharmony_ci 714425bb815Sopenharmony_ci/** 715425bb815Sopenharmony_ci * ECMA-defined conversion of UInt32 to String (zero-terminated). 716425bb815Sopenharmony_ci * 717425bb815Sopenharmony_ci * See also: 718425bb815Sopenharmony_ci * ECMA-262 v5, 9.8.1 719425bb815Sopenharmony_ci * 720425bb815Sopenharmony_ci * @return number of bytes copied to buffer 721425bb815Sopenharmony_ci */ 722425bb815Sopenharmony_cilit_utf8_size_t 723425bb815Sopenharmony_ciecma_uint32_to_utf8_string (uint32_t value, /**< value to convert */ 724425bb815Sopenharmony_ci lit_utf8_byte_t *out_buffer_p, /**< buffer for string */ 725425bb815Sopenharmony_ci lit_utf8_size_t buffer_size) /**< size of buffer */ 726425bb815Sopenharmony_ci{ 727425bb815Sopenharmony_ci lit_utf8_byte_t *buf_p = out_buffer_p + buffer_size; 728425bb815Sopenharmony_ci 729425bb815Sopenharmony_ci do 730425bb815Sopenharmony_ci { 731425bb815Sopenharmony_ci JERRY_ASSERT (buf_p >= out_buffer_p); 732425bb815Sopenharmony_ci 733425bb815Sopenharmony_ci buf_p--; 734425bb815Sopenharmony_ci *buf_p = (lit_utf8_byte_t) ((value % 10) + LIT_CHAR_0); 735425bb815Sopenharmony_ci value /= 10; 736425bb815Sopenharmony_ci } 737425bb815Sopenharmony_ci while (value != 0); 738425bb815Sopenharmony_ci 739425bb815Sopenharmony_ci JERRY_ASSERT (buf_p >= out_buffer_p); 740425bb815Sopenharmony_ci 741425bb815Sopenharmony_ci lit_utf8_size_t bytes_copied = (lit_utf8_size_t) (out_buffer_p + buffer_size - buf_p); 742425bb815Sopenharmony_ci 743425bb815Sopenharmony_ci if (JERRY_LIKELY (buf_p != out_buffer_p)) 744425bb815Sopenharmony_ci { 745425bb815Sopenharmony_ci memmove (out_buffer_p, buf_p, bytes_copied); 746425bb815Sopenharmony_ci } 747425bb815Sopenharmony_ci 748425bb815Sopenharmony_ci return bytes_copied; 749425bb815Sopenharmony_ci} /* ecma_uint32_to_utf8_string */ 750425bb815Sopenharmony_ci 751425bb815Sopenharmony_ci/** 752425bb815Sopenharmony_ci * ECMA-defined conversion of Number value to UInt32 value 753425bb815Sopenharmony_ci * 754425bb815Sopenharmony_ci * See also: 755425bb815Sopenharmony_ci * ECMA-262 v5, 9.6 756425bb815Sopenharmony_ci * 757425bb815Sopenharmony_ci * @return 32-bit unsigned integer - result of conversion. 758425bb815Sopenharmony_ci */ 759425bb815Sopenharmony_ciuint32_t 760425bb815Sopenharmony_ciecma_number_to_uint32 (ecma_number_t num) /**< ecma-number */ 761425bb815Sopenharmony_ci{ 762425bb815Sopenharmony_ci if (JERRY_UNLIKELY (ecma_number_is_zero (num) || !ecma_number_is_finite (num))) 763425bb815Sopenharmony_ci { 764425bb815Sopenharmony_ci return 0; 765425bb815Sopenharmony_ci } 766425bb815Sopenharmony_ci 767425bb815Sopenharmony_ci const bool sign = ecma_number_is_negative (num); 768425bb815Sopenharmony_ci const ecma_number_t abs_num = sign ? -num : num; 769425bb815Sopenharmony_ci 770425bb815Sopenharmony_ci /* 2 ^ 32 */ 771425bb815Sopenharmony_ci const uint64_t uint64_2_pow_32 = (1ull << 32); 772425bb815Sopenharmony_ci 773425bb815Sopenharmony_ci const ecma_number_t num_2_pow_32 = (float) uint64_2_pow_32; 774425bb815Sopenharmony_ci 775425bb815Sopenharmony_ci ecma_number_t num_in_uint32_range; 776425bb815Sopenharmony_ci 777425bb815Sopenharmony_ci if (abs_num >= num_2_pow_32) 778425bb815Sopenharmony_ci { 779425bb815Sopenharmony_ci num_in_uint32_range = ecma_number_calc_remainder (abs_num, 780425bb815Sopenharmony_ci num_2_pow_32); 781425bb815Sopenharmony_ci } 782425bb815Sopenharmony_ci else 783425bb815Sopenharmony_ci { 784425bb815Sopenharmony_ci num_in_uint32_range = abs_num; 785425bb815Sopenharmony_ci } 786425bb815Sopenharmony_ci 787425bb815Sopenharmony_ci /* Check that the floating point value can be represented with uint32_t. */ 788425bb815Sopenharmony_ci JERRY_ASSERT (num_in_uint32_range < uint64_2_pow_32); 789425bb815Sopenharmony_ci uint32_t uint32_num = (uint32_t) num_in_uint32_range; 790425bb815Sopenharmony_ci 791425bb815Sopenharmony_ci const uint32_t ret = sign ? -uint32_num : uint32_num; 792425bb815Sopenharmony_ci 793425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 794425bb815Sopenharmony_ci if (sign 795425bb815Sopenharmony_ci && uint32_num != 0) 796425bb815Sopenharmony_ci { 797425bb815Sopenharmony_ci JERRY_ASSERT (ret == uint64_2_pow_32 - uint32_num); 798425bb815Sopenharmony_ci } 799425bb815Sopenharmony_ci else 800425bb815Sopenharmony_ci { 801425bb815Sopenharmony_ci JERRY_ASSERT (ret == uint32_num); 802425bb815Sopenharmony_ci } 803425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 804425bb815Sopenharmony_ci 805425bb815Sopenharmony_ci return ret; 806425bb815Sopenharmony_ci} /* ecma_number_to_uint32 */ 807425bb815Sopenharmony_ci 808425bb815Sopenharmony_ci/** 809425bb815Sopenharmony_ci * ECMA-defined conversion of Number value to Int32 value 810425bb815Sopenharmony_ci * 811425bb815Sopenharmony_ci * See also: 812425bb815Sopenharmony_ci * ECMA-262 v5, 9.5 813425bb815Sopenharmony_ci * 814425bb815Sopenharmony_ci * @return 32-bit signed integer - result of conversion. 815425bb815Sopenharmony_ci */ 816425bb815Sopenharmony_ciint32_t 817425bb815Sopenharmony_ciecma_number_to_int32 (ecma_number_t num) /**< ecma-number */ 818425bb815Sopenharmony_ci{ 819425bb815Sopenharmony_ci uint32_t uint32_num = ecma_number_to_uint32 (num); 820425bb815Sopenharmony_ci 821425bb815Sopenharmony_ci /* 2 ^ 32 */ 822425bb815Sopenharmony_ci const int64_t int64_2_pow_32 = (1ll << 32); 823425bb815Sopenharmony_ci 824425bb815Sopenharmony_ci /* 2 ^ 31 */ 825425bb815Sopenharmony_ci const uint32_t uint32_2_pow_31 = (1ull << 31); 826425bb815Sopenharmony_ci 827425bb815Sopenharmony_ci int32_t ret; 828425bb815Sopenharmony_ci 829425bb815Sopenharmony_ci if (uint32_num >= uint32_2_pow_31) 830425bb815Sopenharmony_ci { 831425bb815Sopenharmony_ci ret = (int32_t) (uint32_num - int64_2_pow_32); 832425bb815Sopenharmony_ci } 833425bb815Sopenharmony_ci else 834425bb815Sopenharmony_ci { 835425bb815Sopenharmony_ci ret = (int32_t) uint32_num; 836425bb815Sopenharmony_ci } 837425bb815Sopenharmony_ci 838425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 839425bb815Sopenharmony_ci int64_t int64_num = uint32_num; 840425bb815Sopenharmony_ci 841425bb815Sopenharmony_ci JERRY_ASSERT (int64_num >= 0); 842425bb815Sopenharmony_ci 843425bb815Sopenharmony_ci if (int64_num >= uint32_2_pow_31) 844425bb815Sopenharmony_ci { 845425bb815Sopenharmony_ci JERRY_ASSERT (ret == int64_num - int64_2_pow_32); 846425bb815Sopenharmony_ci } 847425bb815Sopenharmony_ci else 848425bb815Sopenharmony_ci { 849425bb815Sopenharmony_ci JERRY_ASSERT (ret == int64_num); 850425bb815Sopenharmony_ci } 851425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 852425bb815Sopenharmony_ci 853425bb815Sopenharmony_ci return ret; 854425bb815Sopenharmony_ci} /* ecma_number_to_int32 */ 855425bb815Sopenharmony_ci 856425bb815Sopenharmony_ci/** 857425bb815Sopenharmony_ci * Perform conversion of ecma-number to decimal representation with decimal exponent. 858425bb815Sopenharmony_ci * 859425bb815Sopenharmony_ci * Note: 860425bb815Sopenharmony_ci * The calculated values correspond to s, n, k parameters in ECMA-262 v5, 9.8.1, item 5: 861425bb815Sopenharmony_ci * - parameter out_digits_p corresponds to s, the digits of the number; 862425bb815Sopenharmony_ci * - parameter out_decimal_exp_p corresponds to n, the decimal exponent; 863425bb815Sopenharmony_ci * - return value corresponds to k, the number of digits. 864425bb815Sopenharmony_ci * 865425bb815Sopenharmony_ci * @return the number of digits 866425bb815Sopenharmony_ci */ 867425bb815Sopenharmony_cilit_utf8_size_t 868425bb815Sopenharmony_ciecma_number_to_decimal (ecma_number_t num, /**< ecma-number */ 869425bb815Sopenharmony_ci lit_utf8_byte_t *out_digits_p, /**< [out] buffer to fill with digits */ 870425bb815Sopenharmony_ci int32_t *out_decimal_exp_p) /**< [out] decimal exponent */ 871425bb815Sopenharmony_ci{ 872425bb815Sopenharmony_ci JERRY_ASSERT (!ecma_number_is_nan (num)); 873425bb815Sopenharmony_ci JERRY_ASSERT (!ecma_number_is_zero (num)); 874425bb815Sopenharmony_ci JERRY_ASSERT (!ecma_number_is_infinity (num)); 875425bb815Sopenharmony_ci JERRY_ASSERT (!ecma_number_is_negative (num)); 876425bb815Sopenharmony_ci 877425bb815Sopenharmony_ci return ecma_errol0_dtoa ((double) num, out_digits_p, out_decimal_exp_p); 878425bb815Sopenharmony_ci} /* ecma_number_to_decimal */ 879425bb815Sopenharmony_ci 880425bb815Sopenharmony_ci/** 881425bb815Sopenharmony_ci * Calculate the number of digits from the given double value whithout franction part 882425bb815Sopenharmony_ci * 883425bb815Sopenharmony_ci * @return number of digits 884425bb815Sopenharmony_ci */ 885425bb815Sopenharmony_ciinline static int32_t JERRY_ATTR_ALWAYS_INLINE 886425bb815Sopenharmony_ciecma_number_of_digits (double val) /**< ecma number */ 887425bb815Sopenharmony_ci{ 888425bb815Sopenharmony_ci JERRY_ASSERT (fabs (fmod (val, 1.0)) < EPSILON); 889425bb815Sopenharmony_ci int32_t exponent = 0; 890425bb815Sopenharmony_ci 891425bb815Sopenharmony_ci while (val >= 1.0) 892425bb815Sopenharmony_ci { 893425bb815Sopenharmony_ci val /= 10.0; 894425bb815Sopenharmony_ci exponent++; 895425bb815Sopenharmony_ci } 896425bb815Sopenharmony_ci 897425bb815Sopenharmony_ci return exponent; 898425bb815Sopenharmony_ci} /* ecma_number_of_digits */ 899425bb815Sopenharmony_ci 900425bb815Sopenharmony_ci/** 901425bb815Sopenharmony_ci * Convert double value to ASCII 902425bb815Sopenharmony_ci */ 903425bb815Sopenharmony_ciinline static void JERRY_ATTR_ALWAYS_INLINE 904425bb815Sopenharmony_ciecma_double_to_ascii (double val, /**< ecma number */ 905425bb815Sopenharmony_ci lit_utf8_byte_t *buffer_p, /**< buffer to generate digits into */ 906425bb815Sopenharmony_ci int32_t num_of_digits, /**< number of digits */ 907425bb815Sopenharmony_ci int32_t *exp_p) /**< [out] exponent */ 908425bb815Sopenharmony_ci{ 909425bb815Sopenharmony_ci int32_t char_cnt = 0; 910425bb815Sopenharmony_ci 911425bb815Sopenharmony_ci double divider = 10.0; 912425bb815Sopenharmony_ci double prev_residual; 913425bb815Sopenharmony_ci double mod_res = fmod (val, divider); 914425bb815Sopenharmony_ci 915425bb815Sopenharmony_ci buffer_p[num_of_digits - 1 - char_cnt++] = (lit_utf8_byte_t) ((int) mod_res + '0'); 916425bb815Sopenharmony_ci divider *= 10.0; 917425bb815Sopenharmony_ci prev_residual = mod_res; 918425bb815Sopenharmony_ci 919425bb815Sopenharmony_ci while (char_cnt < num_of_digits) 920425bb815Sopenharmony_ci { 921425bb815Sopenharmony_ci mod_res = fmod (val, divider); 922425bb815Sopenharmony_ci double residual = mod_res - prev_residual; 923425bb815Sopenharmony_ci buffer_p[num_of_digits - 1 - char_cnt++] = (lit_utf8_byte_t) ((int) (residual / (divider / 10.0)) + '0'); 924425bb815Sopenharmony_ci 925425bb815Sopenharmony_ci divider *= 10.0; 926425bb815Sopenharmony_ci prev_residual = mod_res; 927425bb815Sopenharmony_ci } 928425bb815Sopenharmony_ci 929425bb815Sopenharmony_ci *exp_p = char_cnt; 930425bb815Sopenharmony_ci} /* ecma_double_to_ascii */ 931425bb815Sopenharmony_ci 932425bb815Sopenharmony_ci/** 933425bb815Sopenharmony_ci * Double to binary floating-point number conversion 934425bb815Sopenharmony_ci * 935425bb815Sopenharmony_ci * @return number of generated digits 936425bb815Sopenharmony_ci */ 937425bb815Sopenharmony_cistatic inline lit_utf8_size_t JERRY_ATTR_ALWAYS_INLINE 938425bb815Sopenharmony_ciecma_double_to_binary_floating_point (double val, /**< ecma number */ 939425bb815Sopenharmony_ci lit_utf8_byte_t *buffer_p, /**< buffer to generate digits into */ 940425bb815Sopenharmony_ci int32_t *exp_p) /**< [out] exponent */ 941425bb815Sopenharmony_ci{ 942425bb815Sopenharmony_ci int32_t char_cnt = 0; 943425bb815Sopenharmony_ci double integer_part, fraction_part; 944425bb815Sopenharmony_ci 945425bb815Sopenharmony_ci fraction_part = fmod (val, 1.0); 946425bb815Sopenharmony_ci integer_part = floor (val); 947425bb815Sopenharmony_ci int32_t num_of_digits = ecma_number_of_digits (integer_part); 948425bb815Sopenharmony_ci 949425bb815Sopenharmony_ci if (fabs (integer_part) < EPSILON) 950425bb815Sopenharmony_ci { 951425bb815Sopenharmony_ci buffer_p[0] = '0'; 952425bb815Sopenharmony_ci char_cnt++; 953425bb815Sopenharmony_ci } 954425bb815Sopenharmony_ci else if (num_of_digits <= 16) /* Ensure that integer_part is not rounded */ 955425bb815Sopenharmony_ci { 956425bb815Sopenharmony_ci while (integer_part > 0.0) 957425bb815Sopenharmony_ci { 958425bb815Sopenharmony_ci buffer_p[num_of_digits - 1 - char_cnt++] = (lit_utf8_byte_t) ((int) fmod (integer_part, 10.0) + '0'); 959425bb815Sopenharmony_ci integer_part = floor (integer_part / 10.0); 960425bb815Sopenharmony_ci } 961425bb815Sopenharmony_ci } 962425bb815Sopenharmony_ci else if (num_of_digits <= 21) 963425bb815Sopenharmony_ci { 964425bb815Sopenharmony_ci ecma_double_to_ascii (integer_part, buffer_p, num_of_digits, &char_cnt); 965425bb815Sopenharmony_ci } 966425bb815Sopenharmony_ci else 967425bb815Sopenharmony_ci { 968425bb815Sopenharmony_ci /* According to ECMA-262 v5, 15.7.4.5, step 7: if x >= 10^21, then execution will continue with 969425bb815Sopenharmony_ci * ToString(x) so in this case no further conversions are required. Number 21 in the else if condition 970425bb815Sopenharmony_ci * above must be kept in sync with the number 21 in ecma_builtin_number_prototype_object_to_fixed 971425bb815Sopenharmony_ci * method, step 7. */ 972425bb815Sopenharmony_ci *exp_p = num_of_digits; 973425bb815Sopenharmony_ci return 0; 974425bb815Sopenharmony_ci } 975425bb815Sopenharmony_ci 976425bb815Sopenharmony_ci *exp_p = char_cnt; 977425bb815Sopenharmony_ci 978425bb815Sopenharmony_ci while (fraction_part > 0 && char_cnt < ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER - 1) 979425bb815Sopenharmony_ci { 980425bb815Sopenharmony_ci fraction_part *= 10; 981425bb815Sopenharmony_ci double tmp = fraction_part; 982425bb815Sopenharmony_ci fraction_part = fmod (fraction_part, 1.0); 983425bb815Sopenharmony_ci integer_part = floor (tmp); 984425bb815Sopenharmony_ci buffer_p[char_cnt++] = (lit_utf8_byte_t) ('0' + (int) integer_part); 985425bb815Sopenharmony_ci } 986425bb815Sopenharmony_ci 987425bb815Sopenharmony_ci buffer_p[char_cnt] = '\0'; 988425bb815Sopenharmony_ci 989425bb815Sopenharmony_ci return (lit_utf8_size_t) (char_cnt - *exp_p); 990425bb815Sopenharmony_ci} /* ecma_double_to_binary_floating_point */ 991425bb815Sopenharmony_ci 992425bb815Sopenharmony_ci/** 993425bb815Sopenharmony_ci * Perform conversion of ecma-number to equivalent binary floating-point number representation with decimal exponent. 994425bb815Sopenharmony_ci * 995425bb815Sopenharmony_ci * Note: 996425bb815Sopenharmony_ci * The calculated values correspond to s, n, k parameters in ECMA-262 v5, 9.8.1, item 5: 997425bb815Sopenharmony_ci * - parameter out_digits_p corresponds to s, the digits of the number; 998425bb815Sopenharmony_ci * - parameter out_decimal_exp_p corresponds to n, the decimal exponent; 999425bb815Sopenharmony_ci * - return value corresponds to k, the number of digits. 1000425bb815Sopenharmony_ci * 1001425bb815Sopenharmony_ci * @return the number of digits 1002425bb815Sopenharmony_ci */ 1003425bb815Sopenharmony_cilit_utf8_size_t 1004425bb815Sopenharmony_ciecma_number_to_binary_floating_point_number (ecma_number_t num, /**< ecma-number */ 1005425bb815Sopenharmony_ci lit_utf8_byte_t *out_digits_p, /**< [out] buffer to fill with digits */ 1006425bb815Sopenharmony_ci int32_t *out_decimal_exp_p) /**< [out] decimal exponent */ 1007425bb815Sopenharmony_ci{ 1008425bb815Sopenharmony_ci JERRY_ASSERT (!ecma_number_is_nan (num)); 1009425bb815Sopenharmony_ci JERRY_ASSERT (!ecma_number_is_zero (num)); 1010425bb815Sopenharmony_ci JERRY_ASSERT (!ecma_number_is_infinity (num)); 1011425bb815Sopenharmony_ci JERRY_ASSERT (!ecma_number_is_negative (num)); 1012425bb815Sopenharmony_ci 1013425bb815Sopenharmony_ci return ecma_double_to_binary_floating_point ((double) num, out_digits_p, out_decimal_exp_p); 1014425bb815Sopenharmony_ci} /* ecma_number_to_binary_floating_point_number */ 1015425bb815Sopenharmony_ci 1016425bb815Sopenharmony_ci/** 1017425bb815Sopenharmony_ci * Convert ecma-number to zero-terminated string 1018425bb815Sopenharmony_ci * 1019425bb815Sopenharmony_ci * See also: 1020425bb815Sopenharmony_ci * ECMA-262 v5, 9.8.1 1021425bb815Sopenharmony_ci * 1022425bb815Sopenharmony_ci * 1023425bb815Sopenharmony_ci * @return size of utf-8 string 1024425bb815Sopenharmony_ci */ 1025425bb815Sopenharmony_cilit_utf8_size_t 1026425bb815Sopenharmony_ciecma_number_to_utf8_string (ecma_number_t num, /**< ecma-number */ 1027425bb815Sopenharmony_ci lit_utf8_byte_t *buffer_p, /**< buffer for utf-8 string */ 1028425bb815Sopenharmony_ci lit_utf8_size_t buffer_size) /**< size of buffer */ 1029425bb815Sopenharmony_ci{ 1030425bb815Sopenharmony_ci lit_utf8_byte_t *dst_p; 1031425bb815Sopenharmony_ci 1032425bb815Sopenharmony_ci if (ecma_number_is_nan (num)) 1033425bb815Sopenharmony_ci { 1034425bb815Sopenharmony_ci /* 1. */ 1035425bb815Sopenharmony_ci dst_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_NAN, buffer_p, buffer_size); 1036425bb815Sopenharmony_ci return (lit_utf8_size_t) (dst_p - buffer_p); 1037425bb815Sopenharmony_ci } 1038425bb815Sopenharmony_ci 1039425bb815Sopenharmony_ci if (ecma_number_is_zero (num)) 1040425bb815Sopenharmony_ci { 1041425bb815Sopenharmony_ci /* 2. */ 1042425bb815Sopenharmony_ci *buffer_p = LIT_CHAR_0; 1043425bb815Sopenharmony_ci JERRY_ASSERT (1 <= buffer_size); 1044425bb815Sopenharmony_ci return 1; 1045425bb815Sopenharmony_ci } 1046425bb815Sopenharmony_ci 1047425bb815Sopenharmony_ci dst_p = buffer_p; 1048425bb815Sopenharmony_ci 1049425bb815Sopenharmony_ci if (ecma_number_is_negative (num)) 1050425bb815Sopenharmony_ci { 1051425bb815Sopenharmony_ci /* 3. */ 1052425bb815Sopenharmony_ci *dst_p++ = LIT_CHAR_MINUS; 1053425bb815Sopenharmony_ci num = -num; 1054425bb815Sopenharmony_ci } 1055425bb815Sopenharmony_ci 1056425bb815Sopenharmony_ci if (ecma_number_is_infinity (num)) 1057425bb815Sopenharmony_ci { 1058425bb815Sopenharmony_ci /* 4. */ 1059425bb815Sopenharmony_ci dst_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_INFINITY_UL, dst_p, 1060425bb815Sopenharmony_ci (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); 1061425bb815Sopenharmony_ci JERRY_ASSERT (dst_p <= buffer_p + buffer_size); 1062425bb815Sopenharmony_ci return (lit_utf8_size_t) (dst_p - buffer_p); 1063425bb815Sopenharmony_ci } 1064425bb815Sopenharmony_ci 1065425bb815Sopenharmony_ci JERRY_ASSERT (ecma_number_get_next (ecma_number_get_prev (num)) == num); 1066425bb815Sopenharmony_ci 1067425bb815Sopenharmony_ci /* 5. */ 1068425bb815Sopenharmony_ci uint32_t num_uint32 = ecma_number_to_uint32 (num); 1069425bb815Sopenharmony_ci 1070425bb815Sopenharmony_ci if (((ecma_number_t) num_uint32) == num) 1071425bb815Sopenharmony_ci { 1072425bb815Sopenharmony_ci dst_p += ecma_uint32_to_utf8_string (num_uint32, dst_p, (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); 1073425bb815Sopenharmony_ci JERRY_ASSERT (dst_p <= buffer_p + buffer_size); 1074425bb815Sopenharmony_ci return (lit_utf8_size_t) (dst_p - buffer_p); 1075425bb815Sopenharmony_ci } 1076425bb815Sopenharmony_ci 1077425bb815Sopenharmony_ci /* decimal exponent */ 1078425bb815Sopenharmony_ci int32_t n; 1079425bb815Sopenharmony_ci /* number of digits in mantissa */ 1080425bb815Sopenharmony_ci int32_t k; 1081425bb815Sopenharmony_ci 1082425bb815Sopenharmony_ci k = (int32_t) ecma_number_to_decimal (num, dst_p, &n); 1083425bb815Sopenharmony_ci 1084425bb815Sopenharmony_ci if (k <= n && n <= 21) 1085425bb815Sopenharmony_ci { 1086425bb815Sopenharmony_ci /* 6. */ 1087425bb815Sopenharmony_ci dst_p += k; 1088425bb815Sopenharmony_ci 1089425bb815Sopenharmony_ci memset (dst_p, LIT_CHAR_0, (size_t) (n - k)); 1090425bb815Sopenharmony_ci dst_p += n - k; 1091425bb815Sopenharmony_ci 1092425bb815Sopenharmony_ci JERRY_ASSERT (dst_p <= buffer_p + buffer_size); 1093425bb815Sopenharmony_ci return (lit_utf8_size_t) (dst_p - buffer_p); 1094425bb815Sopenharmony_ci } 1095425bb815Sopenharmony_ci 1096425bb815Sopenharmony_ci if (0 < n && n <= 21) 1097425bb815Sopenharmony_ci { 1098425bb815Sopenharmony_ci /* 7. */ 1099425bb815Sopenharmony_ci memmove (dst_p + n + 1, dst_p + n, (size_t) (k - n)); 1100425bb815Sopenharmony_ci *(dst_p + n) = LIT_CHAR_DOT; 1101425bb815Sopenharmony_ci dst_p += k + 1; 1102425bb815Sopenharmony_ci 1103425bb815Sopenharmony_ci JERRY_ASSERT (dst_p <= buffer_p + buffer_size); 1104425bb815Sopenharmony_ci return (lit_utf8_size_t) (dst_p - buffer_p); 1105425bb815Sopenharmony_ci } 1106425bb815Sopenharmony_ci 1107425bb815Sopenharmony_ci if (-6 < n && n <= 0) 1108425bb815Sopenharmony_ci { 1109425bb815Sopenharmony_ci /* 8. */ 1110425bb815Sopenharmony_ci memmove (dst_p + 2 - n, dst_p, (size_t) k); 1111425bb815Sopenharmony_ci memset (dst_p + 2, LIT_CHAR_0, (size_t) -n); 1112425bb815Sopenharmony_ci *dst_p = LIT_CHAR_0; 1113425bb815Sopenharmony_ci *(dst_p + 1) = LIT_CHAR_DOT; 1114425bb815Sopenharmony_ci dst_p += k - n + 2; 1115425bb815Sopenharmony_ci 1116425bb815Sopenharmony_ci JERRY_ASSERT (dst_p <= buffer_p + buffer_size); 1117425bb815Sopenharmony_ci return (lit_utf8_size_t) (dst_p - buffer_p); 1118425bb815Sopenharmony_ci } 1119425bb815Sopenharmony_ci 1120425bb815Sopenharmony_ci if (k == 1) 1121425bb815Sopenharmony_ci { 1122425bb815Sopenharmony_ci /* 9. */ 1123425bb815Sopenharmony_ci dst_p++; 1124425bb815Sopenharmony_ci } 1125425bb815Sopenharmony_ci else 1126425bb815Sopenharmony_ci { 1127425bb815Sopenharmony_ci /* 10. */ 1128425bb815Sopenharmony_ci memmove (dst_p + 2, dst_p + 1, (size_t) (k - 1)); 1129425bb815Sopenharmony_ci *(dst_p + 1) = LIT_CHAR_DOT; 1130425bb815Sopenharmony_ci dst_p += k + 1; 1131425bb815Sopenharmony_ci } 1132425bb815Sopenharmony_ci 1133425bb815Sopenharmony_ci /* 9., 10. */ 1134425bb815Sopenharmony_ci *dst_p++ = LIT_CHAR_LOWERCASE_E; 1135425bb815Sopenharmony_ci *dst_p++ = (n >= 1) ? LIT_CHAR_PLUS : LIT_CHAR_MINUS; 1136425bb815Sopenharmony_ci uint32_t t = (uint32_t) (n >= 1 ? (n - 1) : -(n - 1)); 1137425bb815Sopenharmony_ci 1138425bb815Sopenharmony_ci dst_p += ecma_uint32_to_utf8_string (t, dst_p, (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); 1139425bb815Sopenharmony_ci 1140425bb815Sopenharmony_ci JERRY_ASSERT (dst_p <= buffer_p + buffer_size); 1141425bb815Sopenharmony_ci 1142425bb815Sopenharmony_ci return (lit_utf8_size_t) (dst_p - buffer_p); 1143425bb815Sopenharmony_ci} /* ecma_number_to_utf8_string */ 1144425bb815Sopenharmony_ci 1145425bb815Sopenharmony_ci/** 1146425bb815Sopenharmony_ci * @} 1147425bb815Sopenharmony_ci * @} 1148425bb815Sopenharmony_ci */ 1149