/** * The Date object's 'parse' routine * * See also: * ECMA-262 v5, 15.9.4.2 * ECMA-262 v5, 15.9.1.15 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_date_parse (ecma_value_t this_arg __attr_unused___, /**< this argument */ ecma_value_t arg) /**< string */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ecma_number_t *date_num_p = ecma_alloc_number (); *date_num_p = ecma_number_make_nan (); /* Date Time String fromat (ECMA-262 v5, 15.9.1.15) */ ECMA_TRY_CATCH (date_str_value, ecma_op_to_string (arg), ret_value); ecma_string_t *date_str_p = ecma_get_string_from_value (date_str_value); lit_utf8_size_t date_str_size = ecma_string_get_size (date_str_p); MEM_DEFINE_LOCAL_ARRAY (date_start_p, date_str_size, lit_utf8_byte_t); ecma_string_to_utf8_string (date_str_p, date_start_p, (ssize_t) date_str_size); lit_utf8_iterator_t iter = lit_utf8_iterator_create (date_start_p, date_str_size); /* 1. read year */ ecma_number_t year = ecma_date_parse_date_chars (&iter, 4); if (!ecma_number_is_nan (year) && year >= 0) { ecma_number_t month = ECMA_NUMBER_ONE; ecma_number_t day = ECMA_NUMBER_ONE; ecma_number_t time = ECMA_NUMBER_ZERO; /* 2. read month if any */ if (!lit_utf8_iterator_is_eos (&iter) && lit_utf8_iterator_peek_next (&iter) == '-') { /* eat up '-' */ lit_utf8_iterator_incr (&iter); month = ecma_date_parse_date_chars (&iter, 2); if (month > 12 || month < 1) { month = ecma_number_make_nan (); } } /* 3. read day if any */ if (!lit_utf8_iterator_is_eos (&iter) && lit_utf8_iterator_peek_next (&iter) == '-') { /* eat up '-' */ lit_utf8_iterator_incr (&iter); day = ecma_date_parse_date_chars (&iter, 2); if (day < 1 || day > 31) { day = ecma_number_make_nan (); } } /* 4. read time if any */ if (!lit_utf8_iterator_is_eos (&iter) && lit_utf8_iterator_peek_next (&iter) == 'T') { ecma_number_t hours = ECMA_NUMBER_ZERO; ecma_number_t minutes = ECMA_NUMBER_ZERO; ecma_number_t seconds = ECMA_NUMBER_ZERO; ecma_number_t milliseconds = ECMA_NUMBER_ZERO; ecma_length_t num_of_visited_chars = lit_utf8_iterator_get_index (&iter); ecma_length_t date_str_len = lit_utf8_string_length (iter.buf_p, iter.buf_size) - 1; if ((date_str_len - num_of_visited_chars) >= 5) { /* eat up 'T' */ lit_utf8_iterator_incr (&iter); /* 4.1 read hours and minutes */ hours = ecma_date_parse_date_chars (&iter, 2); if (hours < 0 || hours > 24) { hours = ecma_number_make_nan (); } else if (hours == 24) { hours = ECMA_NUMBER_ZERO; } /* eat up ':' */ lit_utf8_iterator_incr (&iter); minutes = ecma_date_parse_date_chars (&iter, 2); if (minutes < 0 || minutes > 59) { minutes = ecma_number_make_nan (); } /* 4.2 read seconds if any */ if (!lit_utf8_iterator_is_eos (&iter) && lit_utf8_iterator_peek_next (&iter) == ':') { /* eat up ':' */ lit_utf8_iterator_incr (&iter); seconds = ecma_date_parse_date_chars (&iter, 2); if (seconds < 0 || seconds > 59) { seconds = ecma_number_make_nan (); } /* 4.3 read milliseconds if any */ if (!lit_utf8_iterator_is_eos (&iter) && lit_utf8_iterator_peek_next (&iter) == '.') { /* eat up '.' */ lit_utf8_iterator_incr (&iter); milliseconds = ecma_date_parse_date_chars (&iter, 3); if (milliseconds < 0) { milliseconds = ecma_number_make_nan (); } } } time = ecma_date_make_time (hours, minutes, seconds, milliseconds); } else { time = ecma_number_make_nan (); } /* 4.4 read timezone if any */ if (!lit_utf8_iterator_is_eos (&iter) && lit_utf8_iterator_peek_next (&iter) == 'Z' && !ecma_number_is_nan (time)) { lit_utf8_iterator_incr (&iter); time = ecma_date_utc (ecma_date_make_time (hours, minutes, seconds, milliseconds)); } else if (!lit_utf8_iterator_is_eos (&iter) && (lit_utf8_iterator_peek_next (&iter) == '+' || lit_utf8_iterator_peek_next (&iter) == '-')) { ecma_length_t num_of_visited_chars = lit_utf8_iterator_get_index (&iter); ecma_length_t date_str_len = lit_utf8_string_length (iter.buf_p, iter.buf_size) - 1; if ((date_str_len - num_of_visited_chars) == 5) { bool is_negative = false; if (lit_utf8_iterator_peek_next (&iter) == '-') { is_negative = true; } /* eat up '+/-' */ lit_utf8_iterator_incr (&iter); /* read hours and minutes */ hours = ecma_date_parse_date_chars (&iter, 2); if (hours < 0 || hours > 24) { hours = ecma_number_make_nan (); } else if (hours == 24) { hours = ECMA_NUMBER_ZERO; } /* eat up ':' */ lit_utf8_iterator_incr (&iter); minutes = ecma_date_parse_date_chars (&iter, 2); if (minutes < 0 || minutes > 59) { minutes = ecma_number_make_nan (); } if (is_negative) { time += ecma_date_make_time (hours, minutes, ECMA_NUMBER_ZERO, ECMA_NUMBER_ZERO); } else { time -= ecma_date_make_time (hours, minutes, ECMA_NUMBER_ZERO, ECMA_NUMBER_ZERO); } } } } if (lit_utf8_iterator_is_eos (&iter)) { ecma_number_t date = ecma_date_make_day (year, month - 1, day); *date_num_p = ecma_date_make_date (date, time); } } ret_value = ecma_make_normal_completion_value (ecma_make_number_value (date_num_p)); MEM_FINALIZE_LOCAL_ARRAY (date_start_p); ECMA_FINALIZE (date_str_value); return ret_value; } /* ecma_builtin_date_parse */
int main (int __attr_unused___ argc, char __attr_unused___ **argv) { TEST_INIT (); mem_init (); lit_utf8_byte_t utf8_string[max_bytes_in_string]; ecma_char_t code_units[max_code_units_in_string]; lit_utf8_iterator_pos_t saved_positions[max_code_units_in_string]; for (int i = 0; i < test_iters; i++) { lit_utf8_size_t utf8_string_size = (i == 0) ? 0 : (lit_utf8_size_t) (rand () % max_bytes_in_string); ecma_length_t length = generate_utf8_string (utf8_string, utf8_string_size); JERRY_ASSERT (lit_utf8_string_length (utf8_string, utf8_string_size) == length); lit_utf8_iterator_t iter = lit_utf8_iterator_create (utf8_string, utf8_string_size); ecma_length_t calculated_length = 0; ecma_length_t code_units_count = 0; while (!lit_utf8_iterator_is_eos (&iter)) { code_units[code_units_count] = lit_utf8_iterator_peek_next (&iter); saved_positions[code_units_count] = lit_utf8_iterator_get_pos (&iter); code_units_count++; calculated_length++; lit_utf8_iterator_incr (&iter); } JERRY_ASSERT (length == calculated_length); if (code_units_count > 0) { for (int j = 0; j < test_subiters; j++) { ecma_length_t index = (ecma_length_t) rand () % code_units_count; lit_utf8_iterator_seek (&iter, saved_positions[index]); JERRY_ASSERT (lit_utf8_iterator_peek_next (&iter) == code_units[index]); JERRY_ASSERT (lit_utf8_iterator_get_index (&iter) == index); } } lit_utf8_iterator_seek_eos (&iter); while (!lit_utf8_iterator_is_bos (&iter)) { JERRY_ASSERT (code_units_count > 0); calculated_length--; JERRY_ASSERT (code_units[calculated_length] == lit_utf8_iterator_peek_prev (&iter)); lit_utf8_iterator_decr (&iter); } JERRY_ASSERT (calculated_length == 0); while (!lit_utf8_iterator_is_eos (&iter)) { ecma_char_t code_unit = lit_utf8_iterator_read_next (&iter); JERRY_ASSERT (code_unit == code_units[calculated_length]); calculated_length++; } JERRY_ASSERT (length == calculated_length); while (!lit_utf8_iterator_is_bos (&iter)) { JERRY_ASSERT (code_units_count > 0); calculated_length--; JERRY_ASSERT (code_units[calculated_length] == lit_utf8_iterator_read_prev (&iter)); } JERRY_ASSERT (calculated_length == 0); } /* Overlong-encoded code point */ lit_utf8_byte_t invalid_utf8_string_1[] = {0xC0, 0x82}; JERRY_ASSERT (!lit_is_utf8_string_valid (invalid_utf8_string_1, sizeof (invalid_utf8_string_1))); /* Overlong-encoded code point */ lit_utf8_byte_t invalid_utf8_string_2[] = {0xE0, 0x80, 0x81}; JERRY_ASSERT (!lit_is_utf8_string_valid (invalid_utf8_string_2, sizeof (invalid_utf8_string_2))); /* Pair of surrogates: 0xD901 0xDFF0 which encode Unicode character 0x507F0 */ lit_utf8_byte_t invalid_utf8_string_3[] = {0xED, 0xA4, 0x81, 0xED, 0xBF, 0xB0}; JERRY_ASSERT (!lit_is_utf8_string_valid (invalid_utf8_string_3, sizeof (invalid_utf8_string_3))); /* Isolated high surrogate 0xD901 */ lit_utf8_byte_t valid_utf8_string_1[] = {0xED, 0xA4, 0x81}; JERRY_ASSERT (lit_is_utf8_string_valid (valid_utf8_string_1, sizeof (valid_utf8_string_1))); /* 4-byte long utf-8 character - Unicode character 0x507F0 */ lit_utf8_byte_t valid_utf8_string_2[] = {0xF1, 0x90, 0x9F, 0xB0}; JERRY_ASSERT (lit_is_utf8_string_valid (valid_utf8_string_2, sizeof (valid_utf8_string_2))); lit_utf8_byte_t buf[] = {0xF0, 0x90, 0x8D, 0x88}; lit_code_point_t code_point; lit_utf8_size_t bytes_count = lit_read_code_point_from_utf8 (buf, sizeof (buf), &code_point); JERRY_ASSERT (bytes_count == 4); JERRY_ASSERT (code_point == 0x10348); lit_utf8_byte_t res_buf[3]; lit_utf8_size_t res_size; res_size = lit_code_unit_to_utf8 (0x73, res_buf); JERRY_ASSERT (res_size == 1); JERRY_ASSERT (res_buf[0] == 0x73); res_size = lit_code_unit_to_utf8 (0x41A, res_buf); JERRY_ASSERT (res_size == 2); JERRY_ASSERT (res_buf[0] == 0xD0); JERRY_ASSERT (res_buf[1] == 0x9A); res_size = lit_code_unit_to_utf8 (0xD7FF, res_buf); JERRY_ASSERT (res_size == 3); JERRY_ASSERT (res_buf[0] == 0xED); JERRY_ASSERT (res_buf[1] == 0x9F); JERRY_ASSERT (res_buf[2] == 0xBF); lit_utf8_byte_t bytes[] = {0xF0, 0x90, 0x8D, 0x88}; lit_utf8_iterator_t iter = lit_utf8_iterator_create (bytes, sizeof (bytes)); ecma_char_t code_unit = lit_utf8_iterator_read_next (&iter); JERRY_ASSERT (!lit_utf8_iterator_is_eos (&iter)); JERRY_ASSERT (code_unit == 0xD800); code_unit = lit_utf8_iterator_read_next (&iter); JERRY_ASSERT (lit_utf8_iterator_is_eos (&iter)); JERRY_ASSERT (code_unit == 0xDF48); mem_finalize (true); return 0; }