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 } |
764 #endif | |
763 void ConvertCaseWithTransliterator(icu::UnicodeString* input, | 765 void ConvertCaseWithTransliterator(icu::UnicodeString* input, |
764 const char* transliterator_id) { | 766 const char* transliterator_id) { |
765 UErrorCode status = U_ZERO_ERROR; | 767 UErrorCode status = U_ZERO_ERROR; |
766 base::SmartPointer<icu::Transliterator> translit( | 768 base::SmartPointer<icu::Transliterator> translit( |
767 icu::Transliterator::createInstance( | 769 icu::Transliterator::createInstance( |
768 icu::UnicodeString(transliterator_id, -1, US_INV), UTRANS_FORWARD, | 770 icu::UnicodeString(transliterator_id, -1, US_INV), UTRANS_FORWARD, |
769 status)); | 771 status)); |
770 if (U_FAILURE(status)) return; | 772 if (U_FAILURE(status)) return; |
771 translit->transliterate(*input); | 773 translit->transliterate(*input); |
772 } | 774 } |
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 { |
796 // Will the memory pointed to by |src| be available reliably | |
797 // outside the block? Thai, will it survive 'gc' that may | |
798 // be invoked when |result| is "relloced" below? | |
794 src = reinterpret_cast<const UChar*>(flat.ToUC16Vector().start()); | 799 src = reinterpret_cast<const UChar*>(flat.ToUC16Vector().start()); |
jungshik at Google
2016/04/14 00:32:34
adamk@ and littledan@:
Can you answer my question
adamk
2016/04/14 01:56:35
What you're doing here is basically defeating the
| |
795 converted = icu::UnicodeString(src, length); | |
796 } | 800 } |
797 } | 801 } |
798 | 802 |
799 if (locale_id == -1) { | 803 if (V8_LIKELY(locale_id != 1 || !is_to_upper)) { |
800 LocaleConvertCaseHelper(&converted, is_to_upper, icu::Locale::getRoot()); | 804 typedef int32_t (*case_conversion_fn)( |
801 } else if (V8_UNLIKELY(locale_id == 1 && is_to_upper)) { | 805 UChar * dest, int32_t destCapacity, const UChar* src, int32_t srcLength, |
802 // TODO(jshin): Once http://bugs.icu-project.org/trac/ticket/10582 is | 806 const char* locale, UErrorCode* pErrorCode); |
803 // fixed, remove this special-casing for uppercasing in Greek(el) locale. | 807 case_conversion_fn fn = is_to_upper ? u_strToUpper : u_strToLower; |
804 // This is ~500 times slower than using the case conversion API. | 808 |
805 ConvertCaseWithTransliterator(&converted, "el-Upper"); | 809 int32_t target_length = length; |
806 } else { | 810 const char* locale = locale_id == -1 ? "" : conversion_locales[locale_id]; |
807 LocaleConvertCaseHelper(&converted, is_to_upper, | 811 UErrorCode error; |
808 icu::Locale(conversion_locales[locale_id])); | 812 do { |
813 error = U_ZERO_ERROR; | |
814 target_length = fn(reinterpret_cast<UChar*>(result->GetChars()), | |
815 target_length, src, length, locale, &error); | |
816 result->set_length(target_length); | |
817 } while (error == U_BUFFER_OVERFLOW_ERROR); | |
818 return U_SUCCESS(error) ? *result : *s; | |
809 } | 819 } |
810 | 820 |
811 Handle<String> result; | 821 icu::UnicodeString converted(false, src, length); |
822 ConvertCaseWithTransliterator(&converted, "el-Upper"); | |
823 Handle<String> greek_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; |
818 } | 830 } |
819 | 831 |
820 inline bool IsASCIIUpper(uint16_t ch) { return ch >= 'A' && ch <= 'Z'; } | 832 inline bool IsASCIIUpper(uint16_t ch) { return ch >= 'A' && ch <= 'Z'; } |
821 | 833 |
822 inline uint16_t ToASCIILower(uint16_t ch) { | 834 inline uint16_t ToASCIILower(uint16_t ch) { |
823 return ch | ((ch >= 'A' && ch <= 'Z') << 5); | 835 return ch | ((ch >= 'A' && ch <= 'Z') << 5); |
824 } | 836 } |
825 | 837 |
826 inline uint16_t ToASCIIUpper(uint16_t ch) { | 838 inline uint16_t ToASCIIUpper(uint16_t ch) { |
827 return ch & ~((ch >= 'a' && ch <= 'z') << 5); | 839 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); | 982 CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1); |
971 CONVERT_NUMBER_CHECKED(int, lang_id, Int32, args[2]); | 983 CONVERT_NUMBER_CHECKED(int, lang_id, Int32, args[2]); |
972 | 984 |
973 return LocaleConvertCase(s, isolate, is_upper, lang_id); | 985 return LocaleConvertCase(s, isolate, is_upper, lang_id); |
974 } | 986 } |
975 | 987 |
976 } // namespace internal | 988 } // namespace internal |
977 } // namespace v8 | 989 } // namespace v8 |
978 | 990 |
979 #endif // V8_I18N_SUPPORT | 991 #endif // V8_I18N_SUPPORT |
OLD | NEW |