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 <memory> | 9 #include <memory> |
10 | 10 |
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
932 } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) { | 932 } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) { |
933 return *isolate->factory()->NewStringFromStaticChars("kana"); | 933 return *isolate->factory()->NewStringFromStaticChars("kana"); |
934 } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) { | 934 } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) { |
935 return *isolate->factory()->NewStringFromStaticChars("ideo"); | 935 return *isolate->factory()->NewStringFromStaticChars("ideo"); |
936 } else { | 936 } else { |
937 return *isolate->factory()->NewStringFromStaticChars("unknown"); | 937 return *isolate->factory()->NewStringFromStaticChars("unknown"); |
938 } | 938 } |
939 } | 939 } |
940 | 940 |
941 namespace { | 941 namespace { |
942 void ConvertCaseWithTransliterator(icu::UnicodeString* input, | |
943 const char* transliterator_id) { | |
944 UErrorCode status = U_ZERO_ERROR; | |
945 std::unique_ptr<icu::Transliterator> translit( | |
946 icu::Transliterator::createInstance( | |
947 icu::UnicodeString(transliterator_id, -1, US_INV), UTRANS_FORWARD, | |
948 status)); | |
949 if (U_FAILURE(status)) return; | |
950 translit->transliterate(*input); | |
951 } | |
952 | |
953 MUST_USE_RESULT Object* LocaleConvertCase(Handle<String> s, Isolate* isolate, | 942 MUST_USE_RESULT Object* LocaleConvertCase(Handle<String> s, Isolate* isolate, |
954 bool is_to_upper, const char* lang) { | 943 bool is_to_upper, const char* lang) { |
| 944 auto case_converter = is_to_upper ? u_strToUpper : u_strToLower; |
955 int32_t src_length = s->length(); | 945 int32_t src_length = s->length(); |
956 | |
957 // Greek uppercasing has to be done via transliteration. | |
958 // TODO(jshin): Drop this special-casing once ICU's regular case conversion | |
959 // API supports Greek uppercasing. See | |
960 // http://bugs.icu-project.org/trac/ticket/10582 . | |
961 // In the meantime, if there's no Greek character in |s|, call this | |
962 // function again with the root locale (lang=""). | |
963 // ICU's C API for transliteration is nasty and we just use C++ API. | |
964 if (V8_UNLIKELY(is_to_upper && lang[0] == 'e' && lang[1] == 'l')) { | |
965 icu::UnicodeString converted; | |
966 std::unique_ptr<uc16[]> sap; | |
967 { | |
968 DisallowHeapAllocation no_gc; | |
969 String::FlatContent flat = s->GetFlatContent(); | |
970 const UChar* src = GetUCharBufferFromFlat(flat, &sap, src_length); | |
971 // Starts with the source string (read-only alias with copy-on-write | |
972 // semantics) and will be modified to contain the converted result. | |
973 // Using read-only alias at first saves one copy operation if | |
974 // transliteration does not change the input, which is rather rare. | |
975 // Moreover, transliteration takes rather long so that saving one copy | |
976 // helps only a little bit. | |
977 converted.setTo(false, src, src_length); | |
978 ConvertCaseWithTransliterator(&converted, "el-Upper"); | |
979 // If no change is made, just return |s|. | |
980 if (converted.getBuffer() == src) return *s; | |
981 } | |
982 RETURN_RESULT_OR_FAILURE( | |
983 isolate, | |
984 isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>( | |
985 reinterpret_cast<const uint16_t*>(converted.getBuffer()), | |
986 converted.length()))); | |
987 } | |
988 | |
989 auto case_converter = is_to_upper ? u_strToUpper : u_strToLower; | |
990 | |
991 int32_t dest_length = src_length; | 946 int32_t dest_length = src_length; |
992 UErrorCode status; | 947 UErrorCode status; |
993 Handle<SeqTwoByteString> result; | 948 Handle<SeqTwoByteString> result; |
994 std::unique_ptr<uc16[]> sap; | 949 std::unique_ptr<uc16[]> sap; |
995 | 950 |
996 // This is not a real loop. It'll be executed only once (no overflow) or | 951 // This is not a real loop. It'll be executed only once (no overflow) or |
997 // twice (overflow). | 952 // twice (overflow). |
998 for (int i = 0; i < 2; ++i) { | 953 for (int i = 0; i < 2; ++i) { |
999 // Case conversion can increase the string length (e.g. sharp-S => SS) so | 954 // Case conversion can increase the string length (e.g. sharp-S => SS) so |
1000 // that we have to handle RangeError exceptions here. | 955 // that we have to handle RangeError exceptions here. |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 Handle<FixedArray> date_cache_version = | 1247 Handle<FixedArray> date_cache_version = |
1293 Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton( | 1248 Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton( |
1294 EternalHandles::DATE_CACHE_VERSION)); | 1249 EternalHandles::DATE_CACHE_VERSION)); |
1295 return date_cache_version->get(0); | 1250 return date_cache_version->get(0); |
1296 } | 1251 } |
1297 | 1252 |
1298 } // namespace internal | 1253 } // namespace internal |
1299 } // namespace v8 | 1254 } // namespace v8 |
1300 | 1255 |
1301 #endif // V8_I18N_SUPPORT | 1256 #endif // V8_I18N_SUPPORT |
OLD | NEW |