Skip to content

Commit 7508b80

Browse files
committed
Implement parseFloat()
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com
1 parent 35840a4 commit 7508b80

File tree

2 files changed

+224
-2
lines changed

2 files changed

+224
-2
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-global.cpp

Lines changed: 157 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,165 @@ ecma_builtin_global_object_parse_int (ecma_value_t this_arg __attr_unused___, /*
264264
* Returned value must be freed with ecma_free_completion_value.
265265
*/
266266
static ecma_completion_value_t
267-
ecma_builtin_global_object_parse_float (ecma_value_t this_arg, /**< this argument */
267+
ecma_builtin_global_object_parse_float (ecma_value_t this_arg __attr_unused___, /**< this argument */
268268
ecma_value_t string) /**< routine's first argument */
269269
{
270-
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg, string);
270+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
271+
272+
/* 1. */
273+
ECMA_TRY_CATCH (string_var, ecma_op_to_string (string), ret_value);
274+
275+
ecma_string_t *number_str_p = ecma_get_string_from_value (string_var);
276+
int32_t string_len = ecma_string_get_length (number_str_p);
277+
278+
MEM_DEFINE_LOCAL_ARRAY (zt_string_buff, string_len + 1, ecma_char_t);
279+
280+
size_t string_buf_size = (size_t) (string_len + 1) * sizeof (ecma_char_t);
281+
ssize_t bytes_copied = ecma_string_to_zt_string (number_str_p,
282+
zt_string_buff,
283+
(ssize_t) string_buf_size);
284+
JERRY_ASSERT (bytes_copied > 0);
285+
286+
/* 2. Find first non whitespace char. */
287+
int32_t start = 0;
288+
for (int i = 0; i < string_len; i++)
289+
{
290+
if (!isspace (zt_string_buff[i]))
291+
{
292+
start = i;
293+
break;
294+
}
295+
}
296+
297+
bool sign = false;
298+
299+
/* Check if sign is present. */
300+
if (zt_string_buff[start] == '-')
301+
{
302+
sign = true;
303+
start++;
304+
}
305+
else if (zt_string_buff[start] == '+')
306+
{
307+
start++;
308+
}
309+
310+
ecma_number_t *ret_num_p = ecma_alloc_number ();
311+
312+
/* Check if string is equal to "Infinity". */
313+
const ecma_char_t *infinity_zt_str_p = ecma_get_magic_string_zt (ECMA_MAGIC_STRING_INFINITY_UL);
314+
315+
for (int i = 0; infinity_zt_str_p[i] == zt_string_buff[start + i]; i++)
316+
{
317+
if (infinity_zt_str_p[i + 1] == 0)
318+
{
319+
*ret_num_p = ecma_number_make_infinity (sign);
320+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
321+
break;
322+
}
323+
}
324+
325+
if (ecma_is_completion_value_empty (ret_value))
326+
{
327+
int32_t current = start;
328+
int32_t end = string_len;
329+
bool has_whole_part = false;
330+
bool has_fraction_part = false;
331+
332+
if (isdigit (zt_string_buff[current]))
333+
{
334+
has_whole_part = true;
335+
336+
/* Check digits of whole part. */
337+
for (int i = current; i < string_len; i++, current++)
338+
{
339+
if (!isdigit (zt_string_buff[current]))
340+
{
341+
break;
342+
}
343+
}
344+
}
345+
346+
end = current;
347+
348+
/* Check decimal point. */
349+
if (zt_string_buff[current] == '.')
350+
{
351+
current++;
352+
353+
if (isdigit (zt_string_buff[current]))
354+
{
355+
has_fraction_part = true;
356+
357+
/* Check digits of fractional part. */
358+
for (int i = current; i < string_len; i++, current++)
359+
{
360+
if (!isdigit (zt_string_buff[current]))
361+
{
362+
break;
363+
}
364+
}
365+
366+
end = current;
367+
}
368+
}
369+
370+
/* Check exponent. */
371+
if ((zt_string_buff[current] == 'e' || zt_string_buff[current] == 'E')
372+
&& (has_whole_part || has_fraction_part))
373+
{
374+
current++;
375+
376+
/* Check sign of exponent. */
377+
if (zt_string_buff[current] == '-' || zt_string_buff[current] == '+')
378+
{
379+
current++;
380+
}
381+
382+
if (isdigit (zt_string_buff[current]))
383+
{
384+
385+
/* Check digits of exponent part. */
386+
for (int i = current; i < string_len; i++, current++)
387+
{
388+
if (!isdigit (zt_string_buff[current]))
389+
{
390+
break;
391+
}
392+
}
393+
394+
end = current;
395+
}
396+
}
397+
398+
if (start == end)
399+
{
400+
*ret_num_p = ecma_number_make_nan ();
401+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
402+
}
403+
else
404+
{
405+
if (end < string_len)
406+
{
407+
/* 4. End of valid number, terminate the string. */
408+
zt_string_buff[end] = '\0';
409+
}
410+
411+
/* 5. */
412+
*ret_num_p = ecma_zt_string_to_number (zt_string_buff + start);
413+
414+
if (sign)
415+
{
416+
*ret_num_p *= -1;
417+
}
418+
419+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
420+
}
421+
}
422+
423+
MEM_FINALIZE_LOCAL_ARRAY (zt_string_buff);
424+
ECMA_FINALIZE (string_var);
425+
return ret_value;
271426
} /* ecma_builtin_global_object_parse_float */
272427

273428
/**

tests/jerry/global-parsefloat.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright 2015 Samsung Electronics Co., Ltd.
2+
// Copyright 2015 University of Szeged.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
assert(parseFloat("1") === 1);
17+
assert(parseFloat("+1") === 1);
18+
assert(parseFloat("-1") === -1);
19+
assert(parseFloat("1.2") === 1.2);
20+
assert(parseFloat("+1.2") === 1.2);
21+
assert(parseFloat("-1.2") === -1.2);
22+
assert(parseFloat("1.2e3") === 1200);
23+
assert(parseFloat("+1.2e3") === 1200);
24+
assert(parseFloat("-1.2e3") === -1200);
25+
assert(parseFloat(" \n\t 1.2e3") === 1200);
26+
assert(parseFloat(".2e3") === 200);
27+
assert(parseFloat("1.e3") === 1000);
28+
assert(parseFloat("1.2e") === 1.2);
29+
assert(parseFloat("1.e") === 1);
30+
assert(parseFloat("1.e3") === 1000);
31+
assert(parseFloat("1e3") === 1000);
32+
assert(parseFloat("1e") === 1);
33+
assert(parseFloat("1.2e3foo") === 1200);
34+
assert(isNaN(parseFloat("foo1.2e3foo")));
35+
assert(parseFloat("Infinity") === Infinity);
36+
assert(parseFloat("-Infinity") === -Infinity);
37+
assert(parseFloat("Infinityfoo") === Infinity);
38+
assert(parseFloat("-Infinityfoo") === -Infinity);
39+
assert(isNaN(parseFloat("")));
40+
assert(isNaN(parseFloat(".")));
41+
assert(isNaN(parseFloat("e3")));
42+
assert(isNaN(parseFloat(".e3")));
43+
assert(parseFloat("0") === 0);
44+
assert(parseFloat(".0") === 0);
45+
assert(parseFloat("0.e3") === 0);
46+
assert(parseFloat("0.0e3") === 0);
47+
48+
var obj = new Object();
49+
var arr = [3,4,5];
50+
var num = 7;
51+
var bool = true;
52+
var undef;
53+
54+
assert(isNaN(parseFloat(obj)));
55+
assert(parseFloat(arr) === 3);
56+
assert(parseFloat(num) === 7);
57+
assert(isNaN(parseFloat(bool)));
58+
assert(isNaN(parseFloat(undef)));
59+
60+
var obj = { toString : function () { throw new ReferenceError("foo") } };
61+
try {
62+
parseFloat(obj);
63+
assert(false);
64+
} catch (e) {
65+
assert(e instanceof ReferenceError);
66+
assert(e.message === "foo");
67+
}

0 commit comments

Comments
 (0)