/** * Helper function to try to parse a part of a date string * * @return NaN if cannot read from string, ToNumber() otherwise */ static ecma_number_t ecma_date_parse_date_chars (lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */ const lit_utf8_byte_t *str_end_p, /**< pointer to the end of the string */ uint32_t num_of_chars) /**< number of characters to read and convert */ { JERRY_ASSERT (num_of_chars > 0); const lit_utf8_byte_t *str_start_p = *str_p; while (num_of_chars--) { if (*str_p >= str_end_p || !lit_char_is_decimal_digit (lit_utf8_read_next (str_p))) { return ecma_number_make_nan (); } } return ecma_utf8_string_to_number (str_start_p, (lit_utf8_size_t) (*str_p - str_start_p)); } /* ecma_date_parse_date_chars */
int main (int __attr_unused___ argc, char __attr_unused___ **argv) { TEST_INIT (); jmem_init (); lit_init (); ecma_init (); lit_utf8_byte_t cesu8_string[max_bytes_in_string]; ecma_char_t code_units[max_code_units_in_string]; const lit_utf8_byte_t *saved_positions[max_code_units_in_string]; for (int i = 0; i < test_iters; i++) { lit_utf8_size_t cesu8_string_size = (i == 0) ? 0 : (lit_utf8_size_t) (rand () % max_bytes_in_string); ecma_length_t length = generate_cesu8_string (cesu8_string, cesu8_string_size); ecma_string_t *char_collection_string_p = ecma_new_ecma_string_from_utf8 (cesu8_string, cesu8_string_size); ecma_length_t char_collection_len = ecma_string_get_length (char_collection_string_p); JERRY_ASSERT (char_collection_len == length); ecma_deref_ecma_string (char_collection_string_p); JERRY_ASSERT (lit_utf8_string_length (cesu8_string, cesu8_string_size) == length); const lit_utf8_byte_t *curr_p = cesu8_string; const lit_utf8_byte_t *end_p = cesu8_string + cesu8_string_size; ecma_length_t calculated_length = 0; ecma_length_t code_units_count = 0; while (curr_p < end_p) { code_units[code_units_count] = lit_utf8_peek_next (curr_p); saved_positions[code_units_count] = curr_p; code_units_count++; calculated_length++; lit_utf8_incr (&curr_p); } 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; curr_p = saved_positions[index]; JERRY_ASSERT (lit_utf8_peek_next (curr_p) == code_units[index]); } } curr_p = (lit_utf8_byte_t *) end_p; while (curr_p > cesu8_string) { JERRY_ASSERT (code_units_count > 0); calculated_length--; JERRY_ASSERT (code_units[calculated_length] == lit_utf8_peek_prev (curr_p)); lit_utf8_decr (&curr_p); } JERRY_ASSERT (calculated_length == 0); while (curr_p < end_p) { ecma_char_t code_unit = lit_utf8_read_next (&curr_p); JERRY_ASSERT (code_unit == code_units[calculated_length]); calculated_length++; } JERRY_ASSERT (length == calculated_length); while (curr_p > cesu8_string) { JERRY_ASSERT (code_units_count > 0); calculated_length--; JERRY_ASSERT (code_units[calculated_length] == lit_utf8_read_prev (&curr_p)); } JERRY_ASSERT (calculated_length == 0); } /* Overlong-encoded code point */ lit_utf8_byte_t invalid_cesu8_string_1[] = {0xC0, 0x82}; JERRY_ASSERT (!lit_is_cesu8_string_valid (invalid_cesu8_string_1, sizeof (invalid_cesu8_string_1))); /* Overlong-encoded code point */ lit_utf8_byte_t invalid_cesu8_string_2[] = {0xE0, 0x80, 0x81}; JERRY_ASSERT (!lit_is_cesu8_string_valid (invalid_cesu8_string_2, sizeof (invalid_cesu8_string_2))); /* Pair of surrogates: 0xD901 0xDFF0 which encode Unicode character 0x507F0 */ lit_utf8_byte_t invalid_cesu8_string_3[] = {0xED, 0xA4, 0x81, 0xED, 0xBF, 0xB0}; JERRY_ASSERT (lit_is_cesu8_string_valid (invalid_cesu8_string_3, sizeof (invalid_cesu8_string_3))); /* Isolated high surrogate 0xD901 */ lit_utf8_byte_t valid_utf8_string_1[] = {0xED, 0xA4, 0x81}; JERRY_ASSERT (lit_is_cesu8_string_valid (valid_utf8_string_1, sizeof (valid_utf8_string_1))); 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); ecma_finalize (); lit_finalize (); jmem_finalize (true); return 0; } /* main */
/** * Helper function for finding index of a search string * * This function clamps the given index to the [0, length] range. * If the index is negative, 0 value is used. * If the index is greater than the length of the string, the normalized index will be the length of the string. * NaN is mapped to zero or length depending on the nan_to_zero parameter. * * See also: * ECMA-262 v5, 15.5.4.7,8,11 * * Used by: * - The ecma_builtin_helper_string_prototype_object_index_of helper routine. * - The ecma_builtin_string_prototype_object_replace_match helper routine. * * @return uint32_t - the normalized value of the index */ bool ecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, /**< index */ ecma_string_t *search_str_p, /**< string's length */ bool first_index, /**< whether search for first (t) or last (f) index */ ecma_length_t start_pos, /**< start position */ ecma_length_t *ret_index_p) /**< position found in original string */ { bool match_found = false; const ecma_length_t original_len = ecma_string_get_length (original_str_p); const ecma_length_t search_len = ecma_string_get_length (search_str_p); if (search_len <= original_len) { if (!search_len) { match_found = true; *ret_index_p = first_index ? 0 : original_len; } else { /* create utf8 string from original string and advance to position */ ECMA_STRING_TO_UTF8_STRING (original_str_p, original_str_utf8_p, original_str_size); ecma_length_t index = start_pos; const lit_utf8_byte_t *original_str_curr_p = original_str_utf8_p; for (ecma_length_t idx = 0; idx < index; idx++) { lit_utf8_incr (&original_str_curr_p); } /* create utf8 string from search string */ ECMA_STRING_TO_UTF8_STRING (search_str_p, search_str_utf8_p, search_str_size); const lit_utf8_byte_t *search_str_curr_p = search_str_utf8_p; /* iterate original string and try to match at each position */ bool searching = true; ecma_char_t first_char = lit_utf8_read_next (&search_str_curr_p); while (searching) { /* match as long as possible */ ecma_length_t match_len = 0; const lit_utf8_byte_t *stored_original_str_curr_p = original_str_curr_p; if (match_len < search_len && index + match_len < original_len && lit_utf8_read_next (&original_str_curr_p) == first_char) { const lit_utf8_byte_t *nested_search_str_curr_p = search_str_curr_p; match_len++; while (match_len < search_len && index + match_len < original_len && lit_utf8_read_next (&original_str_curr_p) == lit_utf8_read_next (&nested_search_str_curr_p)) { match_len++; } } /* check for match */ if (match_len == search_len) { match_found = true; *ret_index_p = index; break; } else { /* inc/dec index and update iterators and search condition */ original_str_curr_p = stored_original_str_curr_p; if (first_index) { if ((searching = (index <= original_len - search_len))) { lit_utf8_incr (&original_str_curr_p); index++; } } else { if ((searching = (index > 0))) { lit_utf8_decr (&original_str_curr_p); index--; } } } } ECMA_FINALIZE_UTF8_STRING (search_str_utf8_p, search_str_size); ECMA_FINALIZE_UTF8_STRING (original_str_utf8_p, original_str_size); } } return match_found; } /* ecma_builtin_helper_string_find_index */
/** * Read the input pattern and parse the next token for the RegExp compiler * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t re_parse_next_token (re_parser_ctx_t *parser_ctx_p, /**< RegExp parser context */ re_token_t *out_token_p) /**< out: output token */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); if (parser_ctx_p->input_curr_p >= parser_ctx_p->input_end_p) { out_token_p->type = RE_TOK_EOF; return ret_value; } ecma_char_t ch = lit_utf8_read_next (&parser_ctx_p->input_curr_p); switch (ch) { case LIT_CHAR_VLINE: { out_token_p->type = RE_TOK_ALTERNATIVE; break; } case LIT_CHAR_CIRCUMFLEX: { out_token_p->type = RE_TOK_ASSERT_START; break; } case LIT_CHAR_DOLLAR_SIGN: { out_token_p->type = RE_TOK_ASSERT_END; break; } case LIT_CHAR_DOT: { out_token_p->type = RE_TOK_PERIOD; ret_value = re_parse_iterator (parser_ctx_p, out_token_p); break; } case LIT_CHAR_BACKSLASH: { if (parser_ctx_p->input_curr_p >= parser_ctx_p->input_end_p) { return ecma_raise_syntax_error ("invalid regular experssion"); } out_token_p->type = RE_TOK_CHAR; ch = lit_utf8_read_next (&parser_ctx_p->input_curr_p); if (ch == LIT_CHAR_LOWERCASE_B) { out_token_p->type = RE_TOK_ASSERT_WORD_BOUNDARY; } else if (ch == LIT_CHAR_UPPERCASE_B) { out_token_p->type = RE_TOK_ASSERT_NOT_WORD_BOUNDARY; } else if (ch == LIT_CHAR_LOWERCASE_F) { out_token_p->value = LIT_CHAR_FF; } else if (ch == LIT_CHAR_LOWERCASE_N) { out_token_p->value = LIT_CHAR_LF; } else if (ch == LIT_CHAR_LOWERCASE_T) { out_token_p->value = LIT_CHAR_TAB; } else if (ch == LIT_CHAR_LOWERCASE_R) { out_token_p->value = LIT_CHAR_CR; } else if (ch == LIT_CHAR_LOWERCASE_V) { out_token_p->value = LIT_CHAR_VTAB; } else if (ch == LIT_CHAR_LOWERCASE_C) { if (parser_ctx_p->input_curr_p < parser_ctx_p->input_end_p) { ch = *parser_ctx_p->input_curr_p; if ((ch >= LIT_CHAR_ASCII_UPPERCASE_LETTERS_BEGIN && ch <= LIT_CHAR_ASCII_UPPERCASE_LETTERS_END) || (ch >= LIT_CHAR_ASCII_LOWERCASE_LETTERS_BEGIN && ch <= LIT_CHAR_ASCII_LOWERCASE_LETTERS_END)) { out_token_p->value = (ch % 32); parser_ctx_p->input_curr_p++; } else { out_token_p->value = LIT_CHAR_BACKSLASH; parser_ctx_p->input_curr_p--; } } else { out_token_p->value = LIT_CHAR_BACKSLASH; parser_ctx_p->input_curr_p--; } } else if (ch == LIT_CHAR_LOWERCASE_X && re_hex_lookup (parser_ctx_p, 2)) { lit_code_point_t code_point; if (!lit_read_code_point_from_hex (parser_ctx_p->input_curr_p, 2, &code_point)) { return ecma_raise_syntax_error ("decode error"); } parser_ctx_p->input_curr_p += 2; out_token_p->value = code_point; } else if (ch == LIT_CHAR_LOWERCASE_U && re_hex_lookup (parser_ctx_p, 4)) { lit_code_point_t code_point; if (!lit_read_code_point_from_hex (parser_ctx_p->input_curr_p, 4, &code_point)) { return ecma_raise_syntax_error ("decode error"); } parser_ctx_p->input_curr_p += 4; out_token_p->value = code_point; } else if (ch == LIT_CHAR_LOWERCASE_D) { out_token_p->type = RE_TOK_DIGIT; break; } else if (ch == LIT_CHAR_UPPERCASE_D) { out_token_p->type = RE_TOK_NOT_DIGIT; break; } else if (ch == LIT_CHAR_LOWERCASE_S) { out_token_p->type = RE_TOK_WHITE; break; } else if (ch == LIT_CHAR_UPPERCASE_S) { out_token_p->type = RE_TOK_NOT_WHITE; break; } else if (ch == LIT_CHAR_LOWERCASE_W) { out_token_p->type = RE_TOK_WORD_CHAR; break; } else if (ch == LIT_CHAR_UPPERCASE_W) { out_token_p->type = RE_TOK_NOT_WORD_CHAR; break; } else if (lit_char_is_decimal_digit (ch)) { if (ch == LIT_CHAR_0) { if (parser_ctx_p->input_curr_p < parser_ctx_p->input_end_p && lit_char_is_decimal_digit (*parser_ctx_p->input_curr_p)) { return ecma_raise_syntax_error ("RegExp escape pattern error."); } out_token_p->value = LIT_UNICODE_CODE_POINT_NULL; } else { if (parser_ctx_p->num_of_groups == -1) { re_count_num_of_groups (parser_ctx_p); } if (parser_ctx_p->num_of_groups) { parser_ctx_p->input_curr_p--; uint32_t number = 0; int index = 0; do { if (index >= RE_MAX_RE_DECESC_DIGITS) { ret_value = ecma_raise_syntax_error ("RegExp escape pattern error: decimal escape too long."); return ret_value; } if (parser_ctx_p->input_curr_p >= parser_ctx_p->input_end_p) { break; } ecma_char_t digit = *parser_ctx_p->input_curr_p++; if (!lit_char_is_decimal_digit (digit)) { parser_ctx_p->input_curr_p--; break; } number = number * 10 + lit_char_hex_to_int (digit); index++; } while (true); if ((int) number <= parser_ctx_p->num_of_groups) { out_token_p->type = RE_TOK_BACKREFERENCE; } else /* Invalid backreference, fallback to octal */ { /* Rewind to start of number. */ parser_ctx_p->input_curr_p -= index; /* Try to reparse as octal. */ ecma_char_t digit = *parser_ctx_p->input_curr_p; if (!lit_char_is_octal_digit (digit)) { /* Not octal, keep digit character value. */ number = digit; parser_ctx_p->input_curr_p++; } else { number = re_parse_octal (parser_ctx_p); } } out_token_p->value = number; } else /* Invalid backreference, fallback to octal if possible */ { if (!lit_char_is_octal_digit (ch)) { /* Not octal, keep character value. */ out_token_p->value = ch; } else { parser_ctx_p->input_curr_p--; out_token_p->value = re_parse_octal (parser_ctx_p); } } } } else { out_token_p->value = ch; } ret_value = re_parse_iterator (parser_ctx_p, out_token_p); break; } case LIT_CHAR_LEFT_PAREN: { if (parser_ctx_p->input_curr_p >= parser_ctx_p->input_end_p) { return ecma_raise_syntax_error ("Unterminated group"); } if (*parser_ctx_p->input_curr_p == LIT_CHAR_QUESTION) { parser_ctx_p->input_curr_p++; if (parser_ctx_p->input_curr_p >= parser_ctx_p->input_end_p) { return ecma_raise_syntax_error ("Invalid group"); } ch = *parser_ctx_p->input_curr_p++; if (ch == LIT_CHAR_EQUALS) { /* (?= */ out_token_p->type = RE_TOK_ASSERT_START_POS_LOOKAHEAD; } else if (ch == LIT_CHAR_EXCLAMATION) { /* (?! */ out_token_p->type = RE_TOK_ASSERT_START_NEG_LOOKAHEAD; } else if (ch == LIT_CHAR_COLON) { /* (?: */ out_token_p->type = RE_TOK_START_NON_CAPTURE_GROUP; } else { return ecma_raise_syntax_error ("Invalid group"); } } else { /* ( */ out_token_p->type = RE_TOK_START_CAPTURE_GROUP; } break; } case LIT_CHAR_RIGHT_PAREN: { out_token_p->type = RE_TOK_END_GROUP; ret_value = re_parse_iterator (parser_ctx_p, out_token_p); break; } case LIT_CHAR_LEFT_SQUARE: { out_token_p->type = RE_TOK_START_CHAR_CLASS; if (parser_ctx_p->input_curr_p >= parser_ctx_p->input_end_p) { return ecma_raise_syntax_error ("invalid character class"); } if (*parser_ctx_p->input_curr_p == LIT_CHAR_CIRCUMFLEX) { out_token_p->type = RE_TOK_START_INV_CHAR_CLASS; parser_ctx_p->input_curr_p++; } break; } case LIT_CHAR_QUESTION: case LIT_CHAR_ASTERISK: case LIT_CHAR_PLUS: case LIT_CHAR_LEFT_BRACE: { return ecma_raise_syntax_error ("Invalid RegExp token."); } case LIT_CHAR_NULL: { out_token_p->type = RE_TOK_EOF; break; } default: { out_token_p->type = RE_TOK_CHAR; out_token_p->value = ch; ret_value = re_parse_iterator (parser_ctx_p, out_token_p); break; } } return ret_value; } /* re_parse_next_token */
/** * Read the input pattern and parse the range of character class * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t re_parse_char_class (re_parser_ctx_t *parser_ctx_p, /**< number of classes */ re_char_class_callback append_char_class, /**< callback function, * which adds the char-ranges * to the bytecode */ void *re_ctx_p, /**< regexp compiler context */ re_token_t *out_token_p) /**< out: output token */ { re_token_type_t token_type = ((re_compiler_ctx_t *) re_ctx_p)->current_token.type; out_token_p->qmax = out_token_p->qmin = 1; uint32_t start = RE_CHAR_UNDEF; bool is_range = false; parser_ctx_p->num_of_classes = 0; if (lit_utf8_peek_prev (parser_ctx_p->input_curr_p) != LIT_CHAR_LEFT_SQUARE) { lit_utf8_decr (&parser_ctx_p->input_curr_p); lit_utf8_decr (&parser_ctx_p->input_curr_p); } do { if (parser_ctx_p->input_curr_p >= parser_ctx_p->input_end_p) { return ecma_raise_syntax_error ("invalid character class, end of string"); } uint32_t ch = lit_utf8_read_next (&parser_ctx_p->input_curr_p); if (ch == LIT_CHAR_RIGHT_SQUARE) { if (start != RE_CHAR_UNDEF) { append_char_class (re_ctx_p, start, start); } break; } else if (ch == LIT_CHAR_MINUS) { if (parser_ctx_p->input_curr_p >= parser_ctx_p->input_end_p) { return ecma_raise_syntax_error ("invalid character class, end of string after '-'"); } if (start != RE_CHAR_UNDEF && !is_range && *parser_ctx_p->input_curr_p != LIT_CHAR_RIGHT_SQUARE) { is_range = true; continue; } } else if (ch == LIT_CHAR_BACKSLASH) { if (parser_ctx_p->input_curr_p >= parser_ctx_p->input_end_p) { return ecma_raise_syntax_error ("invalid character class, end of string after '\\'"); } ch = *parser_ctx_p->input_curr_p++; if (ch == LIT_CHAR_LOWERCASE_B) { ch = LIT_CHAR_BS; } else if (ch == LIT_CHAR_LOWERCASE_F) { ch = LIT_CHAR_FF; } else if (ch == LIT_CHAR_LOWERCASE_N) { ch = LIT_CHAR_LF; } else if (ch == LIT_CHAR_LOWERCASE_T) { ch = LIT_CHAR_TAB; } else if (ch == LIT_CHAR_LOWERCASE_R) { ch = LIT_CHAR_CR; } else if (ch == LIT_CHAR_LOWERCASE_V) { ch = LIT_CHAR_VTAB; } else if (ch == LIT_CHAR_LOWERCASE_C) { if (parser_ctx_p->input_curr_p < parser_ctx_p->input_end_p) { ch = *parser_ctx_p->input_curr_p; if ((ch >= LIT_CHAR_ASCII_UPPERCASE_LETTERS_BEGIN && ch <= LIT_CHAR_ASCII_UPPERCASE_LETTERS_END) || (ch >= LIT_CHAR_ASCII_LOWERCASE_LETTERS_BEGIN && ch <= LIT_CHAR_ASCII_LOWERCASE_LETTERS_END) || (ch >= LIT_CHAR_0 && ch <= LIT_CHAR_9)) { /* See ECMA-262 v5, 15.10.2.10 (Point 3) */ ch = (ch % 32); parser_ctx_p->input_curr_p++; } else { ch = LIT_CHAR_LOWERCASE_C; } } } else if (ch == LIT_CHAR_LOWERCASE_X) { lit_code_point_t code_point; if (!lit_read_code_point_from_hex (parser_ctx_p->input_curr_p, 2, &code_point)) { return ecma_raise_syntax_error ("invalid character class, end of string after '\\x'"); } parser_ctx_p->input_curr_p += 2; append_char_class (re_ctx_p, code_point, code_point); } else if (ch == LIT_CHAR_LOWERCASE_U) { lit_code_point_t code_point; if (!lit_read_code_point_from_hex (parser_ctx_p->input_curr_p, 4, &code_point)) { return ecma_raise_syntax_error ("invalid character class, end of string after '\\u'"); } parser_ctx_p->input_curr_p += 4; append_char_class (re_ctx_p, code_point, code_point); } else if (ch == LIT_CHAR_LOWERCASE_D) { /* See ECMA-262 v5, 15.10.2.12 */ append_char_class (re_ctx_p, LIT_CHAR_ASCII_DIGITS_BEGIN, LIT_CHAR_ASCII_DIGITS_END); ch = RE_CHAR_UNDEF; } else if (ch == LIT_CHAR_UPPERCASE_D) { /* See ECMA-262 v5, 15.10.2.12 */ append_char_class (re_ctx_p, LIT_CHAR_NULL, LIT_CHAR_ASCII_DIGITS_BEGIN - 1); append_char_class (re_ctx_p, LIT_CHAR_ASCII_DIGITS_END + 1, LIT_UTF16_CODE_UNIT_MAX); ch = RE_CHAR_UNDEF; } else if (ch == LIT_CHAR_LOWERCASE_S) { /* See ECMA-262 v5, 15.10.2.12 */ append_char_class (re_ctx_p, LIT_CHAR_TAB, LIT_CHAR_CR); append_char_class (re_ctx_p, LIT_CHAR_SP, LIT_CHAR_SP); append_char_class (re_ctx_p, LIT_CHAR_NBSP, LIT_CHAR_NBSP); append_char_class (re_ctx_p, 0x1680UL, 0x1680UL); /* Ogham Space Mark */ append_char_class (re_ctx_p, 0x180EUL, 0x180EUL); /* Mongolian Vowel Separator */ append_char_class (re_ctx_p, 0x2000UL, 0x200AUL); /* En Quad - Hair Space */ append_char_class (re_ctx_p, LIT_CHAR_LS, LIT_CHAR_PS); append_char_class (re_ctx_p, 0x202FUL, 0x202FUL); /* Narrow No-Break Space */ append_char_class (re_ctx_p, 0x205FUL, 0x205FUL); /* Medium Mathematical Space */ append_char_class (re_ctx_p, 0x3000UL, 0x3000UL); /* Ideographic Space */ append_char_class (re_ctx_p, LIT_CHAR_BOM, LIT_CHAR_BOM); ch = RE_CHAR_UNDEF; } else if (ch == LIT_CHAR_UPPERCASE_S) { /* See ECMA-262 v5, 15.10.2.12 */ append_char_class (re_ctx_p, LIT_CHAR_NULL, LIT_CHAR_TAB - 1); append_char_class (re_ctx_p, LIT_CHAR_CR + 1, LIT_CHAR_SP - 1); append_char_class (re_ctx_p, LIT_CHAR_SP + 1, LIT_CHAR_NBSP - 1); append_char_class (re_ctx_p, LIT_CHAR_NBSP + 1, 0x167FUL); append_char_class (re_ctx_p, 0x1681UL, 0x180DUL); append_char_class (re_ctx_p, 0x180FUL, 0x1FFFUL); append_char_class (re_ctx_p, 0x200BUL, LIT_CHAR_LS - 1); append_char_class (re_ctx_p, LIT_CHAR_PS + 1, 0x202EUL); append_char_class (re_ctx_p, 0x2030UL, 0x205EUL); append_char_class (re_ctx_p, 0x2060UL, 0x2FFFUL); append_char_class (re_ctx_p, 0x3001UL, LIT_CHAR_BOM - 1); append_char_class (re_ctx_p, LIT_CHAR_BOM + 1, LIT_UTF16_CODE_UNIT_MAX); ch = RE_CHAR_UNDEF; } else if (ch == LIT_CHAR_LOWERCASE_W) { /* See ECMA-262 v5, 15.10.2.12 */ append_char_class (re_ctx_p, LIT_CHAR_0, LIT_CHAR_9); append_char_class (re_ctx_p, LIT_CHAR_UPPERCASE_A, LIT_CHAR_UPPERCASE_Z); append_char_class (re_ctx_p, LIT_CHAR_UNDERSCORE, LIT_CHAR_UNDERSCORE); append_char_class (re_ctx_p, LIT_CHAR_LOWERCASE_A, LIT_CHAR_LOWERCASE_Z); ch = RE_CHAR_UNDEF; } else if (ch == LIT_CHAR_UPPERCASE_W) { /* See ECMA-262 v5, 15.10.2.12 */ append_char_class (re_ctx_p, LIT_CHAR_NULL, LIT_CHAR_0 - 1); append_char_class (re_ctx_p, LIT_CHAR_9 + 1, LIT_CHAR_UPPERCASE_A - 1); append_char_class (re_ctx_p, LIT_CHAR_UPPERCASE_Z + 1, LIT_CHAR_UNDERSCORE - 1); append_char_class (re_ctx_p, LIT_CHAR_UNDERSCORE + 1, LIT_CHAR_LOWERCASE_A - 1); append_char_class (re_ctx_p, LIT_CHAR_LOWERCASE_Z + 1, LIT_UTF16_CODE_UNIT_MAX); ch = RE_CHAR_UNDEF; } else if (ch <= LIT_UTF16_CODE_UNIT_MAX && lit_char_is_octal_digit ((ecma_char_t) ch) && ch != LIT_CHAR_0) { parser_ctx_p->input_curr_p--; ch = re_parse_octal (parser_ctx_p); } } /* ch == LIT_CHAR_BACKSLASH */ if (ch == RE_CHAR_UNDEF) { if (start != RE_CHAR_UNDEF) { if (is_range) { return ecma_raise_syntax_error ("invalid character class, invalid range"); } else { append_char_class (re_ctx_p, start, start); start = RE_CHAR_UNDEF; } } } else { if (start != RE_CHAR_UNDEF) { if (is_range) { if (start > ch) { return ecma_raise_syntax_error ("invalid character class, wrong order"); } else { append_char_class (re_ctx_p, start, ch); start = RE_CHAR_UNDEF; is_range = false; } } else { append_char_class (re_ctx_p, start, start); start = ch; } } else { start = ch; } } } while (token_type == RE_TOK_START_CHAR_CLASS || token_type == RE_TOK_START_INV_CHAR_CLASS); return re_parse_iterator (parser_ctx_p, out_token_p); } /* re_parse_char_class */
/** * Abstract operation 'Quote' defined in 15.12.3 * * See also: * ECMA-262 v5, 15.12.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_quote (ecma_string_t *string_p) /**< string that should be quoted*/ { /* 1. */ ecma_string_t *quote_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_DOUBLE_QUOTE_CHAR); ecma_string_t *product_str_p = ecma_copy_or_ref_ecma_string (quote_str_p); ecma_string_t *tmp_str_p; ecma_length_t string_size = ecma_string_get_size (string_p); MEM_DEFINE_LOCAL_ARRAY (string_buff, string_size, lit_utf8_byte_t); ssize_t bytes_copied = ecma_string_to_utf8_string (string_p, string_buff, (ssize_t) string_size); JERRY_ASSERT (bytes_copied > 0 || !string_size); lit_utf8_byte_t *str_p = string_buff; const lit_utf8_byte_t *str_end_p = str_p + string_size; while (str_p < str_end_p) { ecma_char_t current_char = lit_utf8_read_next (&str_p); /* 2.a */ if (current_char == LIT_CHAR_BACKSLASH || current_char == LIT_CHAR_DOUBLE_QUOTE) { ecma_string_t *backslash_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BACKSLASH_CHAR); /* 2.a.i */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, backslash_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (backslash_str_p); product_str_p = tmp_str_p; /* 2.a.ii */ ecma_string_t *current_char_str_p = ecma_new_ecma_string_from_code_unit (current_char); tmp_str_p = ecma_concat_ecma_strings (product_str_p, current_char_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (current_char_str_p); product_str_p = tmp_str_p; } /* 2.b */ else if (current_char == LIT_CHAR_BS || current_char == LIT_CHAR_FF || current_char == LIT_CHAR_LF || current_char == LIT_CHAR_CR || current_char == LIT_CHAR_TAB) { ecma_string_t *backslash_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BACKSLASH_CHAR); /* 2.b.i */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, backslash_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (backslash_str_p); product_str_p = tmp_str_p; /* 2.b.ii */ lit_utf8_byte_t abbrev = LIT_CHAR_SP; switch (current_char) { case LIT_CHAR_BS: { abbrev = LIT_CHAR_LOWERCASE_B; break; } case LIT_CHAR_FF: { abbrev = LIT_CHAR_LOWERCASE_F; break; } case LIT_CHAR_LF: { abbrev = LIT_CHAR_LOWERCASE_N; break; } case LIT_CHAR_CR: { abbrev = LIT_CHAR_LOWERCASE_R; break; } case LIT_CHAR_TAB: { abbrev = LIT_CHAR_LOWERCASE_T; break; } } /* 2.b.iii */ ecma_string_t *abbrev_str_p = ecma_new_ecma_string_from_utf8 (&abbrev, 1); tmp_str_p = ecma_concat_ecma_strings (product_str_p, abbrev_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (abbrev_str_p); product_str_p = tmp_str_p; } /* 2.c */ else if (current_char < LIT_CHAR_SP) { ecma_string_t *backslash_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BACKSLASH_CHAR); /* 2.c.i */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, backslash_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (backslash_str_p); product_str_p = tmp_str_p; /* 2.c.ii */ lit_utf8_byte_t u_ch = LIT_CHAR_LOWERCASE_U; ecma_string_t *u_ch_str_p = ecma_new_ecma_string_from_utf8 (&u_ch, 1); tmp_str_p = ecma_concat_ecma_strings (product_str_p, u_ch_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (u_ch_str_p); product_str_p = tmp_str_p; /* 2.c.iii */ ecma_string_t *hex_str_p = ecma_builtin_helper_json_create_hex_digit_ecma_string ((uint8_t) current_char); /* 2.c.iv */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, hex_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (hex_str_p); product_str_p = tmp_str_p; } /* 2.d */ else { ecma_string_t *current_char_str_p = ecma_new_ecma_string_from_code_unit (current_char); tmp_str_p = ecma_concat_ecma_strings (product_str_p, current_char_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (current_char_str_p); product_str_p = tmp_str_p; } } MEM_FINALIZE_LOCAL_ARRAY (string_buff); /* 3. */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, quote_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (quote_str_p); product_str_p = tmp_str_p; /* 4. */ return ecma_make_string_value (product_str_p); } /* ecma_builtin_json_quote */