diff --git a/src/libecmaobjects/ecma-globals.h b/src/libecmaobjects/ecma-globals.h index 7f96c622c..5df5b7d3e 100644 --- a/src/libecmaobjects/ecma-globals.h +++ b/src/libecmaobjects/ecma-globals.h @@ -466,7 +466,7 @@ typedef float ecma_number_t; /** * Maximum number of characters in string representation of ecma-number */ -#define ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER 512 +#define ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER 64 /** * Maximum number of characters in string representation of ecma-uint32 diff --git a/src/libecmaobjects/ecma-helpers-conversion.c b/src/libecmaobjects/ecma-helpers-conversion.c index a90c5c5a9..f403c3792 100644 --- a/src/libecmaobjects/ecma-helpers-conversion.c +++ b/src/libecmaobjects/ecma-helpers-conversion.c @@ -134,11 +134,13 @@ ecma_number_to_int32 (ecma_number_t value) /**< unsigned 32-bit integer value */ * * See also: * ECMA-262 v5, 9.8.1 + * + * @return length of zt-string */ -void +ecma_length_t ecma_number_to_zt_string (ecma_number_t num, /**< ecma-number */ ecma_char_t *buffer_p, /**< buffer for zt-string */ - size_t buffer_size) /**< size of buffer */ + ssize_t buffer_size) /**< size of buffer */ { TODO (Support UTF-16); @@ -149,161 +151,159 @@ ecma_number_to_zt_string (ecma_number_t num, /**< ecma-number */ ecma_char_t e_char = 'e'; ecma_char_t null_char = '\0'; - // 1. if (ecma_number_is_nan (num)) { + // 1. FIXME (/* Assert that buffer's size is enough */); - __strncpy ((char*) buffer_p, (char*) ecma_get_magic_string_zt (ECMA_MAGIC_STRING_NAN), buffer_size); - - return; - } - - ecma_char_t *dst_p = buffer_p; - - // 2. - if (ecma_number_is_zero (num)) - { - *dst_p++ = digits_chars[0]; - *dst_p++ = null_char; - - JERRY_ASSERT ((uint8_t*)dst_p - (uint8_t*)buffer_p <= (ssize_t) buffer_size); - - return; - } - - // 3. - if (ecma_number_is_negative (num)) - { - *dst_p++ = minus_char; - size_t new_buffer_size = (size_t) ((ssize_t) buffer_size - ((uint8_t*)dst_p - (uint8_t*)buffer_p)); - ecma_number_to_zt_string (ecma_number_negate (num), dst_p, new_buffer_size); - - return; - } - - // 4. - if (ecma_number_is_infinity (num)) - { - FIXME (/* Assert that buffer's size is enough */); - __strncpy ((char*) buffer_p, (char*) ecma_get_magic_string_zt (ECMA_MAGIC_STRING_INFINITY), buffer_size); - - return; - } - - // 5. - uint64_t fraction; - int32_t exponent; - int32_t dot_shift; - dot_shift = ecma_number_get_fraction_and_exponent (num, &fraction, &exponent); - - FIXME (Decimal representation); - - uint64_t s = fraction; - int32_t n = exponent + 1; - int32_t k = dot_shift; - - JERRY_ASSERT (s != 0); - while (!(s & 1)) - { - s >>= 1; - k--; - } - - // 6. - if (k <= n && n <= 21) - { - for (int32_t i = 0; i < k; i++) - { - uint64_t bit_mask = 1ul << (k - i - 1); - *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; - } - - for (int32_t i = 0; i < n - k; i++) - { - *dst_p++ = digits_chars[0]; - } - } - else if (0 < n && n <= 21) - { - // 7. - for (int32_t i = 0; i < n; i++) - { - uint64_t bit_mask = 1ul << (k - i - 1); - *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; - } - - *dst_p++ = dot_char; - - for (int32_t i = n; i < k; i++) - { - uint64_t bit_mask = 1ul << (k - i - 1); - *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; - } - } - else if (-6 <= n && n <= 0) - { - // 8. - *dst_p++ = digits_chars[0]; - *dst_p++ = '.'; - - for (int32_t i = 0; i < k; i++) - { - uint64_t bit_mask = 1ul << (k - i - 1); - *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; - } + __strncpy ((char*) buffer_p, (char*) ecma_get_magic_string_zt (ECMA_MAGIC_STRING_NAN), (size_t) buffer_size); } else { - if (k == 1) - { - // 9. - *dst_p++ = digits_chars [s ? 1 : 0]; - } - else - { - // 10. - uint64_t bit_mask = 1ul << (k - 1); - *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; - *dst_p++ = dot_char; - for (int32_t i = 1; i < k; i++) - { - bit_mask = 1ul << (k - i - 1); - *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; - } - } + ecma_char_t *dst_p = buffer_p; - // 9., 10. - *dst_p++ = e_char; - *dst_p++ = (n >= 1) ? plus_char : minus_char; - int32_t t = (n >= 1) ? (n - 1) : -(n - 1); - - if (t == 0) + if (ecma_number_is_zero (num)) { + // 2. *dst_p++ = digits_chars[0]; + *dst_p++ = null_char; + + JERRY_ASSERT ((uint8_t*)dst_p - (uint8_t*)buffer_p <= (ssize_t) buffer_size); + } + else if (ecma_number_is_negative (num)) + { + // 3. + *dst_p++ = minus_char; + ssize_t new_buffer_size = (buffer_size - ((uint8_t*)dst_p - (uint8_t*)buffer_p)); + ecma_number_to_zt_string (ecma_number_negate (num), dst_p, new_buffer_size); + } + else if (ecma_number_is_infinity (num)) + { + // 4. + FIXME (/* Assert that buffer's size is enough */); + __strncpy ((char*) buffer_p, (char*) ecma_get_magic_string_zt (ECMA_MAGIC_STRING_INFINITY), (size_t) buffer_size); } else { - uint32_t t_bit = (1u << 31); + // 5. + uint64_t fraction; + int32_t exponent; + int32_t dot_shift; + dot_shift = ecma_number_get_fraction_and_exponent (num, &fraction, &exponent); - while ((t & (int32_t) t_bit) == 0) + FIXME (Decimal representation); + + uint64_t s = fraction; + int32_t n = exponent + 1; + int32_t k = dot_shift; + + JERRY_ASSERT (s != 0); + while (!(s & 1)) { - t_bit >>= 1; - - JERRY_ASSERT (t_bit != 0); + s >>= 1; + k--; } - while (t_bit != 0) + // 6. + if (k <= n && n <= 21) { - *dst_p++ = digits_chars [(t & (int32_t) t_bit) ? 1 : 0]; + for (int32_t i = 0; i < k; i++) + { + uint64_t bit_mask = 1ul << (k - i - 1); + *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; + } - t_bit >>= 1; + for (int32_t i = 0; i < n - k; i++) + { + *dst_p++ = digits_chars[0]; + } } + else if (0 < n && n <= 21) + { + // 7. + for (int32_t i = 0; i < n; i++) + { + uint64_t bit_mask = 1ul << (k - i - 1); + *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; + } + + *dst_p++ = dot_char; + + for (int32_t i = n; i < k; i++) + { + uint64_t bit_mask = 1ul << (k - i - 1); + *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; + } + } + else if (-6 <= n && n <= 0) + { + // 8. + *dst_p++ = digits_chars[0]; + *dst_p++ = '.'; + + for (int32_t i = 0; i < k; i++) + { + uint64_t bit_mask = 1ul << (k - i - 1); + *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; + } + } + else + { + if (k == 1) + { + // 9. + *dst_p++ = digits_chars [s ? 1 : 0]; + } + else + { + // 10. + uint64_t bit_mask = 1ul << (k - 1); + *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; + *dst_p++ = dot_char; + for (int32_t i = 1; i < k; i++) + { + bit_mask = 1ul << (k - i - 1); + *dst_p++ = digits_chars [(s & bit_mask) ? 1 : 0]; + } + } + + // 9., 10. + *dst_p++ = e_char; + *dst_p++ = (n >= 1) ? plus_char : minus_char; + int32_t t = (n >= 1) ? (n - 1) : -(n - 1); + + if (t == 0) + { + *dst_p++ = digits_chars[0]; + } + else + { + uint32_t t_bit = (1u << 31); + + while ((t & (int32_t) t_bit) == 0) + { + t_bit >>= 1; + + JERRY_ASSERT (t_bit != 0); + } + + while (t_bit != 0) + { + *dst_p++ = digits_chars [(t & (int32_t) t_bit) ? 1 : 0]; + + t_bit >>= 1; + } + } + } + + *dst_p++ = null_char; + + JERRY_ASSERT ((uint8_t*)dst_p - (uint8_t*)buffer_p <= (ssize_t) buffer_size); } } - *dst_p++ = null_char; + ecma_length_t length = (ecma_length_t) __strlen ((char*) buffer_p); - JERRY_ASSERT ((uint8_t*)dst_p - (uint8_t*)buffer_p <= (ssize_t) buffer_size); + return length; } /* ecma_number_to_zt_string */ /** diff --git a/src/libecmaobjects/ecma-helpers-string.c b/src/libecmaobjects/ecma-helpers-string.c index 9414cc844..b370cc96f 100644 --- a/src/libecmaobjects/ecma-helpers-string.c +++ b/src/libecmaobjects/ecma-helpers-string.c @@ -246,7 +246,7 @@ ecma_get_ecma_string_length (ecma_string_t *string_desc_p) /**< ecma-string desc * Convert ecma-string to number */ ecma_number_t -ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */ +ecma_string_to_number (ecma_string_t *str_p) /**< ecma-string */ { JERRY_ASSERT (str_p != NULL); @@ -264,13 +264,46 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */ ssize_t bytes_copied = ecma_string_to_zt_string (str_p, zt_string_buffer, - sizeof (zt_string_buffer)); + (ssize_t) sizeof (zt_string_buffer)); JERRY_ASSERT (bytes_copied > 0); - + return ecma_zt_string_to_number (zt_string_buffer); } } /* ecma_string_to_number */ +/** + * Get size of buffer required to store the ecma-string in zt-form. + */ +static ssize_t +ecma_string_get_required_buffer_size_for_zt_form (const ecma_string_t *string_desc_p) /**< ecma-string */ +{ + ecma_length_t string_length = 0; + + switch ((ecma_string_container_t)string_desc_p->container) + { + case ECMA_STRING_CONTAINER_IN_DESCRIPTOR: + case ECMA_STRING_CONTAINER_HEAP_CHUNKS: + case ECMA_STRING_CONTAINER_LIT_TABLE: + { + JERRY_ASSERT (string_desc_p->is_length_valid); + + string_length = string_desc_p->length; + + break; + } + + case ECMA_STRING_CONTAINER_HEAP_NUMBER: + { + string_length = (string_desc_p->is_length_valid ? + string_desc_p->length : ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); + + break; + } + } + + return (ssize_t) ((ssize_t) sizeof (ecma_char_t) * (string_length + 1)); +} /* ecma_string_get_required_buffer_size_for_zt_form */ + /** * Copy ecma-string's contents to a buffer. * @@ -281,23 +314,21 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */ * as negation of buffer size, that is required to hold the string's content. */ ssize_t -ecma_string_to_zt_string (const ecma_string_t *string_desc_p, /**< ecma-string descriptor */ +ecma_string_to_zt_string (ecma_string_t *string_desc_p, /**< ecma-string descriptor */ ecma_char_t *buffer_p, /**< destination buffer */ - size_t buffer_size) /**< size of buffer */ + ssize_t buffer_size) /**< size of buffer */ { JERRY_ASSERT (string_desc_p != NULL); JERRY_ASSERT (string_desc_p->refs > 0); JERRY_ASSERT (buffer_p != NULL); JERRY_ASSERT (buffer_size > 0); - JERRY_ASSERT (string_desc_p->is_length_valid); - - const ecma_length_t string_length = string_desc_p->length; - size_t required_buffer_size = sizeof (ecma_char_t) * string_length + 1 /* for zero char */; + ssize_t required_buffer_size = ecma_string_get_required_buffer_size_for_zt_form (string_desc_p); + ssize_t bytes_copied = 0; if (required_buffer_size > buffer_size) { - return - (ssize_t) required_buffer_size; + return -required_buffer_size; } ecma_char_t *dest_p = buffer_p; @@ -306,13 +337,21 @@ ecma_string_to_zt_string (const ecma_string_t *string_desc_p, /**< ecma-string d { case ECMA_STRING_CONTAINER_IN_DESCRIPTOR: { + JERRY_ASSERT (string_desc_p->is_length_valid); + ecma_length_t string_length = string_desc_p->length; + __memcpy (dest_p, string_desc_p->u.chars, string_length * sizeof (ecma_char_t)); dest_p += string_length; + *dest_p++ = '\0'; + bytes_copied = (dest_p - buffer_p) * ((ssize_t) sizeof (ecma_char_t)); break; } case ECMA_STRING_CONTAINER_HEAP_CHUNKS: { + JERRY_ASSERT (string_desc_p->is_length_valid); + ecma_length_t string_length = string_desc_p->length; + ecma_collection_chunk_t *string_chunk_p = ECMA_GET_POINTER (string_desc_p->u.chunk_cp); const ecma_length_t max_chars_in_chunk = sizeof (string_chunk_p->data) / sizeof (ecma_char_t); @@ -330,18 +369,47 @@ ecma_string_to_zt_string (const ecma_string_t *string_desc_p, /**< ecma-string d string_chunk_p = ECMA_GET_POINTER(string_chunk_p->next_chunk_cp); } + *dest_p++ = '\0'; + bytes_copied = (dest_p - buffer_p) * ((ssize_t) sizeof (ecma_char_t)); + break; } case ECMA_STRING_CONTAINER_LIT_TABLE: + { + bytes_copied = try_get_string_by_idx ((uint8_t) string_desc_p->u.lit_index, + buffer_p, + buffer_size); + + break; + } case ECMA_STRING_CONTAINER_HEAP_NUMBER: { - JERRY_UNIMPLEMENTED(); + const ssize_t buffer_size_required = (ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER + 1) * sizeof (ecma_char_t); + if (buffer_size_required < buffer_size) + { + return -(ssize_t) buffer_size_required; + } + + ecma_number_t *num_p = ECMA_GET_POINTER (string_desc_p->u.number_cp); + + ecma_length_t length = ecma_number_to_zt_string (*num_p, buffer_p, buffer_size); + + if (!string_desc_p->is_length_valid) + { + string_desc_p->length = length; + string_desc_p->is_length_valid = true; + } + + JERRY_ASSERT (string_desc_p->is_length_valid + && string_desc_p->length == length); + + bytes_copied = (length + 1) * ((ssize_t) sizeof (ecma_char_t)); } } - *dest_p = '\0'; + JERRY_ASSERT (bytes_copied > 0 && bytes_copied <= required_buffer_size); - return (ssize_t) required_buffer_size; + return bytes_copied; } /* ecma_string_to_zt_string */ /** diff --git a/src/libecmaobjects/ecma-helpers.h b/src/libecmaobjects/ecma-helpers.h index e2c21e413..d9979f4db 100644 --- a/src/libecmaobjects/ecma-helpers.h +++ b/src/libecmaobjects/ecma-helpers.h @@ -92,10 +92,10 @@ extern ecma_string_t* ecma_new_ecma_string_from_lit_index (literal_index_t lit_i extern void ecma_ref_ecma_string (ecma_string_t *string_desc_p); extern void ecma_deref_ecma_string (ecma_string_t *string_p); extern ecma_length_t ecma_get_ecma_string_length (ecma_string_t *string_desc_p); -extern ecma_number_t ecma_string_to_number (const ecma_string_t *str_p); -extern ssize_t ecma_string_to_zt_string (const ecma_string_t *string_desc_p, +extern ecma_number_t ecma_string_to_number (ecma_string_t *str_p); +extern ssize_t ecma_string_to_zt_string (ecma_string_t *string_desc_p, ecma_char_t *buffer_p, - size_t buffer_size); + ssize_t buffer_size); extern int32_t ecma_compare_zt_string_to_zt_string (const ecma_char_t *string1_p, const ecma_char_t *string2_p); extern bool ecma_compare_ecma_string_to_ecma_string (const ecma_string_t *string1_p, const ecma_string_t *string2_p); @@ -190,7 +190,7 @@ extern void ecma_uint32_to_string (uint32_t value, ecma_char_t *out_buffer_p, si extern uint32_t ecma_number_to_uint32 (ecma_number_t value); extern int32_t ecma_number_to_int32 (ecma_number_t value); extern ecma_number_t ecma_uint32_to_number (uint32_t value); -extern void ecma_number_to_zt_string (ecma_number_t num, ecma_char_t *buffer_p, size_t buffer_size); +extern ecma_length_t ecma_number_to_zt_string (ecma_number_t num, ecma_char_t *buffer_p, ssize_t buffer_size); #endif /* !JERRY_ECMA_HELPERS_H */