diff --git a/jerry-core/ecma/base/ecma-helpers-conversion.c b/jerry-core/ecma/base/ecma-helpers-conversion.c index 25baa6a83..bd279a661 100644 --- a/jerry-core/ecma/base/ecma-helpers-conversion.c +++ b/jerry-core/ecma/base/ecma-helpers-conversion.c @@ -812,7 +812,48 @@ ecma_number_to_decimal (ecma_number_t num, /**< ecma-number */ JERRY_ASSERT (!ecma_number_is_infinity (num)); JERRY_ASSERT (!ecma_number_is_negative (num)); +#if JERRY_NUMBER_TYPE_FLOAT64 return ecma_errol0_dtoa ((double) num, out_digits_p, out_decimal_exp_p); +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ + /* Float32: snprintf with ECMA_NUMBER_MAX_DIGITS significant digits guarantees round-trip. + * Using %e gives "D.DDDDDDDDe±EEE" which we parse into digits + decimal exponent. */ + char buf[ECMA_NUMBER_MAX_DIGITS + 16]; + snprintf (buf, sizeof (buf), "%.*e", ECMA_NUMBER_MAX_DIGITS - 1, (double) num); + + char *p = buf; + lit_utf8_byte_t *out_p = out_digits_p; + int32_t k = 0; + + *out_p++ = (lit_utf8_byte_t) *p++; /* first significant digit */ + k++; + p++; /* skip '.' */ + + while (*p != 'e' && *p != 'E') + { + *out_p++ = (lit_utf8_byte_t) *p++; + k++; + } + + /* strip trailing zeros */ + while (k > 1 && out_digits_p[k - 1] == '0') + { + k--; + } + + p++; /* skip 'e' */ + int32_t exp_sign = (*p == '-') ? -1 : 1; + p++; /* skip sign */ + int32_t exponent = 0; + while (*p) + { + exponent = exponent * 10 + (*p++ - '0'); + } + + /* decimal exponent convention: n=1 means first digit is units, n=0 means "0.d..." */ + *out_decimal_exp_p = exp_sign * exponent + 1; + + return (lit_utf8_size_t) k; +#endif /* JERRY_NUMBER_TYPE_FLOAT64 */ } /* ecma_number_to_decimal */ /**