1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License. 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17757a7942eed2b0aa457f8517a0259d2ac82c5b18Elliott Hughes#define LOG_TAG "ICU" 18c08f9fb2a3be82bb1a3f477ca1524ddcf7a1d4b8Elliott Hughes 193aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes#include "IcuUtilities.h" 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "JNIHelp.h" 21a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes#include "JniConstants.h" 22bef9ec33e1368f57c731fce63b6a8c61628c64b0Elliott Hughes#include "JniException.h" 23566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include "ScopedFd.h" 24a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes#include "ScopedIcuLocale.h" 254e3714f7fe8ac7f6b20896038e491d378f4e6464Elliott Hughes#include "ScopedJavaUnicodeString.h" 26f281667712baf8e0721ceb2cc60e7eef19c2d859Elliott Hughes#include "ScopedLocalRef.h" 279de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes#include "ScopedUtfChars.h" 28f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes#include "cutils/log.h" 29ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes#include "toStringArray.h" 303879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes#include "unicode/brkiter.h" 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "unicode/calendar.h" 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "unicode/datefmt.h" 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "unicode/dcfmtsym.h" 3494782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/decimfmt.h" 3594782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/dtfmtsym.h" 36cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes#include "unicode/dtptngen.h" 3794782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/gregocal.h" 3894782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/locid.h" 3994782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/numfmt.h" 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "unicode/strenum.h" 41cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fuller#include "unicode/timezone.h" 4294782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/ubrk.h" 4394782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/ucal.h" 4494782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/uclean.h" 4594782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/ucol.h" 4694782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/ucurr.h" 4794782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/udat.h" 480452e9adf6fb133b6d3e59ebae2135aa90ad0d5eFabrice Di Meglio#include "unicode/uloc.h" 4915d82808bab24f399a034d086f587d5fab32522eElliott Hughes#include "unicode/ulocdata.h" 5094782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/ustring.h" 51947eeb80f985827209c9500851e288504d58ec2eclaireho#include "ureslocs.h" 5294782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "valueOf.h" 53ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes 54566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <errno.h> 55566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <fcntl.h> 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdlib.h> 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <string.h> 58ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes#include <string> 59566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <sys/mman.h> 60566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <sys/stat.h> 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <sys/time.h> 62566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <sys/types.h> 63566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <time.h> 64566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <unistd.h> 65b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogers#include <memory> 66c5b1eb191102a20bc0626aea955aba417e337fbcNarayan Kamath#include <vector> 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6870fa193185427473999f1cda823c1ec408acd2baElliott Hughesclass ScopedResourceBundle { 69c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes public: 70c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes ScopedResourceBundle(UResourceBundle* bundle) : bundle_(bundle) { 71c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 73c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes ~ScopedResourceBundle() { 74c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (bundle_ != NULL) { 75c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes ures_close(bundle_); 7670fa193185427473999f1cda823c1ec408acd2baElliott Hughes } 77c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 79c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes UResourceBundle* get() { 80c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return bundle_; 81c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 8270fa193185427473999f1cda823c1ec408acd2baElliott Hughes 83c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes bool hasKey(const char* key) { 84c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes UErrorCode status = U_ZERO_ERROR; 85c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes ures_getStringByKey(bundle_, key, NULL, &status); 86c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return U_SUCCESS(status); 87c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 887ca6fd0dca02f7abdd8808db78357743bbdd23a5Elliott Hughes 89c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes private: 90c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes UResourceBundle* bundle_; 91c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes DISALLOW_COPY_AND_ASSIGN(ScopedResourceBundle); 9270fa193185427473999f1cda823c1ec408acd2baElliott Hughes}; 9370fa193185427473999f1cda823c1ec408acd2baElliott Hughes 94a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_addLikelySubtags(JNIEnv* env, jclass, jstring javaLocaleName) { 950452e9adf6fb133b6d3e59ebae2135aa90ad0d5eFabrice Di Meglio UErrorCode status = U_ZERO_ERROR; 96a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedUtfChars localeID(env, javaLocaleName); 970452e9adf6fb133b6d3e59ebae2135aa90ad0d5eFabrice Di Meglio char maximizedLocaleID[ULOC_FULLNAME_CAPACITY]; 980452e9adf6fb133b6d3e59ebae2135aa90ad0d5eFabrice Di Meglio uloc_addLikelySubtags(localeID.c_str(), maximizedLocaleID, sizeof(maximizedLocaleID), &status); 990452e9adf6fb133b6d3e59ebae2135aa90ad0d5eFabrice Di Meglio if (U_FAILURE(status)) { 100a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return javaLocaleName; 1010452e9adf6fb133b6d3e59ebae2135aa90ad0d5eFabrice Di Meglio } 1020452e9adf6fb133b6d3e59ebae2135aa90ad0d5eFabrice Di Meglio return env->NewStringUTF(maximizedLocaleID); 1030452e9adf6fb133b6d3e59ebae2135aa90ad0d5eFabrice Di Meglio} 1040452e9adf6fb133b6d3e59ebae2135aa90ad0d5eFabrice Di Meglio 105a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_getScript(JNIEnv* env, jclass, jstring javaLocaleName) { 106a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLocaleName); 107a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 108a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 109a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 110a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return env->NewStringUTF(icuLocale.locale().getScript()); 1114c94a6128d1fcfaa75539b36c9f50d0c75df6144Fabrice Di Meglio} 1124c94a6128d1fcfaa75539b36c9f50d0c75df6144Fabrice Di Meglio 11352b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughesstatic jint ICU_getCurrencyFractionDigits(JNIEnv* env, jclass, jstring javaCurrencyCode) { 1143aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode); 1153aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes if (!currencyCode.valid()) { 1163aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes return 0; 1173aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes } 118a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString icuCurrencyCode(currencyCode.unicodeString()); 1193aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes UErrorCode status = U_ZERO_ERROR; 1203aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes return ucurr_getDefaultFractionDigits(icuCurrencyCode.getTerminatedBuffer(), &status); 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 123d627bd4525e41b0503f94c2887c3e01618c73105Neil Fullerstatic jint ICU_getCurrencyNumericCode(JNIEnv* env, jclass, jstring javaCurrencyCode) { 124d627bd4525e41b0503f94c2887c3e01618c73105Neil Fuller ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode); 125d627bd4525e41b0503f94c2887c3e01618c73105Neil Fuller if (!currencyCode.valid()) { 126d627bd4525e41b0503f94c2887c3e01618c73105Neil Fuller return 0; 127d627bd4525e41b0503f94c2887c3e01618c73105Neil Fuller } 128a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString icuCurrencyCode(currencyCode.unicodeString()); 129d627bd4525e41b0503f94c2887c3e01618c73105Neil Fuller return ucurr_getNumericCode(icuCurrencyCode.getTerminatedBuffer()); 130d627bd4525e41b0503f94c2887c3e01618c73105Neil Fuller} 131d627bd4525e41b0503f94c2887c3e01618c73105Neil Fuller 132a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes// TODO: rewrite this with int32_t ucurr_forLocale(const char* locale, UChar* buff, int32_t buffCapacity, UErrorCode* ec)... 13352b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughesstatic jstring ICU_getCurrencyCode(JNIEnv* env, jclass, jstring javaCountryCode) { 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project UErrorCode status = U_ZERO_ERROR; 135947eeb80f985827209c9500851e288504d58ec2eclaireho ScopedResourceBundle supplData(ures_openDirect(U_ICUDATA_CURR, "supplementalData", &status)); 13670fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 14070fa193185427473999f1cda823c1ec408acd2baElliott Hughes ScopedResourceBundle currencyMap(ures_getByKey(supplData.get(), "CurrencyMap", NULL, &status)); 14170fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 14552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes ScopedUtfChars countryCode(env, javaCountryCode); 14652b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes ScopedResourceBundle currency(ures_getByKey(currencyMap.get(), countryCode.c_str(), NULL, &status)); 14770fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 15170fa193185427473999f1cda823c1ec408acd2baElliott Hughes ScopedResourceBundle currencyElem(ures_getByIndex(currency.get(), 0, NULL, &status)); 15270fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 1535b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho return env->NewStringUTF("XXX"); 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 15652b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes // Check if there's a 'to' date. If there is, the currency isn't used anymore. 15767081ff5bcb8a2b3f7db2940f6e0cb3e459ab4b4Elliott Hughes ScopedResourceBundle currencyTo(ures_getByKey(currencyElem.get(), "to", NULL, &status)); 15867081ff5bcb8a2b3f7db2940f6e0cb3e459ab4b4Elliott Hughes if (!U_FAILURE(status)) { 15967081ff5bcb8a2b3f7db2940f6e0cb3e459ab4b4Elliott Hughes return NULL; 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 16152b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes // Ignore the failure to find a 'to' date. 16267081ff5bcb8a2b3f7db2940f6e0cb3e459ab4b4Elliott Hughes status = U_ZERO_ERROR; 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 16470fa193185427473999f1cda823c1ec408acd2baElliott Hughes ScopedResourceBundle currencyId(ures_getByKey(currencyElem.get(), "id", NULL, &status)); 16570fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // No id defined for this country 1675b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho return env->NewStringUTF("XXX"); 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17052b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes int32_t charCount; 17152b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes const jchar* chars = ures_getString(currencyId.get(), &charCount, &status); 1725b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho return (charCount == 0) ? env->NewStringUTF("XXX") : env->NewString(chars, charCount); 17352b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes} 17452b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes 175a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring getCurrencyName(JNIEnv* env, jstring javaLanguageTag, jstring javaCurrencyCode, UCurrNameStyle nameStyle) { 176a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedUtfChars languageTag(env, javaLanguageTag); 177a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (languageTag.c_str() == NULL) { 1783aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes return NULL; 1793aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes } 180a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode); 1813aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes if (!currencyCode.valid()) { 1823aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes return NULL; 1833aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes } 184a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString icuCurrencyCode(currencyCode.unicodeString()); 185a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes UErrorCode status = U_ZERO_ERROR; 186a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes UBool isChoiceFormat = false; 187a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes int32_t charCount; 188a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes const UChar* chars = ucurr_getName(icuCurrencyCode.getTerminatedBuffer(), languageTag.c_str(), 189a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes nameStyle, &isChoiceFormat, &charCount, &status); 190a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes if (status == U_USING_DEFAULT_WARNING) { 191a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes if (nameStyle == UCURR_SYMBOL_NAME) { 192a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes // ICU doesn't distinguish between falling back to the root locale and meeting a genuinely 193a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes // unknown currency. The Currency class does. 194a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes if (!ucurr_isAvailable(icuCurrencyCode.getTerminatedBuffer(), U_DATE_MIN, U_DATE_MAX, &status)) { 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 196a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes } 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 198a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes if (nameStyle == UCURR_LONG_NAME) { 199a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes // ICU's default is English. We want the ISO 4217 currency code instead. 200a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes chars = icuCurrencyCode.getBuffer(); 201a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes charCount = icuCurrencyCode.length(); 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 203a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes } 204a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes return (charCount == 0) ? NULL : env->NewString(chars, charCount); 205a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes} 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 207a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_getCurrencyDisplayName(JNIEnv* env, jclass, jstring javaLanguageTag, jstring javaCurrencyCode) { 208a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return getCurrencyName(env, javaLanguageTag, javaCurrencyCode, UCURR_LONG_NAME); 209a49a1e8c20b3cf9435ed422379f63e33e5c2eaf2Elliott Hughes} 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 211a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_getCurrencySymbol(JNIEnv* env, jclass, jstring javaLanguageTag, jstring javaCurrencyCode) { 212a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return getCurrencyName(env, javaLanguageTag, javaCurrencyCode, UCURR_SYMBOL_NAME); 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 215a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_getDisplayCountryNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) { 216a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLanguageTag); 217a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 218a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 219a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 220a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag); 221a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuTargetLocale.valid()) { 222a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 223a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 224a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes 225a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString str; 226a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes icuTargetLocale.locale().getDisplayCountry(icuLocale.locale(), str); 227a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return env->NewString(str.getBuffer(), str.length()); 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 230a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_getDisplayLanguageNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) { 231a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLanguageTag); 232a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 233a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 234a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 235a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag); 236a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuTargetLocale.valid()) { 237a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 238a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 239a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes 240a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString str; 241a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes icuTargetLocale.locale().getDisplayLanguage(icuLocale.locale(), str); 242a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return env->NewString(str.getBuffer(), str.length()); 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 245a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_getDisplayScriptNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) { 246a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLanguageTag); 247a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 248a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 249a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 250a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag); 251a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuTargetLocale.valid()) { 252a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 253a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 254a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes 255a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString str; 256a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes icuTargetLocale.locale().getDisplayScript(icuLocale.locale(), str); 257a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return env->NewString(str.getBuffer(), str.length()); 258c5b1eb191102a20bc0626aea955aba417e337fbcNarayan Kamath} 259c5b1eb191102a20bc0626aea955aba417e337fbcNarayan Kamath 260a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_getDisplayVariantNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) { 261a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLanguageTag); 262a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 263a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 264a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 265a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag); 266a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuTargetLocale.valid()) { 267a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 268a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 269a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes 270a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString str; 271a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes icuTargetLocale.locale().getDisplayVariant(icuLocale.locale(), str); 272a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return env->NewString(str.getBuffer(), str.length()); 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 275ca6c2dfd21fef61f179223fb710db791802068d5Narayan Kamathstatic jstring ICU_getISO3Country(JNIEnv* env, jclass, jstring javaLanguageTag) { 276a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLanguageTag); 277a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 278a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 279a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 280a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return env->NewStringUTF(icuLocale.locale().getISO3Country()); 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 283ca6c2dfd21fef61f179223fb710db791802068d5Narayan Kamathstatic jstring ICU_getISO3Language(JNIEnv* env, jclass, jstring javaLanguageTag) { 284a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLanguageTag); 285a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 286a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 287a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 288a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return env->NewStringUTF(icuLocale.locale().getISO3Language()); 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 291e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getISOCountriesNative(JNIEnv* env, jclass) { 292a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes return toStringArray(env, icu::Locale::getISOCountries()); 2932e3a41defb42a97b463194d859d2d4088a600fd8Elliott Hughes} 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 295e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getISOLanguagesNative(JNIEnv* env, jclass) { 296a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes return toStringArray(env, icu::Locale::getISOLanguages()); 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 299e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableLocalesNative(JNIEnv* env, jclass) { 300ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, uloc_countAvailable, uloc_getAvailable); 301f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 302f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 303e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableBreakIteratorLocalesNative(JNIEnv* env, jclass) { 304ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, ubrk_countAvailable, ubrk_getAvailable); 305f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 306f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 307e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableCalendarLocalesNative(JNIEnv* env, jclass) { 308ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, ucal_countAvailable, ucal_getAvailable); 309f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 310f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 311e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableCollatorLocalesNative(JNIEnv* env, jclass) { 312ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, ucol_countAvailable, ucol_getAvailable); 313f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 314f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 315e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableDateFormatLocalesNative(JNIEnv* env, jclass) { 316ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, udat_countAvailable, udat_getAvailable); 317f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 318f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 319e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableNumberFormatLocalesNative(JNIEnv* env, jclass) { 320ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, unum_countAvailable, unum_getAvailable); 321f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 322f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 32333aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughesstatic void setIntegerField(JNIEnv* env, jobject obj, const char* fieldName, int value) { 32494782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes ScopedLocalRef<jobject> integerValue(env, integerValueOf(env, value)); 325a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes jfieldID fid = env->GetFieldID(JniConstants::localeDataClass, fieldName, "Ljava/lang/Integer;"); 32694782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes env->SetObjectField(obj, fid, integerValue.get()); 32733aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes} 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 32933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughesstatic void setStringField(JNIEnv* env, jobject obj, const char* fieldName, jstring value) { 330a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes jfieldID fid = env->GetFieldID(JniConstants::localeDataClass, fieldName, "Ljava/lang/String;"); 33133aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes env->SetObjectField(obj, fid, value); 332e2377cdd707b830d07a5708216834f7ac76ee3e1Elliott Hughes env->DeleteLocalRef(value); 33333aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes} 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 33533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughesstatic void setStringArrayField(JNIEnv* env, jobject obj, const char* fieldName, jobjectArray value) { 336a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes jfieldID fid = env->GetFieldID(JniConstants::localeDataClass, fieldName, "[Ljava/lang/String;"); 33733aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes env->SetObjectField(obj, fid, value); 33833aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes} 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 340a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughesstatic void setStringArrayField(JNIEnv* env, jobject obj, const char* fieldName, const icu::UnicodeString* valueArray, int32_t size) { 3415b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho ScopedLocalRef<jobjectArray> result(env, env->NewObjectArray(size, JniConstants::stringClass, NULL)); 3425b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho for (int32_t i = 0; i < size ; i++) { 3435b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho ScopedLocalRef<jstring> s(env, env->NewString(valueArray[i].getBuffer(),valueArray[i].length())); 3445b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho if (env->ExceptionCheck()) { 3455b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho return; 3465b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho } 3475b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho env->SetObjectArrayElement(result.get(), i, s.get()); 3485b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho if (env->ExceptionCheck()) { 3495b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho return; 3505b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho } 3515b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho } 3525b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, obj, fieldName, result.get()); 3535b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho} 3545b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho 35533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughesstatic void setStringField(JNIEnv* env, jobject obj, const char* fieldName, UResourceBundle* bundle, int index) { 356c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes UErrorCode status = U_ZERO_ERROR; 357c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes int charCount; 358c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes const UChar* chars = ures_getStringByIndex(bundle, index, &charCount, &status); 359c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (U_SUCCESS(status)) { 360c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes setStringField(env, obj, fieldName, env->NewString(chars, charCount)); 361c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } else { 362c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes ALOGE("Error setting String field %s from ICU resource (index %d): %s", fieldName, index, u_errorName(status)); 363c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 364c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes} 365c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 366a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughesstatic void setCharField(JNIEnv* env, jobject obj, const char* fieldName, const icu::UnicodeString& value) { 3675b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho if (value.length() == 0) { 3685b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho return; 3693be1277a4644a149c158f99febbab890fc7b708fclaireho } 3705b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho jfieldID fid = env->GetFieldID(JniConstants::localeDataClass, fieldName, "C"); 3715b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho env->SetCharField(obj, fid, value.charAt(0)); 3723be1277a4644a149c158f99febbab890fc7b708fclaireho} 3733be1277a4644a149c158f99febbab890fc7b708fclaireho 374a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughesstatic void setStringField(JNIEnv* env, jobject obj, const char* fieldName, const icu::UnicodeString& value) { 3755b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho const UChar* chars = value.getBuffer(); 3765b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringField(env, obj, fieldName, env->NewString(chars, value.length())); 3773be1277a4644a149c158f99febbab890fc7b708fclaireho} 3783be1277a4644a149c158f99febbab890fc7b708fclaireho 379a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughesstatic void setNumberPatterns(JNIEnv* env, jobject obj, icu::Locale& locale) { 3803be1277a4644a149c158f99febbab890fc7b708fclaireho UErrorCode status = U_ZERO_ERROR; 3813be1277a4644a149c158f99febbab890fc7b708fclaireho 382a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString pattern; 383a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes std::unique_ptr<icu::DecimalFormat> fmt(static_cast<icu::DecimalFormat*>(icu::NumberFormat::createInstance(locale, UNUM_CURRENCY, status))); 3845b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho pattern = fmt->toPattern(pattern.remove()); 3855b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringField(env, obj, "currencyPattern", pattern); 3863be1277a4644a149c158f99febbab890fc7b708fclaireho 387a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes fmt.reset(static_cast<icu::DecimalFormat*>(icu::NumberFormat::createInstance(locale, UNUM_DECIMAL, status))); 3885b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho pattern = fmt->toPattern(pattern.remove()); 3895b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringField(env, obj, "numberPattern", pattern); 3903be1277a4644a149c158f99febbab890fc7b708fclaireho 391a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes fmt.reset(static_cast<icu::DecimalFormat*>(icu::NumberFormat::createInstance(locale, UNUM_PERCENT, status))); 3925b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho pattern = fmt->toPattern(pattern.remove()); 3935b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringField(env, obj, "percentPattern", pattern); 3943be1277a4644a149c158f99febbab890fc7b708fclaireho} 3953be1277a4644a149c158f99febbab890fc7b708fclaireho 396a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughesstatic void setDecimalFormatSymbolsData(JNIEnv* env, jobject obj, icu::Locale& locale) { 3973be1277a4644a149c158f99febbab890fc7b708fclaireho UErrorCode status = U_ZERO_ERROR; 398a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::DecimalFormatSymbols dfs(locale, status); 3995b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho 400a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setCharField(env, obj, "decimalSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kDecimalSeparatorSymbol)); 401a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setCharField(env, obj, "groupingSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kGroupingSeparatorSymbol)); 402a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setCharField(env, obj, "patternSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kPatternSeparatorSymbol)); 403a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setStringField(env, obj, "percent", dfs.getSymbol(icu::DecimalFormatSymbols::kPercentSymbol)); 404a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setCharField(env, obj, "perMill", dfs.getSymbol(icu::DecimalFormatSymbols::kPerMillSymbol)); 405a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setCharField(env, obj, "monetarySeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kMonetarySeparatorSymbol)); 406a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setStringField(env, obj, "minusSign", dfs.getSymbol(icu::DecimalFormatSymbols:: kMinusSignSymbol)); 407a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setStringField(env, obj, "exponentSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kExponentialSymbol)); 408a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setStringField(env, obj, "infinity", dfs.getSymbol(icu::DecimalFormatSymbols::kInfinitySymbol)); 409a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setStringField(env, obj, "NaN", dfs.getSymbol(icu::DecimalFormatSymbols::kNaNSymbol)); 410a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes setCharField(env, obj, "zeroDigit", dfs.getSymbol(icu::DecimalFormatSymbols::kZeroDigitSymbol)); 4113be1277a4644a149c158f99febbab890fc7b708fclaireho} 4123be1277a4644a149c158f99febbab890fc7b708fclaireho 413c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 414c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes// Iterates up through the locale hierarchy. So "en_US" would return "en_US", "en", "". 415c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughesclass LocaleNameIterator { 416c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes public: 417c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes LocaleNameIterator(const char* locale_name, UErrorCode& status) : status_(status), has_next_(true) { 418c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes strcpy(locale_name_, locale_name); 419c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes locale_name_length_ = strlen(locale_name_); 420c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 421c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 422c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes const char* Get() { 423c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return locale_name_; 424c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 425c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 426c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes bool HasNext() { 427c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return has_next_; 428c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 429c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 430c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes void Up() { 431c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (locale_name_length_ == 0) { 432c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes has_next_ = false; 433f001abe6478c2ece3d86138f649a5459de85a50aElliott Hughes } else { 434f001abe6478c2ece3d86138f649a5459de85a50aElliott Hughes locale_name_length_ = uloc_getParent(locale_name_, locale_name_, sizeof(locale_name_), &status_); 435c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 436c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 437c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 438c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes private: 439c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes UErrorCode& status_; 440c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes bool has_next_; 441c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes char locale_name_[ULOC_FULLNAME_CAPACITY]; 442c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes int32_t locale_name_length_; 443c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 444c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes DISALLOW_COPY_AND_ASSIGN(LocaleNameIterator); 445c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes}; 446c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 447b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughesstatic bool getAmPmMarkersNarrow(JNIEnv* env, jobject localeData, const char* locale_name) { 448b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes UErrorCode status = U_ZERO_ERROR; 449b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes ScopedResourceBundle root(ures_open(NULL, locale_name, &status)); 450b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes if (U_FAILURE(status)) { 451b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes return false; 452b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes } 453b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status)); 454b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes if (U_FAILURE(status)) { 455b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes return false; 456b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes } 457b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status)); 458b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes if (U_FAILURE(status)) { 459b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes return false; 460b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes } 461b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes ScopedResourceBundle amPmMarkersNarrow(ures_getByKey(gregorian.get(), "AmPmMarkersNarrow", NULL, &status)); 462b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes if (U_FAILURE(status)) { 463b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes return false; 464b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes } 465b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes setStringField(env, localeData, "narrowAm", amPmMarkersNarrow.get(), 0); 466b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes setStringField(env, localeData, "narrowPm", amPmMarkersNarrow.get(), 1); 467b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes return true; 468b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes} 469b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes 470c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughesstatic bool getDateTimePatterns(JNIEnv* env, jobject localeData, const char* locale_name) { 471c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes UErrorCode status = U_ZERO_ERROR; 472c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes ScopedResourceBundle root(ures_open(NULL, locale_name, &status)); 473c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (U_FAILURE(status)) { 474c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return false; 475c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 476c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status)); 477c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (U_FAILURE(status)) { 478c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return false; 479c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 480c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status)); 481c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (U_FAILURE(status)) { 482c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return false; 483c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 484c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes ScopedResourceBundle dateTimePatterns(ures_getByKey(gregorian.get(), "DateTimePatterns", NULL, &status)); 485c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (U_FAILURE(status)) { 486c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return false; 487c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 488c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes setStringField(env, localeData, "fullTimeFormat", dateTimePatterns.get(), 0); 489c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes setStringField(env, localeData, "longTimeFormat", dateTimePatterns.get(), 1); 490c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes setStringField(env, localeData, "mediumTimeFormat", dateTimePatterns.get(), 2); 491c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes setStringField(env, localeData, "shortTimeFormat", dateTimePatterns.get(), 3); 492c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes setStringField(env, localeData, "fullDateFormat", dateTimePatterns.get(), 4); 493c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes setStringField(env, localeData, "longDateFormat", dateTimePatterns.get(), 5); 494c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes setStringField(env, localeData, "mediumDateFormat", dateTimePatterns.get(), 6); 495c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes setStringField(env, localeData, "shortDateFormat", dateTimePatterns.get(), 7); 496c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return true; 497c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes} 498c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 499a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughesstatic bool getYesterdayTodayAndTomorrow(JNIEnv* env, jobject localeData, const icu::Locale& locale, const char* locale_name) { 500c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes UErrorCode status = U_ZERO_ERROR; 501c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes ScopedResourceBundle root(ures_open(NULL, locale_name, &status)); 5020ef9944d1968207ae8501aca5f904809320c520eElliott Hughes ScopedResourceBundle fields(ures_getByKey(root.get(), "fields", NULL, &status)); 5033879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes ScopedResourceBundle day(ures_getByKey(fields.get(), "day", NULL, &status)); 5043879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes ScopedResourceBundle relative(ures_getByKey(day.get(), "relative", NULL, &status)); 505c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (U_FAILURE(status)) { 506c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return false; 507c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 5083879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes 509a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString yesterday(icu::ures_getUnicodeStringByKey(relative.get(), "-1", &status)); 510a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString today(icu::ures_getUnicodeStringByKey(relative.get(), "0", &status)); 511a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString tomorrow(icu::ures_getUnicodeStringByKey(relative.get(), "1", &status)); 512c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (U_FAILURE(status)) { 513b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes ALOGE("Error getting yesterday/today/tomorrow for %s: %s", locale_name, u_errorName(status)); 514c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return false; 515c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 5163879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes 5173879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes // We title-case the strings so they have consistent capitalization (http://b/14493853). 518a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes std::unique_ptr<icu::BreakIterator> brk(icu::BreakIterator::createSentenceInstance(locale, status)); 519c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (U_FAILURE(status)) { 520b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes ALOGE("Error getting yesterday/today/tomorrow break iterator for %s: %s", locale_name, u_errorName(status)); 521c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return false; 522c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 5233879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes yesterday.toTitle(brk.get(), locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); 5243879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes today.toTitle(brk.get(), locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); 5253879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes tomorrow.toTitle(brk.get(), locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); 5263879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes 5273879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes setStringField(env, localeData, "yesterday", yesterday); 5283879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes setStringField(env, localeData, "today", today); 5293879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes setStringField(env, localeData, "tomorrow", tomorrow); 5303879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes return true; 531c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes} 532c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 5335c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamathstatic jboolean ICU_initLocaleDataNative(JNIEnv* env, jclass, jstring javaLanguageTag, jobject localeData) { 5345c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamath ScopedUtfChars languageTag(env, javaLanguageTag); 5355c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamath if (languageTag.c_str() == NULL) { 5365b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho return JNI_FALSE; 5373be1277a4644a149c158f99febbab890fc7b708fclaireho } 5385c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamath if (languageTag.size() >= ULOC_FULLNAME_CAPACITY) { 539c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes return JNI_FALSE; // ICU has a fixed-length limit. 5405b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho } 5415b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho 5425c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamath ScopedIcuLocale icuLocale(env, javaLanguageTag); 543a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 544a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return JNI_FALSE; 545a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 5463879b91e1baee17ecd51c653200ebdafc011020cElliott Hughes 547c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes // Get the DateTimePatterns. 548c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes UErrorCode status = U_ZERO_ERROR; 549c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes bool foundDateTimePatterns = false; 5505c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamath for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) { 551c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (getDateTimePatterns(env, localeData, it.Get())) { 552c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes foundDateTimePatterns = true; 553c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes break; 554c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 555c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 556c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (!foundDateTimePatterns) { 5575c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamath ALOGE("Couldn't find ICU DateTimePatterns for %s", languageTag.c_str()); 55833aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return JNI_FALSE; 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 561c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes // Get the "Yesterday", "Today", and "Tomorrow" strings. 562c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes bool foundYesterdayTodayAndTomorrow = false; 5635c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamath for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) { 564a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (getYesterdayTodayAndTomorrow(env, localeData, icuLocale.locale(), it.Get())) { 565c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes foundYesterdayTodayAndTomorrow = true; 566c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes break; 567c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 568c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 569c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes if (!foundYesterdayTodayAndTomorrow) { 5705c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamath ALOGE("Couldn't find ICU yesterday/today/tomorrow for %s", languageTag.c_str()); 571680b1e27caf10e3c41ec9f022054ab53d3a6bf7aElliott Hughes return JNI_FALSE; 572c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes } 573c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 574b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes // Get the narrow "AM" and "PM" strings. 575b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes bool foundAmPmMarkersNarrow = false; 576b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) { 577b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes if (getAmPmMarkersNarrow(env, localeData, it.Get())) { 578b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes foundAmPmMarkersNarrow = true; 579b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes break; 580b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes } 581b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes } 582b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes if (!foundAmPmMarkersNarrow) { 583b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes ALOGE("Couldn't find ICU AmPmMarkersNarrow for %s", languageTag.c_str()); 584b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes return JNI_FALSE; 585b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes } 586b799123bc221b926a9f189107f2a3619a4da8874Elliott Hughes 5875b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho status = U_ZERO_ERROR; 588a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes std::unique_ptr<icu::Calendar> cal(icu::Calendar::createInstance(icuLocale.locale(), status)); 58933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (U_FAILURE(status)) { 59033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return JNI_FALSE; 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 592c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 5935b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setIntegerField(env, localeData, "firstDayOfWeek", cal->getFirstDayOfWeek()); 5945b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setIntegerField(env, localeData, "minimalDaysInFirstWeek", cal->getMinimalDaysInFirstWeek()); 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 596c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes // Get DateFormatSymbols. 5975b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho status = U_ZERO_ERROR; 598a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::DateFormatSymbols dateFormatSym(icuLocale.locale(), status); 59933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (U_FAILURE(status)) { 60033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return JNI_FALSE; 601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 602c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes 603c4e0797a4dd028d23e788da15c3055f83f6f37d5Elliott Hughes // Get AM/PM and BC/AD. 6045b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho int32_t count = 0; 605a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* amPmStrs = dateFormatSym.getAmPmStrings(count); 6065b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, localeData, "amPm", amPmStrs, count); 607a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* erasStrs = dateFormatSym.getEras(count); 6085b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, localeData, "eras", erasStrs, count); 6095b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho 610a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* longMonthNames = 611a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getMonths(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::WIDE); 6125b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, localeData, "longMonthNames", longMonthNames, count); 613a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* shortMonthNames = 614a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getMonths(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::ABBREVIATED); 6155b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, localeData, "shortMonthNames", shortMonthNames, count); 616a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* tinyMonthNames = 617a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getMonths(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::NARROW); 618ad66a888b2e48b1a185de1b3c73fd01383a1fd04Elliott Hughes setStringArrayField(env, localeData, "tinyMonthNames", tinyMonthNames, count); 619a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* longWeekdayNames = 620a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::WIDE); 6215b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, localeData, "longWeekdayNames", longWeekdayNames, count); 622a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* shortWeekdayNames = 623a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::ABBREVIATED); 6245b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, localeData, "shortWeekdayNames", shortWeekdayNames, count); 625a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* tinyWeekdayNames = 626a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::NARROW); 627ad66a888b2e48b1a185de1b3c73fd01383a1fd04Elliott Hughes setStringArrayField(env, localeData, "tinyWeekdayNames", tinyWeekdayNames, count); 6285b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho 629a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* longStandAloneMonthNames = 630a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getMonths(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::WIDE); 6315b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, localeData, "longStandAloneMonthNames", longStandAloneMonthNames, count); 632a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* shortStandAloneMonthNames = 633a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getMonths(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::ABBREVIATED); 6345b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, localeData, "shortStandAloneMonthNames", shortStandAloneMonthNames, count); 635a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* tinyStandAloneMonthNames = 636a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getMonths(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::NARROW); 637ad66a888b2e48b1a185de1b3c73fd01383a1fd04Elliott Hughes setStringArrayField(env, localeData, "tinyStandAloneMonthNames", tinyStandAloneMonthNames, count); 638a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* longStandAloneWeekdayNames = 639a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::WIDE); 6405b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, localeData, "longStandAloneWeekdayNames", longStandAloneWeekdayNames, count); 641a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* shortStandAloneWeekdayNames = 642a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::ABBREVIATED); 6435b7b7fe6a817fdf058eefd9a716cc58a3283eb05claireho setStringArrayField(env, localeData, "shortStandAloneWeekdayNames", shortStandAloneWeekdayNames, count); 644a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes const icu::UnicodeString* tinyStandAloneWeekdayNames = 645a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::NARROW); 646ad66a888b2e48b1a185de1b3c73fd01383a1fd04Elliott Hughes setStringArrayField(env, localeData, "tinyStandAloneWeekdayNames", tinyStandAloneWeekdayNames, count); 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 64833aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes status = U_ZERO_ERROR; 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6503be1277a4644a149c158f99febbab890fc7b708fclaireho // For numberPatterns and symbols. 651a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes setNumberPatterns(env, localeData, icuLocale.locale()); 652a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes setDecimalFormatSymbolsData(env, localeData, icuLocale.locale()); 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6545c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamath jstring countryCode = env->NewStringUTF(icuLocale.locale().getCountry()); 65552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes jstring internationalCurrencySymbol = ICU_getCurrencyCode(env, NULL, countryCode); 656e2377cdd707b830d07a5708216834f7ac76ee3e1Elliott Hughes env->DeleteLocalRef(countryCode); 657e2377cdd707b830d07a5708216834f7ac76ee3e1Elliott Hughes countryCode = NULL; 658e2377cdd707b830d07a5708216834f7ac76ee3e1Elliott Hughes 65933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes jstring currencySymbol = NULL; 66033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (internationalCurrencySymbol != NULL) { 6615c0472fd7c53464e526bb833707551d85dbafec1Narayan Kamath currencySymbol = ICU_getCurrencySymbol(env, NULL, javaLanguageTag, internationalCurrencySymbol); 662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 66333aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes internationalCurrencySymbol = env->NewStringUTF("XXX"); 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 66533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (currencySymbol == NULL) { 66633aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes // This is the UTF-8 encoding of U+00A4 (CURRENCY SIGN). 667ad884a7b8cae7a1c3d973c8032d4f78ef7c96b80Hao Feng currencySymbol = env->NewStringUTF("\xc2\xa4"); 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 66933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringField(env, localeData, "currencySymbol", currencySymbol); 67033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringField(env, localeData, "internationalCurrencySymbol", internationalCurrencySymbol); 671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 67233aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return JNI_TRUE; 673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 675a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_toLowerCase(JNIEnv* env, jclass, jstring javaString, jstring javaLanguageTag) { 6763aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes ScopedJavaUnicodeString scopedString(env, javaString); 6773aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes if (!scopedString.valid()) { 6783aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes return NULL; 6793aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes } 680a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLanguageTag); 681a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 682a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 683a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 684a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString& s(scopedString.unicodeString()); 685a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString original(s); 686a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes s.toLower(icuLocale.locale()); 6873aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes return s == original ? javaString : env->NewString(s.getBuffer(), s.length()); 688dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes} 689dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes 690a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_toUpperCase(JNIEnv* env, jclass, jstring javaString, jstring javaLanguageTag) { 6913aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes ScopedJavaUnicodeString scopedString(env, javaString); 6923aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes if (!scopedString.valid()) { 6933aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes return NULL; 6943aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes } 695a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLanguageTag); 696a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 697a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 698a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 699a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString& s(scopedString.unicodeString()); 700a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString original(s); 701a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes s.toUpper(icuLocale.locale()); 7023aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes return s == original ? javaString : env->NewString(s.getBuffer(), s.length()); 703dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes} 704dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes 705e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughesstatic jstring versionString(JNIEnv* env, const UVersionInfo& version) { 706e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes char versionString[U_MAX_VERSION_STRING_LENGTH]; 707e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes u_versionToString(const_cast<UVersionInfo&>(version), &versionString[0]); 708e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes return env->NewStringUTF(versionString); 709e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes} 710e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes 71115d82808bab24f399a034d086f587d5fab32522eElliott Hughesstatic jstring ICU_getCldrVersion(JNIEnv* env, jclass) { 71215d82808bab24f399a034d086f587d5fab32522eElliott Hughes UErrorCode status = U_ZERO_ERROR; 71315d82808bab24f399a034d086f587d5fab32522eElliott Hughes UVersionInfo cldrVersion; 71415d82808bab24f399a034d086f587d5fab32522eElliott Hughes ulocdata_getCLDRVersion(cldrVersion, &status); 71515d82808bab24f399a034d086f587d5fab32522eElliott Hughes return versionString(env, cldrVersion); 71615d82808bab24f399a034d086f587d5fab32522eElliott Hughes} 71715d82808bab24f399a034d086f587d5fab32522eElliott Hughes 718e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughesstatic jstring ICU_getIcuVersion(JNIEnv* env, jclass) { 719e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes UVersionInfo icuVersion; 720e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes u_getVersion(icuVersion); 721e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes return versionString(env, icuVersion); 722e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes} 723e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes 724e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughesstatic jstring ICU_getUnicodeVersion(JNIEnv* env, jclass) { 725e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes UVersionInfo unicodeVersion; 726e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes u_getUnicodeVersion(unicodeVersion); 727e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes return versionString(env, unicodeVersion); 728e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes} 729e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes 730cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fullerstatic jstring ICU_getTZDataVersion(JNIEnv* env, jclass) { 731cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fuller UErrorCode status = U_ZERO_ERROR; 732cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fuller const char* version = icu::TimeZone::getTZDataVersion(status); 733cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fuller if (maybeThrowIcuException(env, "icu::TimeZone::getTZDataVersion", status)) { 734cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fuller return NULL; 735cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fuller } 736cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fuller return env->NewStringUTF(version); 737cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fuller} 738cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fuller 73952b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughesstatic jobject ICU_getAvailableCurrencyCodes(JNIEnv* env, jclass) { 740783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes UErrorCode status = U_ZERO_ERROR; 741a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UStringEnumeration e(ucurr_openISOCurrencies(UCURR_COMMON|UCURR_NON_DEPRECATED, &status)); 742783a57a7ece339bc246925e328bc82b50cae427aElliott Hughes return fromStringEnumeration(env, status, "ucurr_openISOCurrencies", &e); 74352b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes} 74452b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes 745a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic jstring ICU_getBestDateTimePatternNative(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLanguageTag) { 746a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLanguageTag); 747a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 748a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return NULL; 749a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 750a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes 751cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes UErrorCode status = U_ZERO_ERROR; 752a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes std::unique_ptr<icu::DateTimePatternGenerator> generator(icu::DateTimePatternGenerator::createInstance(icuLocale.locale(), status)); 753cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes if (maybeThrowIcuException(env, "DateTimePatternGenerator::createInstance", status)) { 754cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes return NULL; 755cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes } 756cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes 757480537d9d51add98bffe6d9a9ef3b1022b959336Elliott Hughes ScopedJavaUnicodeString skeletonHolder(env, javaSkeleton); 758480537d9d51add98bffe6d9a9ef3b1022b959336Elliott Hughes if (!skeletonHolder.valid()) { 7593aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes return NULL; 7603aac4ddc4d17c07fa8b4908069d23d5401a77993Elliott Hughes } 761a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::UnicodeString result(generator->getBestPattern(skeletonHolder.unicodeString(), status)); 762cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes if (maybeThrowIcuException(env, "DateTimePatternGenerator::getBestPattern", status)) { 763cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes return NULL; 764cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes } 765cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes 766cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes return env->NewString(result.getBuffer(), result.length()); 767cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes} 768cb1b9026b8aa993785c4d54f686905522b7959b9Elliott Hughes 769a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughesstatic void ICU_setDefaultLocale(JNIEnv* env, jclass, jstring javaLanguageTag) { 770a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes ScopedIcuLocale icuLocale(env, javaLanguageTag); 771a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes if (!icuLocale.valid()) { 772a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes return; 773a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes } 774de0eb683370d789e7bb25673b350b8dbf2ba5d69Narayan Kamath 775a94266074c7b82720fd2cecfb37ab8da85f1b296Elliott Hughes UErrorCode status = U_ZERO_ERROR; 776a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes icu::Locale::setDefault(icuLocale.locale(), status); 777de0eb683370d789e7bb25673b350b8dbf2ba5d69Narayan Kamath maybeThrowIcuException(env, "Locale::setDefault", status); 778de0eb683370d789e7bb25673b350b8dbf2ba5d69Narayan Kamath} 779de0eb683370d789e7bb25673b350b8dbf2ba5d69Narayan Kamath 780de0eb683370d789e7bb25673b350b8dbf2ba5d69Narayan Kamathstatic jstring ICU_getDefaultLocale(JNIEnv* env, jclass) { 781a04b5c3d39232c7616591883ee2124520e3ab622Elliott Hughes return env->NewStringUTF(icu::Locale::getDefault().getName()); 782de0eb683370d789e7bb25673b350b8dbf2ba5d69Narayan Kamath} 783de0eb683370d789e7bb25673b350b8dbf2ba5d69Narayan Kamath 784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic JNINativeMethod gMethods[] = { 7850452e9adf6fb133b6d3e59ebae2135aa90ad0d5eFabrice Di Meglio NATIVE_METHOD(ICU, addLikelySubtags, "(Ljava/lang/String;)Ljava/lang/String;"), 786e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableBreakIteratorLocalesNative, "()[Ljava/lang/String;"), 787e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableCalendarLocalesNative, "()[Ljava/lang/String;"), 788e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableCollatorLocalesNative, "()[Ljava/lang/String;"), 78952b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes NATIVE_METHOD(ICU, getAvailableCurrencyCodes, "()[Ljava/lang/String;"), 790e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableDateFormatLocalesNative, "()[Ljava/lang/String;"), 791e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableLocalesNative, "()[Ljava/lang/String;"), 792e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableNumberFormatLocalesNative, "()[Ljava/lang/String;"), 7930fd776f4dbf7c1940c080003f0c7a02d35374ab9Elliott Hughes NATIVE_METHOD(ICU, getBestDateTimePatternNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 79415d82808bab24f399a034d086f587d5fab32522eElliott Hughes NATIVE_METHOD(ICU, getCldrVersion, "()Ljava/lang/String;"), 79552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes NATIVE_METHOD(ICU, getCurrencyCode, "(Ljava/lang/String;)Ljava/lang/String;"), 79652b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes NATIVE_METHOD(ICU, getCurrencyDisplayName, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 79752b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes NATIVE_METHOD(ICU, getCurrencyFractionDigits, "(Ljava/lang/String;)I"), 798d627bd4525e41b0503f94c2887c3e01618c73105Neil Fuller NATIVE_METHOD(ICU, getCurrencyNumericCode, "(Ljava/lang/String;)I"), 79952b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes NATIVE_METHOD(ICU, getCurrencySymbol, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 800de0eb683370d789e7bb25673b350b8dbf2ba5d69Narayan Kamath NATIVE_METHOD(ICU, getDefaultLocale, "()Ljava/lang/String;"), 801e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getDisplayCountryNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 802e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getDisplayLanguageNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 803c5b1eb191102a20bc0626aea955aba417e337fbcNarayan Kamath NATIVE_METHOD(ICU, getDisplayScriptNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 804e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getDisplayVariantNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 805ca6c2dfd21fef61f179223fb710db791802068d5Narayan Kamath NATIVE_METHOD(ICU, getISO3Country, "(Ljava/lang/String;)Ljava/lang/String;"), 806ca6c2dfd21fef61f179223fb710db791802068d5Narayan Kamath NATIVE_METHOD(ICU, getISO3Language, "(Ljava/lang/String;)Ljava/lang/String;"), 807e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getISOCountriesNative, "()[Ljava/lang/String;"), 808e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getISOLanguagesNative, "()[Ljava/lang/String;"), 809e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes NATIVE_METHOD(ICU, getIcuVersion, "()Ljava/lang/String;"), 8104c94a6128d1fcfaa75539b36c9f50d0c75df6144Fabrice Di Meglio NATIVE_METHOD(ICU, getScript, "(Ljava/lang/String;)Ljava/lang/String;"), 811cf14cc4ee0de8c3e4f9a1dab7a5a91d09264dee9Neil Fuller NATIVE_METHOD(ICU, getTZDataVersion, "()Ljava/lang/String;"), 812e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes NATIVE_METHOD(ICU, getUnicodeVersion, "()Ljava/lang/String;"), 8130fd776f4dbf7c1940c080003f0c7a02d35374ab9Elliott Hughes NATIVE_METHOD(ICU, initLocaleDataNative, "(Ljava/lang/String;Llibcore/icu/LocaleData;)Z"), 814de0eb683370d789e7bb25673b350b8dbf2ba5d69Narayan Kamath NATIVE_METHOD(ICU, setDefaultLocale, "(Ljava/lang/String;)V"), 815e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, toLowerCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 816e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, toUpperCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}; 818566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes 819317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller#define FAIL_WITH_STRERROR(s) \ 820317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller ALOGE("Couldn't " s " '%s': %s", path.c_str(), strerror(errno)); \ 821317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller return FALSE; 822317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 823317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller#define MAYBE_FAIL_WITH_ICU_ERROR(s) \ 824317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller if (status != U_ZERO_ERROR) {\ 825317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller ALOGE("Couldn't initialize ICU (" s "): %s (%s)", u_errorName(status), path.c_str()); \ 826317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller return FALSE; \ 827317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller } 828317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 829317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fullerstatic bool mapIcuData(const std::string& path) { 830566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes // Open the file and get its length. 831566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes ScopedFd fd(open(path.c_str(), O_RDONLY)); 832566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes if (fd.get() == -1) { 8339f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes FAIL_WITH_STRERROR("open"); 834566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes } 835566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes struct stat sb; 836566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes if (fstat(fd.get(), &sb) == -1) { 8379f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes FAIL_WITH_STRERROR("stat"); 838566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes } 839566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes 840566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes // Map it. 841566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes void* data = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd.get(), 0); 842566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes if (data == MAP_FAILED) { 8439f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes FAIL_WITH_STRERROR("mmap"); 844566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes } 845566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes 846566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes // Tell the kernel that accesses are likely to be random rather than sequential. 847566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes if (madvise(data, sb.st_size, MADV_RANDOM) == -1) { 8489f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes FAIL_WITH_STRERROR("madvise(MADV_RANDOM)"); 849566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes } 850566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes 851566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes UErrorCode status = U_ZERO_ERROR; 852317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 853317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller // Tell ICU to use our memory-mapped data. 854566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes udata_setCommonData(data, &status); 8559f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes MAYBE_FAIL_WITH_ICU_ERROR("udata_setCommonData"); 856317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 857317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller return TRUE; 858317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller} 859317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 860317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fullervoid register_libcore_icu_ICU(JNIEnv* env) { 861317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller // Check the timezone override file exists. If it does, map it first so we use it in preference 862317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller // to the one that shipped with the device. 863317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller const char* dataPathPrefix = getenv("ANDROID_DATA"); 864317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller if (dataPathPrefix == NULL) { 865317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller ALOGE("ANDROID_DATA environment variable not set"); \ 866317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller abort(); 867317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller } 868317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 869317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller UErrorCode status = U_ZERO_ERROR; 870566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes // Tell ICU it can *only* use our memory-mapped data. 871566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes udata_setFileAccess(UDATA_NO_FILES, &status); 872317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller if (status != U_ZERO_ERROR) { 873317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller ALOGE("Couldn't initialize ICU (s_setFileAccess): %s", u_errorName(status)); 874317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller abort(); 875317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller } 876317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 877317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller // Map in optional TZ data files. 878317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller std::string dataPath; 879317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller dataPath = dataPathPrefix; 880317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller dataPath += "/misc/zoneinfo/current/icu/icu_tzdata.dat"; 881317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 882317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller struct stat sb; 883317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller if (stat(dataPath.c_str(), &sb) == 0) { 884317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller ALOGD("Timezone override file found: %s", dataPath.c_str()); 885317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller if (!mapIcuData(dataPath)) { 886317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller ALOGW("TZ override file %s exists but could not be loaded. Skipping.", dataPath.c_str()); 887317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller } 888317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller } else { 889317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller ALOGD("No timezone override file found: %s", dataPath.c_str()); 890317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller } 891317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 892317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller // Use the ICU data files that shipped with the device for everything else. 893d2a3075106f700f229750c228de989b789b7dacdNeil Fuller const char* systemPathPrefix = getenv("ANDROID_ROOT"); 894d2a3075106f700f229750c228de989b789b7dacdNeil Fuller if (systemPathPrefix == NULL) { 895d2a3075106f700f229750c228de989b789b7dacdNeil Fuller ALOGE("ANDROID_ROOT environment variable not set"); \ 896d2a3075106f700f229750c228de989b789b7dacdNeil Fuller abort(); 897d2a3075106f700f229750c228de989b789b7dacdNeil Fuller } 898317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller std::string systemPath; 899d2a3075106f700f229750c228de989b789b7dacdNeil Fuller systemPath = systemPathPrefix; 900d2a3075106f700f229750c228de989b789b7dacdNeil Fuller systemPath += "/usr/icu/"; 901317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller systemPath += U_ICUDATA_NAME; 902317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller systemPath += ".dat"; 903317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 904317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller if (!mapIcuData(systemPath)) { 905317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller abort(); 906317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller } 907566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes 908972d9be2dbbf6d467728b8ad44625f6574068bf8Elliott Hughes // Failures to find the ICU data tend to be somewhat obscure because ICU loads its data on first 909972d9be2dbbf6d467728b8ad44625f6574068bf8Elliott Hughes // use, which can be anywhere. Force initialization up front so we can report a nice clear error 910972d9be2dbbf6d467728b8ad44625f6574068bf8Elliott Hughes // and bail. 911972d9be2dbbf6d467728b8ad44625f6574068bf8Elliott Hughes u_init(&status); 912317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller if (status != U_ZERO_ERROR) {\ 913317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller ALOGE("Couldn't initialize ICU (u_init): %s", u_errorName(status)); 914317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller abort(); 915317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller } 916317d6e12782e069e4fde06ed0f9a976a7c49f580Neil Fuller 9177cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes jniRegisterNativeMethods(env, "libcore/icu/ICU", gMethods, NELEM(gMethods)); 918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 919