Implement parseInt()
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include "ecma-try-catch-macro.h"
|
||||
#include "jrt.h"
|
||||
#include "vm.h"
|
||||
#include "jrt-libc-includes.h"
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
@@ -97,11 +98,160 @@ ecma_builtin_global_object_eval (ecma_value_t this_arg, /**< this argument */
|
||||
* Returned value must be freed with ecma_free_completion_value.
|
||||
*/
|
||||
static ecma_completion_value_t
|
||||
ecma_builtin_global_object_parse_int (ecma_value_t this_arg, /**< this argument */
|
||||
ecma_builtin_global_object_parse_int (ecma_value_t this_arg __attr_unused___, /**< this argument */
|
||||
ecma_value_t string, /**< routine's first argument */
|
||||
ecma_value_t radix) /**< routine's second argument */
|
||||
{
|
||||
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg, string, radix);
|
||||
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
|
||||
|
||||
/* 1. */
|
||||
ECMA_TRY_CATCH (string_var, ecma_op_to_string (string), ret_value);
|
||||
|
||||
ecma_string_t *number_str_p = ecma_get_string_from_value (string_var);
|
||||
int32_t string_len = ecma_string_get_length (number_str_p);
|
||||
|
||||
MEM_DEFINE_LOCAL_ARRAY (zt_string_buff, string_len + 1, ecma_char_t);
|
||||
|
||||
size_t string_buf_size = (size_t) (string_len + 1) * sizeof (ecma_char_t);
|
||||
ssize_t bytes_copied = ecma_string_to_zt_string (number_str_p,
|
||||
zt_string_buff,
|
||||
(ssize_t) string_buf_size);
|
||||
JERRY_ASSERT (bytes_copied > 0);
|
||||
|
||||
/* 2. Remove leading whitespace. */
|
||||
int32_t start = string_len;
|
||||
int32_t end = string_len;
|
||||
for (int i = 0; i < end; i++)
|
||||
{
|
||||
if (!(isspace (zt_string_buff[i])))
|
||||
{
|
||||
start = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 3. */
|
||||
int sign = 1;
|
||||
|
||||
/* 4. */
|
||||
if (zt_string_buff[start] == '-')
|
||||
{
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
/* 5. */
|
||||
if (zt_string_buff[start] == '-' || zt_string_buff[start] == '+')
|
||||
{
|
||||
start++;
|
||||
}
|
||||
|
||||
/* 6. */
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (radix_num, radix, ret_value);
|
||||
int32_t rad = ecma_number_to_int32 (radix_num);
|
||||
|
||||
/* 7.*/
|
||||
bool strip_prefix = true;
|
||||
|
||||
/* 8. */
|
||||
if (rad != 0)
|
||||
{
|
||||
/* 8.a */
|
||||
if (rad < 2 || rad > 36)
|
||||
{
|
||||
ecma_number_t *ret_num_p = ecma_alloc_number ();
|
||||
*ret_num_p = ecma_number_make_nan ();
|
||||
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
|
||||
}
|
||||
/* 8.b */
|
||||
else if (rad != 16)
|
||||
{
|
||||
strip_prefix = false;
|
||||
}
|
||||
}
|
||||
/* 9. */
|
||||
else
|
||||
{
|
||||
rad = 10;
|
||||
}
|
||||
|
||||
if (ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
/* 10. */
|
||||
if (strip_prefix)
|
||||
{
|
||||
if (end - start >= 2
|
||||
&& zt_string_buff[start] == '0'
|
||||
&& (zt_string_buff[start + 1] == 'x' || zt_string_buff[start + 1] == 'X'))
|
||||
{
|
||||
start += 2;
|
||||
|
||||
rad = 16;
|
||||
}
|
||||
}
|
||||
|
||||
/* 11. Check if characters are in [0, Radix - 1]. We also convert them to number values in the process. */
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
if ((zt_string_buff[i]) >= 'a' && zt_string_buff[i] <= 'z')
|
||||
{
|
||||
zt_string_buff[i] = (ecma_char_t) (zt_string_buff[i] - 'a' + 10);
|
||||
}
|
||||
else if (zt_string_buff[i] >= 'A' && zt_string_buff[i] <= 'Z')
|
||||
{
|
||||
zt_string_buff[i] = (ecma_char_t) (zt_string_buff[i] - 'A' + 10);
|
||||
}
|
||||
else if (isdigit (zt_string_buff[i]))
|
||||
{
|
||||
zt_string_buff[i] = (ecma_char_t) (zt_string_buff[i] - '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Not a valid number char, set value to radix so it fails to pass as a valid character. */
|
||||
zt_string_buff[i] = (ecma_char_t) rad;
|
||||
}
|
||||
|
||||
if (!(zt_string_buff[i] < rad))
|
||||
{
|
||||
end = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 12. */
|
||||
if (end - start == 0)
|
||||
{
|
||||
ecma_number_t *ret_num_p = ecma_alloc_number ();
|
||||
*ret_num_p = ecma_number_make_nan ();
|
||||
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
ecma_number_t *value_p = ecma_alloc_number ();
|
||||
*value_p = 0;
|
||||
ecma_number_t multiplier = 1.0f;
|
||||
|
||||
/* 13. and 14. */
|
||||
for (int i = end - 1; i >= start; i--)
|
||||
{
|
||||
*value_p += (ecma_number_t) zt_string_buff[i] * multiplier;
|
||||
multiplier *= (ecma_number_t) rad;
|
||||
}
|
||||
|
||||
/* 15. */
|
||||
if (sign < 0)
|
||||
{
|
||||
*value_p *= (ecma_number_t) sign;
|
||||
}
|
||||
|
||||
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (value_p));
|
||||
}
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (radix_num);
|
||||
MEM_FINALIZE_LOCAL_ARRAY (zt_string_buff);
|
||||
ECMA_FINALIZE (string_var);
|
||||
return ret_value;
|
||||
} /* ecma_builtin_global_object_parse_int */
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2015 Samsung Electronics Co., Ltd.
|
||||
// Copyright 2015 University of Szeged.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
assert(parseInt("123") === 123);
|
||||
assert(parseInt("+123") === 123);
|
||||
assert(parseInt("-123") === -123);
|
||||
assert(parseInt("0123") === 123);
|
||||
assert(parseInt(" 123") === 123);
|
||||
assert(parseInt(" \n 123") === 123);
|
||||
assert(parseInt(" \n 123 \t") === 123);
|
||||
assert(parseInt("0x123") === 291);
|
||||
assert(parseInt("0X123") === 291);
|
||||
assert(parseInt("123", 4) === 27);
|
||||
assert(parseInt("ABC", 16) === 2748);
|
||||
assert(parseInt("12A3") === 12);
|
||||
assert(parseInt("12.34") === 12);
|
||||
assert(isNaN(parseInt("AB")));
|
||||
|
||||
var bool = true;
|
||||
var obj = new Object();
|
||||
var num = 8;
|
||||
var arr = [2,3,4];
|
||||
var undef;
|
||||
|
||||
assert(isNaN(parseInt(bool, bool)));
|
||||
assert(isNaN(parseInt(bool, obj)));
|
||||
assert(isNaN(parseInt(bool, num)));
|
||||
assert(isNaN(parseInt(bool, arr)));
|
||||
|
||||
assert(isNaN(parseInt(obj, bool)));
|
||||
assert(isNaN(parseInt(obj, obj)));
|
||||
assert(isNaN(parseInt(obj, num)));
|
||||
assert(isNaN(parseInt(obj, arr)));
|
||||
|
||||
assert(isNaN(parseInt(num, bool)));
|
||||
assert(parseInt(num, obj) === 8);
|
||||
assert(isNaN(parseInt(num, num)));
|
||||
assert(parseInt(num, arr) === 8);
|
||||
|
||||
assert(isNaN(parseInt(arr, bool)));
|
||||
assert(parseInt(arr, obj) === 2);
|
||||
assert(parseInt(arr, num) === 2);
|
||||
assert(parseInt(arr, arr) === 2);
|
||||
|
||||
assert(isNaN(parseInt(undef, bool)));
|
||||
assert(isNaN(parseInt(undef, obj)));
|
||||
assert(isNaN(parseInt(undef, num)));
|
||||
assert(isNaN(parseInt(undef, arr)));
|
||||
|
||||
var obj = { toString : function () { throw new ReferenceError("foo") } };
|
||||
try {
|
||||
parseInt(obj);
|
||||
assert(false);
|
||||
} catch (e) {
|
||||
assert(e instanceof ReferenceError);
|
||||
assert(e.message === "foo");
|
||||
}
|
||||
Reference in New Issue
Block a user