/** * 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 */
/** * ECMA abstract relational comparison routine. * * See also: ECMA-262 v5, 11.8.5 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_abstract_relational_compare (ecma_value_t x, /**< first operand */ ecma_value_t y, /**< second operand */ bool left_first) /**< 'LeftFirst' flag */ { ecma_value_t ret_value = ECMA_VALUE_EMPTY; /* 1., 2. */ ecma_value_t prim_first_converted_value = ecma_op_to_primitive (x, ECMA_PREFERRED_TYPE_NUMBER); if (ECMA_IS_VALUE_ERROR (prim_first_converted_value)) { return prim_first_converted_value; } ecma_value_t prim_second_converted_value = ecma_op_to_primitive (y, ECMA_PREFERRED_TYPE_NUMBER); if (ECMA_IS_VALUE_ERROR (prim_second_converted_value)) { ecma_free_value (prim_first_converted_value); return prim_second_converted_value; } const ecma_value_t px = left_first ? prim_first_converted_value : prim_second_converted_value; const ecma_value_t py = left_first ? prim_second_converted_value : prim_first_converted_value; const bool is_px_string = ecma_is_value_string (px); const bool is_py_string = ecma_is_value_string (py); if (!(is_px_string && is_py_string)) { /* 3. */ /* a. */ ECMA_OP_TO_NUMBER_TRY_CATCH (nx, px, ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (ny, py, ret_value); /* b. */ if (ecma_number_is_nan (nx) || ecma_number_is_nan (ny)) { /* c., d. */ ret_value = ECMA_VALUE_UNDEFINED; } else { bool is_x_less_than_y = (nx < ny); #ifndef JERRY_NDEBUG bool is_x_less_than_y_check; if (nx == ny || (ecma_number_is_zero (nx) && ecma_number_is_zero (ny))) { /* e., f., g. */ is_x_less_than_y_check = false; } else if (ecma_number_is_infinity (nx) && !ecma_number_is_negative (nx)) { /* h. */ is_x_less_than_y_check = false; } else if (ecma_number_is_infinity (ny) && !ecma_number_is_negative (ny)) { /* i. */ is_x_less_than_y_check = true; } else if (ecma_number_is_infinity (ny) && ecma_number_is_negative (ny)) { /* j. */ is_x_less_than_y_check = false; } else if (ecma_number_is_infinity (nx) && ecma_number_is_negative (nx)) { /* k. */ is_x_less_than_y_check = true; } else { /* l. */ JERRY_ASSERT (!ecma_number_is_nan (nx) && !ecma_number_is_infinity (nx)); JERRY_ASSERT (!ecma_number_is_nan (ny) && !ecma_number_is_infinity (ny)); JERRY_ASSERT (!(ecma_number_is_zero (nx) && ecma_number_is_zero (ny))); if (nx < ny) { is_x_less_than_y_check = true; } else { is_x_less_than_y_check = false; } } JERRY_ASSERT (is_x_less_than_y_check == is_x_less_than_y); #endif /* !JERRY_NDEBUG */ ret_value = ecma_make_boolean_value (is_x_less_than_y); } ECMA_OP_TO_NUMBER_FINALIZE (ny); ECMA_OP_TO_NUMBER_FINALIZE (nx); } else { /* 4. */ JERRY_ASSERT (is_px_string && is_py_string); ecma_string_t *str_x_p = ecma_get_string_from_value (px); ecma_string_t *str_y_p = ecma_get_string_from_value (py); bool is_px_less = ecma_compare_ecma_strings_relational (str_x_p, str_y_p); ret_value = ecma_make_boolean_value (is_px_less); } ecma_free_value (prim_second_converted_value); ecma_free_value (prim_first_converted_value); return ret_value; } /* ecma_op_abstract_relational_compare */