27
27
#include " ecma-try-catch-macro.h"
28
28
#include " jrt.h"
29
29
#include " jrt-libc-includes.h"
30
+ #include " lit-char-helpers.h"
30
31
31
32
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN
32
33
@@ -507,6 +508,164 @@ ecma_builtin_string_prototype_object_substring (ecma_value_t this_arg, /**< this
507
508
return ret_value;
508
509
} /* ecma_builtin_string_prototype_object_substring */
509
510
511
+ /* *
512
+ * Helper function to convert a string to upper or lower case.
513
+ *
514
+ * @return completion value
515
+ * Returned value must be freed with ecma_free_completion_value.
516
+ */
517
+ static ecma_completion_value_t
518
+ ecma_builtin_string_prototype_object_conversion_helper (ecma_value_t this_arg, /* *< this argument */
519
+ bool lower_case) /* *< convert to lower (true)
520
+ * or upper (false) case */
521
+ {
522
+ ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
523
+
524
+ /* 1. */
525
+ ECMA_TRY_CATCH (check_coercible_val,
526
+ ecma_op_check_object_coercible (this_arg),
527
+ ret_value);
528
+
529
+ /* 2. */
530
+ ECMA_TRY_CATCH (to_string_val,
531
+ ecma_op_to_string (this_arg),
532
+ ret_value);
533
+
534
+ /* 3. */
535
+ ecma_string_t *input_string_p = ecma_get_string_from_value (to_string_val);
536
+ lit_utf8_size_t input_size = ecma_string_get_size (input_string_p);
537
+
538
+ MEM_DEFINE_LOCAL_ARRAY (input_start_p,
539
+ input_size,
540
+ lit_utf8_byte_t );
541
+
542
+ ecma_string_to_utf8_string (input_string_p,
543
+ input_start_p,
544
+ (ssize_t ) (input_size));
545
+
546
+ /*
547
+ * The URI encoding has two major phases: first we compute
548
+ * the length of the lower case string, then we encode it.
549
+ */
550
+
551
+ lit_utf8_size_t output_length = 0 ;
552
+ lit_utf8_iterator_t input_iterator = lit_utf8_iterator_create (input_start_p, input_size);
553
+
554
+ while (!lit_utf8_iterator_is_eos (&input_iterator))
555
+ {
556
+ ecma_char_t character = lit_utf8_iterator_read_next (&input_iterator);
557
+ ecma_char_t character_buffer[LIT_MAXIMUM_OTHER_CASE_LENGTH];
558
+ lit_utf8_byte_t utf8_byte_buffer[LIT_UTF8_MAX_BYTES_IN_CODE_POINT];
559
+ lit_utf8_size_t character_length;
560
+
561
+ /*
562
+ * We need to keep surrogate pairs. Surrogates are never converted,
563
+ * regardless they form a valid pair or not.
564
+ */
565
+ if (lit_is_code_unit_high_surrogate (character))
566
+ {
567
+ ecma_char_t next_character = lit_utf8_iterator_peek_next (&input_iterator);
568
+
569
+ if (lit_is_code_unit_low_surrogate (next_character))
570
+ {
571
+ lit_code_point_t surrogate_code_point = lit_convert_surrogate_pair_to_code_point (character, next_character);
572
+ output_length += lit_code_point_to_utf8 (surrogate_code_point, utf8_byte_buffer);
573
+ lit_utf8_iterator_incr (&input_iterator);
574
+ continue ;
575
+ }
576
+ }
577
+
578
+ if (lower_case)
579
+ {
580
+ character_length = lit_char_to_lower_case (character,
581
+ character_buffer,
582
+ LIT_MAXIMUM_OTHER_CASE_LENGTH);
583
+ }
584
+ else
585
+ {
586
+ character_length = lit_char_to_upper_case (character,
587
+ character_buffer,
588
+ LIT_MAXIMUM_OTHER_CASE_LENGTH);
589
+ }
590
+
591
+ JERRY_ASSERT (character_length >= 1 && character_length <= LIT_MAXIMUM_OTHER_CASE_LENGTH);
592
+
593
+ for (lit_utf8_size_t i = 0 ; i < character_length; i++)
594
+ {
595
+ output_length += lit_code_unit_to_utf8 (character_buffer[i], utf8_byte_buffer);
596
+ }
597
+ }
598
+
599
+ /* Second phase. */
600
+
601
+ MEM_DEFINE_LOCAL_ARRAY (output_start_p,
602
+ output_length,
603
+ lit_utf8_byte_t );
604
+
605
+ lit_utf8_byte_t *output_char_p = output_start_p;
606
+
607
+ /* Encoding the output. */
608
+ lit_utf8_iterator_seek_bos (&input_iterator);
609
+
610
+ while (!lit_utf8_iterator_is_eos (&input_iterator))
611
+ {
612
+ ecma_char_t character = lit_utf8_iterator_read_next (&input_iterator);
613
+ ecma_char_t character_buffer[LIT_MAXIMUM_OTHER_CASE_LENGTH];
614
+ lit_utf8_size_t character_length;
615
+
616
+ /*
617
+ * We need to keep surrogate pairs. Surrogates are never converted,
618
+ * regardless they form a valid pair or not.
619
+ */
620
+ if (lit_is_code_unit_high_surrogate (character))
621
+ {
622
+ ecma_char_t next_character = lit_utf8_iterator_peek_next (&input_iterator);
623
+
624
+ if (lit_is_code_unit_low_surrogate (next_character))
625
+ {
626
+ lit_code_point_t surrogate_code_point = lit_convert_surrogate_pair_to_code_point (character, next_character);
627
+ output_char_p += lit_code_point_to_utf8 (surrogate_code_point, output_char_p);
628
+ lit_utf8_iterator_incr (&input_iterator);
629
+ continue ;
630
+ }
631
+ }
632
+
633
+ if (lower_case)
634
+ {
635
+ character_length = lit_char_to_lower_case (character,
636
+ character_buffer,
637
+ LIT_MAXIMUM_OTHER_CASE_LENGTH);
638
+ }
639
+ else
640
+ {
641
+ character_length = lit_char_to_upper_case (character,
642
+ character_buffer,
643
+ LIT_MAXIMUM_OTHER_CASE_LENGTH);
644
+ }
645
+
646
+ JERRY_ASSERT (character_length >= 1 && character_length <= LIT_MAXIMUM_OTHER_CASE_LENGTH);
647
+
648
+ for (lit_utf8_size_t i = 0 ; i < character_length; i++)
649
+ {
650
+ output_char_p += lit_code_point_to_utf8 (character_buffer[i], output_char_p);
651
+ }
652
+ }
653
+
654
+ JERRY_ASSERT (output_start_p + output_length == output_char_p);
655
+
656
+ ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (output_start_p, output_length);
657
+
658
+ ret_value = ecma_make_normal_completion_value (ecma_make_string_value (output_string_p));
659
+
660
+ MEM_FINALIZE_LOCAL_ARRAY (output_start_p);
661
+ MEM_FINALIZE_LOCAL_ARRAY (input_start_p);
662
+
663
+ ECMA_FINALIZE (to_string_val);
664
+ ECMA_FINALIZE (check_coercible_val);
665
+
666
+ return ret_value;
667
+ } /* ecma_builtin_string_prototype_object_conversion_helper */
668
+
510
669
/* *
511
670
* The String.prototype object's 'toLowerCase' routine
512
671
*
@@ -519,7 +678,7 @@ ecma_builtin_string_prototype_object_substring (ecma_value_t this_arg, /**< this
519
678
static ecma_completion_value_t
520
679
ecma_builtin_string_prototype_object_to_lower_case (ecma_value_t this_arg) /* *< this argument */
521
680
{
522
- ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg);
681
+ return ecma_builtin_string_prototype_object_conversion_helper (this_arg, true );
523
682
} /* ecma_builtin_string_prototype_object_to_lower_case */
524
683
525
684
/* *
@@ -534,7 +693,7 @@ ecma_builtin_string_prototype_object_to_lower_case (ecma_value_t this_arg) /**<
534
693
static ecma_completion_value_t
535
694
ecma_builtin_string_prototype_object_to_locale_lower_case (ecma_value_t this_arg) /* *< this argument */
536
695
{
537
- ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg);
696
+ return ecma_builtin_string_prototype_object_conversion_helper (this_arg, true );
538
697
} /* ecma_builtin_string_prototype_object_to_locale_lower_case */
539
698
540
699
/* *
@@ -549,7 +708,7 @@ ecma_builtin_string_prototype_object_to_locale_lower_case (ecma_value_t this_arg
549
708
static ecma_completion_value_t
550
709
ecma_builtin_string_prototype_object_to_upper_case (ecma_value_t this_arg) /* *< this argument */
551
710
{
552
- ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg);
711
+ return ecma_builtin_string_prototype_object_conversion_helper (this_arg, false );
553
712
} /* ecma_builtin_string_prototype_object_to_upper_case */
554
713
555
714
/* *
@@ -564,7 +723,7 @@ ecma_builtin_string_prototype_object_to_upper_case (ecma_value_t this_arg) /**<
564
723
static ecma_completion_value_t
565
724
ecma_builtin_string_prototype_object_to_locale_upper_case (ecma_value_t this_arg) /* *< this argument */
566
725
{
567
- ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg);
726
+ return ecma_builtin_string_prototype_object_conversion_helper (this_arg, false );
568
727
} /* ecma_builtin_string_prototype_object_to_locale_upper_case */
569
728
570
729
/* *
0 commit comments