libcore_icu_ICU.cpp revision bef9ec33e1368f57c731fce63b6a8c61628c64b0
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 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "JNIHelp.h" 20a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes#include "JniConstants.h" 21bef9ec33e1368f57c731fce63b6a8c61628c64b0Elliott Hughes#include "JniException.h" 22566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include "ScopedFd.h" 234e3714f7fe8ac7f6b20896038e491d378f4e6464Elliott Hughes#include "ScopedJavaUnicodeString.h" 24f281667712baf8e0721ceb2cc60e7eef19c2d859Elliott Hughes#include "ScopedLocalRef.h" 2552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes#include "ScopedStringChars.h" 269de899cc3ffd3aa3f8f827201cbe14120609018bElliott Hughes#include "ScopedUtfChars.h" 27757a7942eed2b0aa457f8517a0259d2ac82c5b18Elliott Hughes#include "UniquePtr.h" 28f2d5062b67e57ef00ee81fec67480f0d58d66b50Elliott Hughes#include "cutils/log.h" 29ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes#include "toStringArray.h" 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "unicode/calendar.h" 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "unicode/datefmt.h" 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "unicode/dcfmtsym.h" 3394782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/decimfmt.h" 3494782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/dtfmtsym.h" 3594782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/gregocal.h" 3694782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/locid.h" 3794782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/numfmt.h" 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "unicode/strenum.h" 3994782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/ubrk.h" 4094782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/ucal.h" 4194782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/uclean.h" 4294782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/ucol.h" 4394782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/ucurr.h" 4494782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/udat.h" 4594782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "unicode/ustring.h" 46947eeb80f985827209c9500851e288504d58ec2eclaireho#include "ureslocs.h" 4794782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes#include "valueOf.h" 48ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes 49566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <errno.h> 50566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <fcntl.h> 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdlib.h> 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <string.h> 53ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes#include <string> 54566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <sys/mman.h> 55566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <sys/stat.h> 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <sys/time.h> 57566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <sys/types.h> 58566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <time.h> 59566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes#include <unistd.h> 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6170fa193185427473999f1cda823c1ec408acd2baElliott Hughesclass ScopedResourceBundle { 6270fa193185427473999f1cda823c1ec408acd2baElliott Hughespublic: 6370fa193185427473999f1cda823c1ec408acd2baElliott Hughes ScopedResourceBundle(UResourceBundle* bundle) : mBundle(bundle) { 6470fa193185427473999f1cda823c1ec408acd2baElliott Hughes } 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6670fa193185427473999f1cda823c1ec408acd2baElliott Hughes ~ScopedResourceBundle() { 6770fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (mBundle != NULL) { 6870fa193185427473999f1cda823c1ec408acd2baElliott Hughes ures_close(mBundle); 6970fa193185427473999f1cda823c1ec408acd2baElliott Hughes } 7070fa193185427473999f1cda823c1ec408acd2baElliott Hughes } 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7270fa193185427473999f1cda823c1ec408acd2baElliott Hughes UResourceBundle* get() { 7370fa193185427473999f1cda823c1ec408acd2baElliott Hughes return mBundle; 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 7570fa193185427473999f1cda823c1ec408acd2baElliott Hughes 7670fa193185427473999f1cda823c1ec408acd2baElliott Hughesprivate: 7770fa193185427473999f1cda823c1ec408acd2baElliott Hughes UResourceBundle* mBundle; 787ca6fd0dca02f7abdd8808db78357743bbdd23a5Elliott Hughes 797ca6fd0dca02f7abdd8808db78357743bbdd23a5Elliott Hughes // Disallow copy and assignment. 807ca6fd0dca02f7abdd8808db78357743bbdd23a5Elliott Hughes ScopedResourceBundle(const ScopedResourceBundle&); 817ca6fd0dca02f7abdd8808db78357743bbdd23a5Elliott Hughes void operator=(const ScopedResourceBundle&); 8270fa193185427473999f1cda823c1ec408acd2baElliott Hughes}; 8370fa193185427473999f1cda823c1ec408acd2baElliott Hughes 8421557bb6a8f35a2f9889adba449cac950c9d41b9Elliott HughesLocale getLocale(JNIEnv* env, jstring localeName) { 850808cae1a2616ba9c708c7cc4489723b4060178eElliott Hughes return Locale::createFromName(ScopedUtfChars(env, localeName).c_str()); 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8852b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughesstatic jint ICU_getCurrencyFractionDigits(JNIEnv* env, jclass, jstring javaCurrencyCode) { 894e3714f7fe8ac7f6b20896038e491d378f4e6464Elliott Hughes ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode); 9052b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes UnicodeString icuCurrencyCode(currencyCode.unicodeString()); 9152b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes UErrorCode status = U_ZERO_ERROR; 9252b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes return ucurr_getDefaultFractionDigits(icuCurrencyCode.getTerminatedBuffer(), &status); 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughesstatic jstring ICU_getCurrencyCode(JNIEnv* env, jclass, jstring javaCountryCode) { 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project UErrorCode status = U_ZERO_ERROR; 97947eeb80f985827209c9500851e288504d58ec2eclaireho ScopedResourceBundle supplData(ures_openDirect(U_ICUDATA_CURR, "supplementalData", &status)); 9870fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 10270fa193185427473999f1cda823c1ec408acd2baElliott Hughes ScopedResourceBundle currencyMap(ures_getByKey(supplData.get(), "CurrencyMap", NULL, &status)); 10370fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 10752b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes ScopedUtfChars countryCode(env, javaCountryCode); 10852b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes ScopedResourceBundle currency(ures_getByKey(currencyMap.get(), countryCode.c_str(), NULL, &status)); 10970fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 11370fa193185427473999f1cda823c1ec408acd2baElliott Hughes ScopedResourceBundle currencyElem(ures_getByIndex(currency.get(), 0, NULL, &status)); 11470fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return env->NewStringUTF("None"); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 11852b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes // Check if there's a 'to' date. If there is, the currency isn't used anymore. 11967081ff5bcb8a2b3f7db2940f6e0cb3e459ab4b4Elliott Hughes ScopedResourceBundle currencyTo(ures_getByKey(currencyElem.get(), "to", NULL, &status)); 12067081ff5bcb8a2b3f7db2940f6e0cb3e459ab4b4Elliott Hughes if (!U_FAILURE(status)) { 12167081ff5bcb8a2b3f7db2940f6e0cb3e459ab4b4Elliott Hughes return NULL; 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 12352b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes // Ignore the failure to find a 'to' date. 12467081ff5bcb8a2b3f7db2940f6e0cb3e459ab4b4Elliott Hughes status = U_ZERO_ERROR; 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 12670fa193185427473999f1cda823c1ec408acd2baElliott Hughes ScopedResourceBundle currencyId(ures_getByKey(currencyElem.get(), "id", NULL, &status)); 12770fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // No id defined for this country 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return env->NewStringUTF("None"); 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 13252b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes int32_t charCount; 13352b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes const jchar* chars = ures_getString(currencyId.get(), &charCount, &status); 13452b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes return (charCount == 0) ? env->NewStringUTF("None") : env->NewString(chars, charCount); 13552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes} 13652b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes 13752b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughesstatic jstring ICU_getCurrencyDisplayName(JNIEnv* env, jclass, jstring javaLocaleName, jstring javaCurrencyCode) { 13852b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes ScopedUtfChars localeName(env, javaLocaleName); 13952b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode); 14052b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes UnicodeString icuCurrencyCode(currencyCode.unicodeString()); 14152b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes UErrorCode status = U_ZERO_ERROR; 14252b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes UBool isChoiceFormat; 14352b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes int32_t charCount; 14452b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes const UChar* chars = ucurr_getName(icuCurrencyCode.getTerminatedBuffer(), localeName.c_str(), 14552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes UCURR_LONG_NAME, &isChoiceFormat, &charCount, &status); 14652b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes if (status == U_USING_DEFAULT_WARNING) { 14752b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes // ICU's default is English. We want the ISO 4217 currency code instead. 14852b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes chars = icuCurrencyCode.getBuffer(); 14952b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes charCount = icuCurrencyCode.length(); 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 15152b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes return (charCount == 0) ? NULL : env->NewString(chars, charCount); 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 15452b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughesstatic jstring ICU_getCurrencySymbol(JNIEnv* env, jclass, jstring locale, jstring currencyCode) { 15552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes // We can't use ucurr_getName because it doesn't distinguish between using data root from 15652b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes // the root locale and parroting back the input because it's never heard of the currency code. 15705960876dff6a5b686821eed8f7ae7cef5af4f50Elliott Hughes ScopedUtfChars localeName(env, locale); 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project UErrorCode status = U_ZERO_ERROR; 159947eeb80f985827209c9500851e288504d58ec2eclaireho ScopedResourceBundle currLoc(ures_open(U_ICUDATA_CURR, localeName.c_str(), &status)); 16070fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 164947eeb80f985827209c9500851e288504d58ec2eclaireho ScopedResourceBundle currencies(ures_getByKey(currLoc.get(), "Currencies", NULL, &status)); 16570fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 16905960876dff6a5b686821eed8f7ae7cef5af4f50Elliott Hughes ScopedUtfChars currency(env, currencyCode); 17005960876dff6a5b686821eed8f7ae7cef5af4f50Elliott Hughes ScopedResourceBundle currencyElems(ures_getByKey(currencies.get(), currency.c_str(), NULL, &status)); 17170fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes int32_t charCount; 17652b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes const jchar* chars = ures_getStringByIndex(currencyElems.get(), 0, &charCount, &status); 17770fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 18052b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes return (charCount == 0) ? NULL : env->NewString(chars, charCount); 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 183e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jstring ICU_getDisplayCountryNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) { 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Locale loc = getLocale(env, locale); 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Locale targetLoc = getLocale(env, targetLocale); 18670fa193185427473999f1cda823c1ec408acd2baElliott Hughes UnicodeString str; 18770fa193185427473999f1cda823c1ec408acd2baElliott Hughes targetLoc.getDisplayCountry(loc, str); 18870fa193185427473999f1cda823c1ec408acd2baElliott Hughes return env->NewString(str.getBuffer(), str.length()); 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 191e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jstring ICU_getDisplayLanguageNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) { 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Locale loc = getLocale(env, locale); 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Locale targetLoc = getLocale(env, targetLocale); 19470fa193185427473999f1cda823c1ec408acd2baElliott Hughes UnicodeString str; 19570fa193185427473999f1cda823c1ec408acd2baElliott Hughes targetLoc.getDisplayLanguage(loc, str); 19670fa193185427473999f1cda823c1ec408acd2baElliott Hughes return env->NewString(str.getBuffer(), str.length()); 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 199e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jstring ICU_getDisplayVariantNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) { 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Locale loc = getLocale(env, locale); 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Locale targetLoc = getLocale(env, targetLocale); 20270fa193185427473999f1cda823c1ec408acd2baElliott Hughes UnicodeString str; 20370fa193185427473999f1cda823c1ec408acd2baElliott Hughes targetLoc.getDisplayVariant(loc, str); 20470fa193185427473999f1cda823c1ec408acd2baElliott Hughes return env->NewString(str.getBuffer(), str.length()); 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 207e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jstring ICU_getISO3CountryNative(JNIEnv* env, jclass, jstring locale) { 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Locale loc = getLocale(env, locale); 2092e3a41defb42a97b463194d859d2d4088a600fd8Elliott Hughes return env->NewStringUTF(loc.getISO3Country()); 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 212e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jstring ICU_getISO3LanguageNative(JNIEnv* env, jclass, jstring locale) { 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Locale loc = getLocale(env, locale); 2142e3a41defb42a97b463194d859d2d4088a600fd8Elliott Hughes return env->NewStringUTF(loc.getISO3Language()); 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 217e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getISOCountriesNative(JNIEnv* env, jclass) { 2182e3a41defb42a97b463194d859d2d4088a600fd8Elliott Hughes return toStringArray(env, Locale::getISOCountries()); 2192e3a41defb42a97b463194d859d2d4088a600fd8Elliott Hughes} 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 221e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getISOLanguagesNative(JNIEnv* env, jclass) { 2222e3a41defb42a97b463194d859d2d4088a600fd8Elliott Hughes return toStringArray(env, Locale::getISOLanguages()); 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 225e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableLocalesNative(JNIEnv* env, jclass) { 226ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, uloc_countAvailable, uloc_getAvailable); 227f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 228f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 229e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableBreakIteratorLocalesNative(JNIEnv* env, jclass) { 230ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, ubrk_countAvailable, ubrk_getAvailable); 231f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 232f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 233e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableCalendarLocalesNative(JNIEnv* env, jclass) { 234ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, ucal_countAvailable, ucal_getAvailable); 235f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 236f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 237e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableCollatorLocalesNative(JNIEnv* env, jclass) { 238ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, ucol_countAvailable, ucol_getAvailable); 239f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 240f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 241e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableDateFormatLocalesNative(JNIEnv* env, jclass) { 242ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, udat_countAvailable, udat_getAvailable); 243f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 244f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 245e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jobjectArray ICU_getAvailableNumberFormatLocalesNative(JNIEnv* env, jclass) { 246ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, unum_countAvailable, unum_getAvailable); 247f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes} 248f9157eaea53923d3dbe6a521b29427819052f176Elliott Hughes 24944e0e560c92338110953ce806df475fedcdf926eBrian Carlstromstatic bool getDayIntVector(JNIEnv*, UResourceBundle* gregorian, int* values) { 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // get the First day of week and the minimal days in first week numbers 2512e3a41defb42a97b463194d859d2d4088a600fd8Elliott Hughes UErrorCode status = U_ZERO_ERROR; 25270fa193185427473999f1cda823c1ec408acd2baElliott Hughes ScopedResourceBundle gregorianElems(ures_getByKey(gregorian, "DateTimeElements", NULL, &status)); 2532e3a41defb42a97b463194d859d2d4088a600fd8Elliott Hughes if (U_FAILURE(status)) { 25433aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return false; 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int intVectSize; 25870fa193185427473999f1cda823c1ec408acd2baElliott Hughes const int* result = ures_getIntVector(gregorianElems.get(), &intVectSize, &status); 25970fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status) || intVectSize != 2) { 26033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return false; 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 26233aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes 26370fa193185427473999f1cda823c1ec408acd2baElliott Hughes values[0] = result[0]; 26470fa193185427473999f1cda823c1ec408acd2baElliott Hughes values[1] = result[1]; 26533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return true; 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 268ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes// This allows you to leave extra space at the beginning or end of the array to support the 269ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes// month names and day names arrays. 270ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughesstatic jobjectArray toStringArray(JNIEnv* env, UResourceBundle* rb, size_t size, int capacity, size_t offset) { 271ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes if (capacity == -1) { 272ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes capacity = size; 273ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes } 274ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes jobjectArray result = env->NewObjectArray(capacity, JniConstants::stringClass, NULL); 275ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes if (result == NULL) { 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 278ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes UErrorCode status = U_ZERO_ERROR; 279ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes for (size_t i = 0; i < size; ++i) { 280ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes int charCount; 281ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes const jchar* chars = ures_getStringByIndex(rb, i, &charCount, &status); 282ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes if (U_FAILURE(status)) { 283ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return NULL; 284ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes } 285ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes ScopedLocalRef<jstring> s(env, env->NewString(chars, charCount)); 286ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes if (env->ExceptionCheck()) { 287ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return NULL; 288ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes } 289ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes env->SetObjectArrayElement(result, offset + i, s.get()); 290ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes if (env->ExceptionCheck()) { 291ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return NULL; 292ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes } 293ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes } 294ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return result; 295ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes} 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 297ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughesstatic jobjectArray getAmPmMarkers(JNIEnv* env, UResourceBundle* gregorian) { 298ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes UErrorCode status = U_ZERO_ERROR; 299ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes ScopedResourceBundle amPmMarkers(ures_getByKey(gregorian, "AmPmMarkers", NULL, &status)); 3002e3a41defb42a97b463194d859d2d4088a600fd8Elliott Hughes if (U_FAILURE(status)) { 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 303ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, amPmMarkers.get(), ures_getSize(amPmMarkers.get()), -1, 0); 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 30670fa193185427473999f1cda823c1ec408acd2baElliott Hughesstatic jobjectArray getEras(JNIEnv* env, UResourceBundle* gregorian) { 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project UErrorCode status = U_ZERO_ERROR; 308ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes ScopedResourceBundle eras(ures_getByKey(gregorian, "eras", NULL, &status)); 30970fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 312ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes ScopedResourceBundle abbreviatedEras(ures_getByKey(eras.get(), "abbreviated", NULL, &status)); 31370fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 316ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes return toStringArray(env, abbreviatedEras.get(), ures_getSize(abbreviatedEras.get()), -1, 0); 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 319143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughesenum NameType { REGULAR, STAND_ALONE }; 320143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughesenum NameWidth { LONG, SHORT }; 321143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughesstatic jobjectArray getNames(JNIEnv* env, UResourceBundle* namesBundle, bool months, NameType type, NameWidth width) { 322143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes const char* typeKey = (type == REGULAR) ? "format" : "stand-alone"; 323143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes const char* widthKey = (width == LONG) ? "wide" : "abbreviated"; 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project UErrorCode status = U_ZERO_ERROR; 325143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes ScopedResourceBundle formatBundle(ures_getByKey(namesBundle, typeKey, NULL, &status)); 326143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes ScopedResourceBundle valuesBundle(ures_getByKey(formatBundle.get(), widthKey, NULL, &status)); 32770fa193185427473999f1cda823c1ec408acd2baElliott Hughes if (U_FAILURE(status)) { 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 3308044bf6b446c93cd29c5753544246316f269064fElliott Hughes 331143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes // The months array has a trailing empty string. The days array has a leading empty string. 332143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes int count = ures_getSize(valuesBundle.get()); 333ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes int offset = months ? 0 : 1; 334ddafeb1d73cfe504720d10a2634b5858fc4cc413Elliott Hughes jobjectArray result = toStringArray(env, valuesBundle.get(), count, count + 1, offset); 335143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes env->SetObjectArrayElement(result, months ? count : 0, env->NewStringUTF("")); 336143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes return result; 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 33933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughesstatic void setIntegerField(JNIEnv* env, jobject obj, const char* fieldName, int value) { 34094782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes ScopedLocalRef<jobject> integerValue(env, integerValueOf(env, value)); 341a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes jfieldID fid = env->GetFieldID(JniConstants::localeDataClass, fieldName, "Ljava/lang/Integer;"); 34294782d07dd2d65b1a37fddca68eb9a9ac81ada4aElliott Hughes env->SetObjectField(obj, fid, integerValue.get()); 34333aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes} 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 34533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughesstatic void setStringField(JNIEnv* env, jobject obj, const char* fieldName, jstring value) { 346a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes jfieldID fid = env->GetFieldID(JniConstants::localeDataClass, fieldName, "Ljava/lang/String;"); 34733aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes env->SetObjectField(obj, fid, value); 34833aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes} 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 35033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughesstatic void setStringArrayField(JNIEnv* env, jobject obj, const char* fieldName, jobjectArray value) { 351a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes jfieldID fid = env->GetFieldID(JniConstants::localeDataClass, fieldName, "[Ljava/lang/String;"); 35233aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes env->SetObjectField(obj, fid, value); 35333aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes} 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 35533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughesstatic void setStringField(JNIEnv* env, jobject obj, const char* fieldName, UResourceBundle* bundle, int index) { 35633aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes UErrorCode status = U_ZERO_ERROR; 35733aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes int charCount; 35833aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes const UChar* chars = ures_getStringByIndex(bundle, index, &charCount, &status); 35933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (U_SUCCESS(status)) { 36033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringField(env, obj, fieldName, env->NewString(chars, charCount)); 36190aa512eb7b126deb8d752b7474c30d3f73507b2Elliott Hughes } else { 362b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes LOGE("Error setting String field %s from ICU resource: %s", fieldName, u_errorName(status)); 363b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes } 364b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes} 365b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes 366b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughesstatic void setCharField(JNIEnv* env, jobject obj, const char* fieldName, UResourceBundle* bundle, int index) { 367b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes UErrorCode status = U_ZERO_ERROR; 368b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes int charCount; 369b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes const UChar* chars = ures_getStringByIndex(bundle, index, &charCount, &status); 370b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes if (U_SUCCESS(status)) { 371a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes jfieldID fid = env->GetFieldID(JniConstants::localeDataClass, fieldName, "C"); 372b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes env->SetCharField(obj, fid, chars[0]); 373b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes } else { 374b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes LOGE("Error setting char field %s from ICU resource: %s", fieldName, u_errorName(status)); 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 37633aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes} 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 378e22935d3c7040c22b48d53bd18878844f381287cElliott Hughesstatic jboolean ICU_initLocaleDataImpl(JNIEnv* env, jclass, jstring locale, jobject localeData) { 37905960876dff6a5b686821eed8f7ae7cef5af4f50Elliott Hughes ScopedUtfChars localeName(env, locale); 38033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes UErrorCode status = U_ZERO_ERROR; 38121557bb6a8f35a2f9889adba449cac950c9d41b9Elliott Hughes ScopedResourceBundle root(ures_open(NULL, localeName.c_str(), &status)); 38233aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (U_FAILURE(status)) { 38333aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes LOGE("Error getting ICU resource bundle: %s", u_errorName(status)); 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = U_ZERO_ERROR; 38533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return JNI_FALSE; 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 38833aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status)); 38933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (U_FAILURE(status)) { 3904722f161d49b5c483aa7aec0daad7bfee18578bbElliott Hughes LOGE("Error getting ICU calendar resource bundle: %s", u_errorName(status)); 39133aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return JNI_FALSE; 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 39433aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status)); 39533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (U_FAILURE(status)) { 3964722f161d49b5c483aa7aec0daad7bfee18578bbElliott Hughes LOGE("Error getting ICU gregorian resource bundle: %s", u_errorName(status)); 39733aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return JNI_FALSE; 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 400e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes int firstDayVals[] = { 0, 0 }; 40133aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (getDayIntVector(env, gregorian.get(), firstDayVals)) { 40233aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setIntegerField(env, localeData, "firstDayOfWeek", firstDayVals[0]); 40333aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setIntegerField(env, localeData, "minimalDaysInFirstWeek", firstDayVals[1]); 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 40633aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringArrayField(env, localeData, "amPm", getAmPmMarkers(env, gregorian.get())); 40733aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringArrayField(env, localeData, "eras", getEras(env, gregorian.get())); 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 409143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes ScopedResourceBundle dayNames(ures_getByKey(gregorian.get(), "dayNames", NULL, &status)); 410143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes ScopedResourceBundle monthNames(ures_getByKey(gregorian.get(), "monthNames", NULL, &status)); 411143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes 412143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes // Get the regular month and weekday names. 413143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes jobjectArray longMonthNames = getNames(env, monthNames.get(), true, REGULAR, LONG); 414143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes jobjectArray shortMonthNames = getNames(env, monthNames.get(), true, REGULAR, SHORT); 415143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes jobjectArray longWeekdayNames = getNames(env, dayNames.get(), false, REGULAR, LONG); 416143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes jobjectArray shortWeekdayNames = getNames(env, dayNames.get(), false, REGULAR, SHORT); 417143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringArrayField(env, localeData, "longMonthNames", longMonthNames); 418143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringArrayField(env, localeData, "shortMonthNames", shortMonthNames); 419143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringArrayField(env, localeData, "longWeekdayNames", longWeekdayNames); 420143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringArrayField(env, localeData, "shortWeekdayNames", shortWeekdayNames); 421143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes 422143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes // Get the stand-alone month and weekday names. If they're not available (as they aren't for 423143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes // English), we reuse the regular names. If we returned null to Java, the usual fallback 424143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes // mechanisms would come into play and we'd end up with the bogus stand-alone names from the 425143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes // root locale ("1" for January, and so on). 426143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes jobjectArray longStandAloneMonthNames = getNames(env, monthNames.get(), true, STAND_ALONE, LONG); 427143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes if (longStandAloneMonthNames == NULL) { 428143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes longStandAloneMonthNames = longMonthNames; 429143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes } 430143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes jobjectArray shortStandAloneMonthNames = getNames(env, monthNames.get(), true, STAND_ALONE, SHORT); 431143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes if (shortStandAloneMonthNames == NULL) { 432143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes shortStandAloneMonthNames = shortMonthNames; 433143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes } 434143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes jobjectArray longStandAloneWeekdayNames = getNames(env, dayNames.get(), false, STAND_ALONE, LONG); 435143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes if (longStandAloneWeekdayNames == NULL) { 436143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes longStandAloneWeekdayNames = longWeekdayNames; 437143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes } 438143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes jobjectArray shortStandAloneWeekdayNames = getNames(env, dayNames.get(), false, STAND_ALONE, SHORT); 439143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes if (shortStandAloneWeekdayNames == NULL) { 440143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes shortStandAloneWeekdayNames = shortWeekdayNames; 441143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes } 442143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringArrayField(env, localeData, "longStandAloneMonthNames", longStandAloneMonthNames); 443143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringArrayField(env, localeData, "shortStandAloneMonthNames", shortStandAloneMonthNames); 444143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringArrayField(env, localeData, "longStandAloneWeekdayNames", longStandAloneWeekdayNames); 445143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringArrayField(env, localeData, "shortStandAloneWeekdayNames", shortStandAloneWeekdayNames); 446143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes 447143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes ScopedResourceBundle dateTimePatterns(ures_getByKey(gregorian.get(), "DateTimePatterns", NULL, &status)); 44833aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (U_SUCCESS(status)) { 449143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringField(env, localeData, "fullTimeFormat", dateTimePatterns.get(), 0); 450143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringField(env, localeData, "longTimeFormat", dateTimePatterns.get(), 1); 451143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringField(env, localeData, "mediumTimeFormat", dateTimePatterns.get(), 2); 452143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringField(env, localeData, "shortTimeFormat", dateTimePatterns.get(), 3); 453143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringField(env, localeData, "fullDateFormat", dateTimePatterns.get(), 4); 454143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringField(env, localeData, "longDateFormat", dateTimePatterns.get(), 5); 455143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringField(env, localeData, "mediumDateFormat", dateTimePatterns.get(), 6); 456143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes setStringField(env, localeData, "shortDateFormat", dateTimePatterns.get(), 7); 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 45833aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes status = U_ZERO_ERROR; 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 46033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes ScopedResourceBundle numberElements(ures_getByKey(root.get(), "NumberElements", NULL, &status)); 46133aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (U_SUCCESS(status) && ures_getSize(numberElements.get()) >= 11) { 462b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes setCharField(env, localeData, "zeroDigit", numberElements.get(), 4); 463b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes setCharField(env, localeData, "digit", numberElements.get(), 5); 464b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes setCharField(env, localeData, "decimalSeparator", numberElements.get(), 0); 465b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes setCharField(env, localeData, "groupingSeparator", numberElements.get(), 1); 466b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes setCharField(env, localeData, "patternSeparator", numberElements.get(), 2); 467b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes setCharField(env, localeData, "percent", numberElements.get(), 3); 468b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes setCharField(env, localeData, "perMill", numberElements.get(), 8); 469b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes setCharField(env, localeData, "monetarySeparator", numberElements.get(), 0); 470b7e820b92c7345cdc0cd4fea50954289ae66eb67Elliott Hughes setCharField(env, localeData, "minusSign", numberElements.get(), 6); 47190aa512eb7b126deb8d752b7474c30d3f73507b2Elliott Hughes setStringField(env, localeData, "exponentSeparator", numberElements.get(), 7); 47233aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringField(env, localeData, "infinity", numberElements.get(), 9); 47333aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringField(env, localeData, "NaN", numberElements.get(), 10); 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 47533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes status = U_ZERO_ERROR; 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 4777ff7010c01a090dcbf992c7223fbc8fde54b3018Elliott Hughes jstring countryCode = env->NewStringUTF(Locale::createFromName(localeName.c_str()).getCountry()); 47852b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes jstring internationalCurrencySymbol = ICU_getCurrencyCode(env, NULL, countryCode); 47933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes jstring currencySymbol = NULL; 48033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (internationalCurrencySymbol != NULL) { 48152b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes currencySymbol = ICU_getCurrencySymbol(env, NULL, locale, internationalCurrencySymbol); 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 48333aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes internationalCurrencySymbol = env->NewStringUTF("XXX"); 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 48533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (currencySymbol == NULL) { 48633aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes // This is the UTF-8 encoding of U+00A4 (CURRENCY SIGN). 487ad884a7b8cae7a1c3d973c8032d4f78ef7c96b80Hao Feng currencySymbol = env->NewStringUTF("\xc2\xa4"); 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 48933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringField(env, localeData, "currencySymbol", currencySymbol); 49033aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringField(env, localeData, "internationalCurrencySymbol", internationalCurrencySymbol); 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 49233aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes ScopedResourceBundle numberPatterns(ures_getByKey(root.get(), "NumberPatterns", NULL, &status)); 49333aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes if (U_SUCCESS(status) && ures_getSize(numberPatterns.get()) >= 3) { 49433aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringField(env, localeData, "numberPattern", numberPatterns.get(), 0); 49533aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringField(env, localeData, "currencyPattern", numberPatterns.get(), 1); 49633aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes setStringField(env, localeData, "percentPattern", numberPatterns.get(), 2); 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 49933aa6eb602478e7f51ac16f30c88db3566022886Elliott Hughes return JNI_TRUE; 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 502dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughesstatic jstring ICU_toLowerCase(JNIEnv* env, jclass, jstring javaString, jstring localeName) { 503dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes ScopedJavaUnicodeString scopedString(env, javaString); 504dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes UnicodeString& s(scopedString.unicodeString()); 505dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes UnicodeString original(s); 506dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes s.toLower(Locale::createFromName(ScopedUtfChars(env, localeName).c_str())); 507dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes return s == original ? javaString : env->NewString(s.getBuffer(), s.length()); 508dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes} 509dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes 510dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughesstatic jstring ICU_toUpperCase(JNIEnv* env, jclass, jstring javaString, jstring localeName) { 511dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes ScopedJavaUnicodeString scopedString(env, javaString); 512dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes UnicodeString& s(scopedString.unicodeString()); 513dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes UnicodeString original(s); 514dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes s.toUpper(Locale::createFromName(ScopedUtfChars(env, localeName).c_str())); 515dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes return s == original ? javaString : env->NewString(s.getBuffer(), s.length()); 516dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes} 517dbbdffce5ac97a0e93ef495adaacca3660b9ab21Elliott Hughes 518e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughesstatic jstring versionString(JNIEnv* env, const UVersionInfo& version) { 519e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes char versionString[U_MAX_VERSION_STRING_LENGTH]; 520e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes u_versionToString(const_cast<UVersionInfo&>(version), &versionString[0]); 521e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes return env->NewStringUTF(versionString); 522e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes} 523e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes 524e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughesstatic jstring ICU_getIcuVersion(JNIEnv* env, jclass) { 525e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes UVersionInfo icuVersion; 526e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes u_getVersion(icuVersion); 527e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes return versionString(env, icuVersion); 528e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes} 529e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes 530e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughesstatic jstring ICU_getUnicodeVersion(JNIEnv* env, jclass) { 531e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes UVersionInfo unicodeVersion; 532e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes u_getUnicodeVersion(unicodeVersion); 533e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes return versionString(env, unicodeVersion); 534e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes} 535e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes 53652b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes 53752b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughesstruct EnumerationCounter { 53852b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes const size_t count; 53952b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes EnumerationCounter(size_t count) : count(count) {} 54052b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes size_t operator()() { return count; } 54152b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes}; 54252b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughesstruct EnumerationGetter { 54352b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes UEnumeration* e; 54452b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes UErrorCode* status; 54552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes EnumerationGetter(UEnumeration* e, UErrorCode* status) : e(e), status(status) {} 54652b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes const UChar* operator()(int32_t* charCount) { return uenum_unext(e, charCount, status); } 54752b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes}; 54852b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughesstatic jobject ICU_getAvailableCurrencyCodes(JNIEnv* env, jclass) { 54952b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes UErrorCode status = U_ZERO_ERROR; 55052b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes UEnumeration* e(ucurr_openISOCurrencies(UCURR_COMMON|UCURR_NON_DEPRECATED, &status)); 55152b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes EnumerationCounter counter(uenum_count(e, &status)); 55252b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes EnumerationGetter getter(e, &status); 55352b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes jobject result = toStringArray16(env, &counter, &getter); 554bef9ec33e1368f57c731fce63b6a8c61628c64b0Elliott Hughes maybeThrowIcuException(env, status); 55552b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes uenum_close(e); 55652b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes return result; 55752b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes} 55852b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic JNINativeMethod gMethods[] = { 560e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableBreakIteratorLocalesNative, "()[Ljava/lang/String;"), 561e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableCalendarLocalesNative, "()[Ljava/lang/String;"), 562e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableCollatorLocalesNative, "()[Ljava/lang/String;"), 56352b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes NATIVE_METHOD(ICU, getAvailableCurrencyCodes, "()[Ljava/lang/String;"), 564e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableDateFormatLocalesNative, "()[Ljava/lang/String;"), 565e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableLocalesNative, "()[Ljava/lang/String;"), 566e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getAvailableNumberFormatLocalesNative, "()[Ljava/lang/String;"), 56752b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes NATIVE_METHOD(ICU, getCurrencyCode, "(Ljava/lang/String;)Ljava/lang/String;"), 56852b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes NATIVE_METHOD(ICU, getCurrencyDisplayName, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 56952b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes NATIVE_METHOD(ICU, getCurrencyFractionDigits, "(Ljava/lang/String;)I"), 57052b310afcffe8b6aed6fa0c1e9e8b0ade6f0a672Elliott Hughes NATIVE_METHOD(ICU, getCurrencySymbol, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 571e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getDisplayCountryNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 572e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getDisplayLanguageNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 573e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getDisplayVariantNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 574e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getISO3CountryNative, "(Ljava/lang/String;)Ljava/lang/String;"), 575e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getISO3LanguageNative, "(Ljava/lang/String;)Ljava/lang/String;"), 576e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getISOCountriesNative, "()[Ljava/lang/String;"), 577e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, getISOLanguagesNative, "()[Ljava/lang/String;"), 578e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes NATIVE_METHOD(ICU, getIcuVersion, "()Ljava/lang/String;"), 579e0e567287e4392bebc5f5826b8ef3b1bd8ca166eElliott Hughes NATIVE_METHOD(ICU, getUnicodeVersion, "()Ljava/lang/String;"), 580c27a366a89e470690e99374b15270e7b9169ade1Elliott Hughes NATIVE_METHOD(ICU, initLocaleDataImpl, "(Ljava/lang/String;Llibcore/icu/LocaleData;)Z"), 581e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, toLowerCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 582e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ICU, toUpperCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}; 584c27a366a89e470690e99374b15270e7b9169ade1Elliott Hughesint register_libcore_icu_ICU(JNIEnv* env) { 585566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes std::string path; 586566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes path = u_getDataDirectory(); 587566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes path += "/"; 588566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes path += U_ICUDATA_NAME; 589566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes path += ".dat"; 5909f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes 5919f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes #define FAIL_WITH_STRERROR(s) \ 5929f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes LOGE("Couldn't " s " '%s': %s", path.c_str(), strerror(errno)); \ 5939f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes return -1; 5949f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes #define MAYBE_FAIL_WITH_ICU_ERROR(s) \ 5959f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes if (status != U_ZERO_ERROR) {\ 5969f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes LOGE("Couldn't initialize ICU (" s "): %s (%s)", u_errorName(status), path.c_str()); \ 5979f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes return -1; \ 5989f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes } 599566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes 600566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes // Open the file and get its length. 601566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes ScopedFd fd(open(path.c_str(), O_RDONLY)); 602566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes if (fd.get() == -1) { 6039f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes FAIL_WITH_STRERROR("open"); 604566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes } 605566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes struct stat sb; 606566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes if (fstat(fd.get(), &sb) == -1) { 6079f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes FAIL_WITH_STRERROR("stat"); 608566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes } 609566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes 610566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes // Map it. 611566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes void* data = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd.get(), 0); 612566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes if (data == MAP_FAILED) { 6139f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes FAIL_WITH_STRERROR("mmap"); 614566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes } 615566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes 616566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes // Tell the kernel that accesses are likely to be random rather than sequential. 617566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes if (madvise(data, sb.st_size, MADV_RANDOM) == -1) { 6189f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes FAIL_WITH_STRERROR("madvise(MADV_RANDOM)"); 619566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes } 620566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes 621566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes // Tell ICU to use our memory-mapped data. 622566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes UErrorCode status = U_ZERO_ERROR; 623566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes udata_setCommonData(data, &status); 6249f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes MAYBE_FAIL_WITH_ICU_ERROR("udata_setCommonData"); 625566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes // Tell ICU it can *only* use our memory-mapped data. 626566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes udata_setFileAccess(UDATA_NO_FILES, &status); 6279f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes MAYBE_FAIL_WITH_ICU_ERROR("udata_setFileAccess"); 628566bbb1d5a0ffadfc07fa58176587d4bd0d0be13Elliott Hughes 629972d9be2dbbf6d467728b8ad44625f6574068bf8Elliott Hughes // Failures to find the ICU data tend to be somewhat obscure because ICU loads its data on first 630972d9be2dbbf6d467728b8ad44625f6574068bf8Elliott Hughes // use, which can be anywhere. Force initialization up front so we can report a nice clear error 631972d9be2dbbf6d467728b8ad44625f6574068bf8Elliott Hughes // and bail. 632972d9be2dbbf6d467728b8ad44625f6574068bf8Elliott Hughes u_init(&status); 6339f557fae5a751ba8de8c0bc9ba689ab23ad405f6Elliott Hughes MAYBE_FAIL_WITH_ICU_ERROR("u_init"); 634c27a366a89e470690e99374b15270e7b9169ade1Elliott Hughes return jniRegisterNativeMethods(env, "libcore/icu/ICU", gMethods, NELEM(gMethods)); 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 636