OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 | 5 |
6 #ifdef V8_I18N_SUPPORT | 6 #ifdef V8_I18N_SUPPORT |
7 #include "src/runtime/runtime-utils.h" | 7 #include "src/runtime/runtime-utils.h" |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/api-natives.h" | 10 #include "src/api-natives.h" |
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
746 } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) { | 746 } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) { |
747 return *isolate->factory()->NewStringFromStaticChars("kana"); | 747 return *isolate->factory()->NewStringFromStaticChars("kana"); |
748 } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) { | 748 } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) { |
749 return *isolate->factory()->NewStringFromStaticChars("ideo"); | 749 return *isolate->factory()->NewStringFromStaticChars("ideo"); |
750 } else { | 750 } else { |
751 return *isolate->factory()->NewStringFromStaticChars("unknown"); | 751 return *isolate->factory()->NewStringFromStaticChars("unknown"); |
752 } | 752 } |
753 } | 753 } |
754 | 754 |
755 namespace { | 755 namespace { |
756 #if 0 | |
756 inline void LocaleConvertCaseHelper(icu::UnicodeString* s, bool is_to_upper, | 757 inline void LocaleConvertCaseHelper(icu::UnicodeString* s, bool is_to_upper, |
757 const icu::Locale& locale) { | 758 const icu::Locale& locale) { |
758 if (is_to_upper) | 759 if (is_to_upper) |
759 s->toUpper(locale); | 760 s->toUpper(locale); |
760 else | 761 else |
761 s->toLower(locale); | 762 s->toLower(locale); |
762 } | 763 } |
763 void ConvertCaseWithTransliterator(icu::UnicodeString* input, | 764 void ConvertCaseWithTransliterator(icu::UnicodeString* input, |
764 const char* transliterator_id) { | 765 const char* transliterator_id) { |
765 UErrorCode status = U_ZERO_ERROR; | 766 UErrorCode status = U_ZERO_ERROR; |
766 base::SmartPointer<icu::Transliterator> translit( | 767 base::SmartPointer<icu::Transliterator> translit( |
767 icu::Transliterator::createInstance( | 768 icu::Transliterator::createInstance( |
768 icu::UnicodeString(transliterator_id, -1, US_INV), UTRANS_FORWARD, | 769 icu::UnicodeString(transliterator_id, -1, US_INV), UTRANS_FORWARD, |
769 status)); | 770 status)); |
770 if (U_FAILURE(status)) return; | 771 if (U_FAILURE(status)) return; |
771 translit->transliterate(*input); | 772 translit->transliterate(*input); |
772 } | 773 } |
774 #endif | |
773 | 775 |
774 MUST_USE_RESULT Object* LocaleConvertCase(Handle<String> s, Isolate* isolate, | 776 MUST_USE_RESULT Object* LocaleConvertCase(Handle<String> s, Isolate* isolate, |
775 bool is_to_upper, int locale_id) { | 777 bool is_to_upper, int locale_id) { |
776 static const char* conversion_locales[] = { | 778 static const char* conversion_locales[] = { |
777 "az", "el", "lt", "tr", | 779 "az", "el", "lt", "tr", |
778 }; | 780 }; |
779 RUNTIME_ASSERT(locale_id >= -1 && | 781 RUNTIME_ASSERT(locale_id >= -1 && |
780 locale_id < static_cast<int>(arraysize(conversion_locales))); | 782 locale_id < static_cast<int>(arraysize(conversion_locales))); |
781 int32_t length = s->length(); | 783 int32_t length = s->length(); |
782 icu::UnicodeString converted; | 784 base::SmartArrayPointer<uc16> sap; |
785 const UChar* src; | |
786 Handle<SeqTwoByteString> result = | |
787 isolate->factory()->NewRawTwoByteString(length).ToHandleChecked(); | |
783 { | 788 { |
784 DisallowHeapAllocation no_gc; | 789 DisallowHeapAllocation no_gc; |
785 DCHECK(s->IsFlat()); | 790 DCHECK(s->IsFlat()); |
786 String::FlatContent flat = s->GetFlatContent(); | 791 String::FlatContent flat = s->GetFlatContent(); |
787 | |
788 const UChar* src; | |
789 if (flat.IsOneByte()) { | 792 if (flat.IsOneByte()) { |
790 base::SmartArrayPointer<uc16> sap = s->ToWideCString(); | 793 sap = s->ToWideCString(); |
791 src = reinterpret_cast<const UChar*>(sap.get()); | 794 src = reinterpret_cast<const UChar*>(sap.get()); |
792 converted = icu::UnicodeString(src, length); | |
793 } else { | 795 } else { |
794 src = reinterpret_cast<const UChar*>(flat.ToUC16Vector().start()); | 796 src = reinterpret_cast<const UChar*>(flat.ToUC16Vector().start()); |
795 converted = icu::UnicodeString(src, length); | 797 } |
798 | |
799 if (V8_LIKELY(locale_id != 1 || !is_to_upper)) { | |
800 typedef int32_t (*case_conversion_fn)( | |
801 UChar * dest, int32_t destCapacity, const UChar* src, | |
802 int32_t srcLength, const char* locale, UErrorCode* pErrorCode); | |
803 case_conversion_fn fn = is_to_upper ? u_strToUpper : u_strToLower; | |
804 | |
805 int32_t target_length = length; | |
806 const char* locale = locale_id == -1 ? "" : conversion_locales[locale_id]; | |
807 UErrorCode error; | |
808 do { | |
809 error = U_ZERO_ERROR; | |
810 target_length = fn(reinterpret_cast<UChar*>(result->GetChars()), | |
811 target_length, src, length, locale, &error); | |
812 result->synchronized_set_length(target_length); | |
jungshik at Google
2016/04/14 07:46:31
|set_length| is called over |result| ( which is Se
| |
813 } while (error == U_BUFFER_OVERFLOW_ERROR); | |
814 return U_SUCCESS(error) ? *result : *s; | |
796 } | 815 } |
797 } | 816 } |
798 | 817 |
799 if (locale_id == -1) { | 818 return *s; |
800 LocaleConvertCaseHelper(&converted, is_to_upper, icu::Locale::getRoot()); | 819 #if 0 |
801 } else if (V8_UNLIKELY(locale_id == 1 && is_to_upper)) { | 820 // For Greek Uppercasing |
802 // TODO(jshin): Once http://bugs.icu-project.org/trac/ticket/10582 is | 821 icu::UnicodeString converted(false, src, length); |
803 // fixed, remove this special-casing for uppercasing in Greek(el) locale. | 822 ConvertCaseWithTransliterator(&converted, "el-Upper"); |
804 // This is ~500 times slower than using the case conversion API. | 823 Handle<String> greek_result; |
805 ConvertCaseWithTransliterator(&converted, "el-Upper"); | |
806 } else { | |
807 LocaleConvertCaseHelper(&converted, is_to_upper, | |
808 icu::Locale(conversion_locales[locale_id])); | |
809 } | |
810 | |
811 Handle<String> result; | |
812 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 824 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
813 isolate, result, | 825 isolate, greek_result, |
814 isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>( | 826 isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>( |
815 reinterpret_cast<const uint16_t*>(converted.getBuffer()), | 827 reinterpret_cast<const uint16_t*>(converted.getBuffer()), |
816 converted.length()))); | 828 converted.length()))); |
817 return *result; | 829 return *greek_result; |
830 #endif | |
818 } | 831 } |
819 | 832 |
820 inline bool IsASCIIUpper(uint16_t ch) { return ch >= 'A' && ch <= 'Z'; } | 833 inline bool IsASCIIUpper(uint16_t ch) { return ch >= 'A' && ch <= 'Z'; } |
821 | 834 |
822 inline uint16_t ToASCIILower(uint16_t ch) { | 835 inline uint16_t ToASCIILower(uint16_t ch) { |
823 return ch | ((ch >= 'A' && ch <= 'Z') << 5); | 836 return ch | ((ch >= 'A' && ch <= 'Z') << 5); |
824 } | 837 } |
825 | 838 |
826 inline uint16_t ToASCIIUpper(uint16_t ch) { | 839 inline uint16_t ToASCIIUpper(uint16_t ch) { |
827 return ch & ~((ch >= 'a' && ch <= 'z') << 5); | 840 return ch & ~((ch >= 'a' && ch <= 'z') << 5); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
970 CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1); | 983 CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1); |
971 CONVERT_NUMBER_CHECKED(int, lang_id, Int32, args[2]); | 984 CONVERT_NUMBER_CHECKED(int, lang_id, Int32, args[2]); |
972 | 985 |
973 return LocaleConvertCase(s, isolate, is_upper, lang_id); | 986 return LocaleConvertCase(s, isolate, is_upper, lang_id); |
974 } | 987 } |
975 | 988 |
976 } // namespace internal | 989 } // namespace internal |
977 } // namespace v8 | 990 } // namespace v8 |
978 | 991 |
979 #endif // V8_I18N_SUPPORT | 992 #endif // V8_I18N_SUPPORT |
OLD | NEW |