/** * The String.prototype object's 'localeCompare' routine * * See also: * ECMA-262 v5, 15.5.4.9 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_locale_compare (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1. */ ECMA_TRY_CATCH (this_check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2. */ ECMA_TRY_CATCH (this_to_string_val, ecma_op_to_string (this_arg), ret_value); /* 3. */ ECMA_TRY_CATCH (arg_to_string_val, ecma_op_to_string (arg), ret_value); ecma_string_t *this_string_p = ecma_get_string_from_value (this_to_string_val); ecma_string_t *arg_string_p = ecma_get_string_from_value (arg_to_string_val); ecma_number_t *result_p = ecma_alloc_number (); if (ecma_compare_ecma_strings_relational (this_string_p, arg_string_p)) { *result_p = ecma_int32_to_number (-1); } else if (!ecma_compare_ecma_strings (this_string_p, arg_string_p)) { *result_p = ecma_int32_to_number (1); } else { *result_p = ecma_int32_to_number (0); } ret_value = ecma_make_normal_completion_value (ecma_make_number_value (result_p)); ECMA_FINALIZE (arg_to_string_val); ECMA_FINALIZE (this_to_string_val); ECMA_FINALIZE (this_check_coercible_val); return ret_value; } /* ecma_builtin_string_prototype_object_locale_compare */
/* * Helper function for string indexOf and lastIndexOf functions * * This function implements string indexOf and lastIndexOf with required checks and conversions. * * See also: * ECMA-262 v5, 15.5.4.7 * ECMA-262 v5, 15.5.4.8 * * Used by: * - The String.prototype.indexOf routine. * - The String.prototype.lastIndexOf routine. * * @return uint32_t - (last)index of search string */ ecma_completion_value_t ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2, /**< routine's second argument */ bool firstIndex) /**< routine's third argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1 */ ECMA_TRY_CATCH (check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2 */ ECMA_TRY_CATCH (to_str_val, ecma_op_to_string (this_arg), ret_value); /* 3 */ ECMA_TRY_CATCH (search_str_val, ecma_op_to_string (arg1), ret_value); /* 4 */ ECMA_OP_TO_NUMBER_TRY_CATCH (pos_num, arg2, ret_value); /* 6 */ ecma_string_t *original_str_p = ecma_get_string_from_value (to_str_val); const ecma_length_t original_len = ecma_string_get_length (original_str_p); const lit_utf8_size_t original_size = ecma_string_get_size (original_str_p); /* 4b, 5, 7 */ ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, firstIndex); /* 8 */ ecma_string_t *search_str_p = ecma_get_string_from_value (search_str_val); const ecma_length_t search_len = ecma_string_get_length (search_str_p); const lit_utf8_size_t search_size = ecma_string_get_size (search_str_p); ecma_number_t *ret_num_p = ecma_alloc_number (); *ret_num_p = ecma_int32_to_number (-1); /* 9 */ if (search_len <= original_len) { if (!search_len) { *ret_num_p = ecma_uint32_to_number (firstIndex ? 0 : original_len); } else { /* create utf8 string from original string and advance to position */ MEM_DEFINE_LOCAL_ARRAY (original_str_utf8_p, original_size, lit_utf8_byte_t); ecma_string_to_utf8_string (original_str_p, original_str_utf8_p, (ssize_t) (original_size)); lit_utf8_iterator_t original_it = lit_utf8_iterator_create (original_str_utf8_p, original_size); ecma_length_t index = start; lit_utf8_iterator_advance (&original_it, index); /* create utf8 string from search string */ MEM_DEFINE_LOCAL_ARRAY (search_str_utf8_p, search_size, lit_utf8_byte_t); ecma_string_to_utf8_string (search_str_p, search_str_utf8_p, (ssize_t) (search_size)); lit_utf8_iterator_t search_it = lit_utf8_iterator_create (search_str_utf8_p, search_size); /* iterate original string and try to match at each position */ bool searching = true; while (searching) { /* match as long as possible */ ecma_length_t match_len = 0; lit_utf8_iterator_t stored_original_it = original_it; while (match_len < search_len && index + match_len < original_len && lit_utf8_iterator_read_next (&original_it) == lit_utf8_iterator_read_next (&search_it)) { match_len++; } /* check for match */ if (match_len == search_len) { *ret_num_p = ecma_uint32_to_number (index); break; } else { /* inc/dec index and update iterators and search condition */ lit_utf8_iterator_seek_bos (&search_it); original_it = stored_original_it; if (firstIndex) { if ((searching = (index <= original_len - search_len))) { lit_utf8_iterator_incr (&original_it); index++; } } else { if ((searching = (index > 0))) { lit_utf8_iterator_decr (&original_it); index--; } } } } MEM_FINALIZE_LOCAL_ARRAY (search_str_utf8_p); MEM_FINALIZE_LOCAL_ARRAY (original_str_utf8_p); } } ecma_value_t new_value = ecma_make_number_value (ret_num_p); ret_value = ecma_make_normal_completion_value (new_value); ECMA_OP_TO_NUMBER_FINALIZE (pos_num); ECMA_FINALIZE (search_str_val); ECMA_FINALIZE (to_str_val); ECMA_FINALIZE (check_coercible_val); return ret_value; } /* ecma_builtin_helper_string_index_normalize */
/** * The String.prototype object's 'indexOf' routine * * See also: * ECMA-262 v5, 15.5.4.7 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_index_of (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2) /**< routine's second argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1 */ ECMA_TRY_CATCH (check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2 */ ECMA_TRY_CATCH (to_str_val, ecma_op_to_string (this_arg), ret_value); /* 3 */ ECMA_TRY_CATCH (search_str_val, ecma_op_to_string (arg1), ret_value); /* 4 */ ECMA_OP_TO_NUMBER_TRY_CATCH (pos_num, arg2, ret_value); /* 5 */ ecma_string_t *original_str_p = ecma_get_string_from_value (to_str_val); const ecma_length_t original_len = ecma_string_get_length (original_str_p); const lit_utf8_size_t original_size = ecma_string_get_size (original_str_p); /* 4b, 6 */ ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len); /* 7 */ ecma_string_t *search_str_p = ecma_get_string_from_value (search_str_val); const ecma_length_t search_len = ecma_string_get_length (search_str_p); const lit_utf8_size_t search_size = ecma_string_get_size (search_str_p); ecma_number_t *ret_num_p = ecma_alloc_number (); *ret_num_p = ecma_int32_to_number (-1); /* 8 */ if (search_len <= original_len) { if (!search_len) { *ret_num_p = ecma_uint32_to_number (0); } else { /* create utf8 string from original string and advance to start position */ MEM_DEFINE_LOCAL_ARRAY (original_str_utf8_p, original_size, lit_utf8_byte_t); ecma_string_to_utf8_string (original_str_p, original_str_utf8_p, (ssize_t) (original_size)); lit_utf8_iterator_t original_it = lit_utf8_iterator_create (original_str_utf8_p, original_size); ecma_length_t index = start; lit_utf8_iterator_advance (&original_it, index); /* create utf8 string from search string */ MEM_DEFINE_LOCAL_ARRAY (search_str_utf8_p, search_size, lit_utf8_byte_t); ecma_string_to_utf8_string (search_str_p, search_str_utf8_p, (ssize_t) (search_size)); lit_utf8_iterator_t search_it = lit_utf8_iterator_create (search_str_utf8_p, search_size); /* iterate original string and try to match at each position */ bool found = false; while (!found && index <= original_len - search_len) { ecma_length_t match_len = 0; lit_utf8_iterator_pos_t stored_original_pos = lit_utf8_iterator_get_pos (&original_it); while (match_len < search_len && lit_utf8_iterator_read_next (&original_it) == lit_utf8_iterator_read_next (&search_it)) { match_len++; } /* Check for match */ if (match_len == search_len) { *ret_num_p = ecma_uint32_to_number (index); found = true; } else { /* reset iterators */ lit_utf8_iterator_seek_bos (&search_it); lit_utf8_iterator_seek (&original_it, stored_original_pos); lit_utf8_iterator_incr (&original_it); } index++; } MEM_FINALIZE_LOCAL_ARRAY (search_str_utf8_p); MEM_FINALIZE_LOCAL_ARRAY (original_str_utf8_p); } } ecma_value_t new_value = ecma_make_number_value (ret_num_p); ret_value = ecma_make_normal_completion_value (new_value); ECMA_OP_TO_NUMBER_FINALIZE (pos_num); ECMA_FINALIZE (search_str_val); ECMA_FINALIZE (to_str_val); ECMA_FINALIZE (check_coercible_val); return ret_value; } /* ecma_builtin_string_prototype_object_index_of */