Stop using ResourceBundle for locale data.
This offers an additional speed increase and gets rid of a lot of native code.
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java b/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
index 0ceb287..43ac3f2 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
@@ -17,6 +17,7 @@
package com.ibm.icu4jni.text;
import com.ibm.icu4jni.text.NativeDecimalFormat.UNumberFormatSymbol;
+import com.ibm.icu4jni.util.LocaleData;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -36,18 +37,15 @@
}
public DecimalFormatSymbols(Locale locale) {
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
this.loc = locale;
- ResourceBundle bundle = com.ibm.icu4jni.util.Resources.getLocaleInstance(locale);
- String pattern = bundle.getString("Number");
- this.addr = NativeDecimalFormat.openDecimalFormatImpl(
- locale.toString(), pattern);
- String currSymbol = bundle.getString("CurrencySymbol");
- String intCurrSymbol = bundle.getString("IntCurrencySymbol");
+ this.addr = NativeDecimalFormat.openDecimalFormatImpl(locale.toString(),
+ localeData.numberPattern);
NativeDecimalFormat.setSymbol(this.addr,
- UNumberFormatSymbol.UNUM_CURRENCY_SYMBOL.ordinal(), currSymbol);
+ UNumberFormatSymbol.UNUM_CURRENCY_SYMBOL.ordinal(), localeData.currencySymbol);
NativeDecimalFormat.setSymbol(this.addr,
UNumberFormatSymbol.UNUM_INTL_CURRENCY_SYMBOL.ordinal(),
- intCurrSymbol);
+ localeData.internationalCurrencySymbol);
}
@Override
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/util/LocaleData.java b/libcore/icu/src/main/java/com/ibm/icu4jni/util/LocaleData.java
new file mode 100644
index 0000000..1e91574
--- /dev/null
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/util/LocaleData.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.icu4jni.util;
+
+/**
+ * Passes locale-specific from ICU native code to Java.
+ * <p>
+ * Note that you share these; you must not alter any of the fields, nor their array elements
+ * in the case of arrays. If you ever expose any of these things to user code, you must give
+ * them a clone rather than the original.
+ */
+public class LocaleData {
+ public Integer firstDayOfWeek;
+ public Integer minimalDaysInFirstWeek;
+
+ public String[] amPm;
+
+ public String[] eras;
+
+ public String[] longMonthNames;
+ public String[] shortMonthNames;
+
+ public String[] longWeekdayNames;
+ public String[] shortWeekdayNames;
+
+ public String fullTimeFormat;
+ public String longTimeFormat;
+ public String mediumTimeFormat;
+ public String shortTimeFormat;
+
+ public String fullDateFormat;
+ public String longDateFormat;
+ public String mediumDateFormat;
+ public String shortDateFormat;
+
+ public String decimalPatternChars;
+
+ public String infinity;
+ public String NaN;
+
+ public String currencySymbol;
+ public String internationalCurrencySymbol;
+
+ public String numberPattern;
+ public String integerPattern;
+ public String currencyPattern;
+ public String percentPattern;
+
+ @Override public String toString() {
+ return "LocaleData[" +
+ "firstDayOfWeek=" + firstDayOfWeek + "," +
+ "minimalDaysInFirstWeek=" + minimalDaysInFirstWeek + "," +
+ "amPm=" + amPm + "," +
+ "eras=" + eras + "," +
+ "longMonthNames=" + longMonthNames + "," +
+ "shortMonthNames=" + shortMonthNames + "," +
+ "longWeekdayNames=" + longWeekdayNames + "," +
+ "shortWeekdayNames=" + shortWeekdayNames + "," +
+ "fullTimeFormat=" + fullTimeFormat + "," +
+ "longTimeFormat=" + longTimeFormat + "," +
+ "mediumTimeFormat=" + mediumTimeFormat + "," +
+ "shortTimeFormat=" + shortTimeFormat + "," +
+ "fullDateFormat=" + fullDateFormat + "," +
+ "longDateFormat=" + longDateFormat + "," +
+ "mediumDateFormat=" + mediumDateFormat + "," +
+ "shortDateFormat=" + shortDateFormat + "," +
+ "decimalPatternChars=" + decimalPatternChars + "," +
+ "infinity=" + infinity + "," +
+ "NaN=" + NaN + "," +
+ "currencySymbol=" + currencySymbol + "," +
+ "internationalCurrencySymbol=" + internationalCurrencySymbol + "," +
+ "numberPattern=" + numberPattern + "," +
+ "integerPattern=" + integerPattern + "," +
+ "currencyPattern=" + currencyPattern + "," +
+ "percentPattern=" + percentPattern + "]";
+ }
+
+ public void overrideWithDataFrom(LocaleData overrides) {
+ if (overrides.firstDayOfWeek != null) {
+ firstDayOfWeek = overrides.firstDayOfWeek;
+ }
+ if (overrides.minimalDaysInFirstWeek != null) {
+ minimalDaysInFirstWeek = overrides.minimalDaysInFirstWeek;
+ }
+ if (overrides.amPm != null) {
+ amPm = overrides.amPm;
+ }
+ if (overrides.eras != null) {
+ eras = overrides.eras;
+ }
+ if (overrides.longMonthNames != null) {
+ longMonthNames = overrides.longMonthNames;
+ }
+ if (overrides.shortMonthNames != null) {
+ shortMonthNames = overrides.shortMonthNames;
+ }
+ if (overrides.longWeekdayNames != null) {
+ longWeekdayNames = overrides.longWeekdayNames;
+ }
+ if (overrides.shortWeekdayNames != null) {
+ shortWeekdayNames = overrides.shortWeekdayNames;
+ }
+ if (overrides.fullTimeFormat != null) {
+ fullTimeFormat = overrides.fullTimeFormat;
+ }
+ if (overrides.longTimeFormat != null) {
+ longTimeFormat = overrides.longTimeFormat;
+ }
+ if (overrides.mediumTimeFormat != null) {
+ mediumTimeFormat = overrides.mediumTimeFormat;
+ }
+ if (overrides.shortTimeFormat != null) {
+ shortTimeFormat = overrides.shortTimeFormat;
+ }
+ if (overrides.fullDateFormat != null) {
+ fullDateFormat = overrides.fullDateFormat;
+ }
+ if (overrides.longDateFormat != null) {
+ longDateFormat = overrides.longDateFormat;
+ }
+ if (overrides.mediumDateFormat != null) {
+ mediumDateFormat = overrides.mediumDateFormat;
+ }
+ if (overrides.shortDateFormat != null) {
+ shortDateFormat = overrides.shortDateFormat;
+ }
+ if (overrides.decimalPatternChars != null) {
+ decimalPatternChars = overrides.decimalPatternChars;
+ }
+ if (overrides.NaN != null) {
+ NaN = overrides.NaN;
+ }
+ if (overrides.infinity != null) {
+ infinity = overrides.infinity;
+ }
+ if (overrides.currencySymbol != null) {
+ currencySymbol = overrides.currencySymbol;
+ }
+ if (overrides.internationalCurrencySymbol != null) {
+ internationalCurrencySymbol = overrides.internationalCurrencySymbol;
+ }
+ if (overrides.numberPattern != null) {
+ numberPattern = overrides.numberPattern;
+ }
+ if (overrides.integerPattern != null) {
+ integerPattern = overrides.integerPattern;
+ }
+ if (overrides.currencyPattern != null) {
+ currencyPattern = overrides.currencyPattern;
+ }
+ if (overrides.percentPattern != null) {
+ percentPattern = overrides.percentPattern;
+ }
+ }
+}
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java b/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
index 41bf3e3..8f09029 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
@@ -33,8 +33,8 @@
*/
public class Resources {
// A cache for the locale-specific data.
- private static final ConcurrentHashMap<String, LocaleResourceBundle> localeInstanceCache =
- new ConcurrentHashMap<String, LocaleResourceBundle>();
+ private static final ConcurrentHashMap<String, LocaleData> localeDataCache =
+ new ConcurrentHashMap<String, LocaleData>();
/**
* Cache for ISO language names.
@@ -57,40 +57,37 @@
private static String[] availableTimezones = null;
/**
- * Returns a LocaleResourceBundle corresponding to the given locale.
- * TODO: return something that allows cheap static field lookup rather than
- * expensive chained hash table lookup.
+ * Returns a shared LocaleData for the given locale.
*/
- public static ResourceBundle getLocaleInstance(Locale locale) {
+ public static LocaleData getLocaleData(Locale locale) {
if (locale == null) {
locale = Locale.getDefault();
}
String localeName = locale.toString();
- LocaleResourceBundle bundle = localeInstanceCache.get(localeName);
- if (bundle != null) {
- return bundle;
+ LocaleData localeData = localeDataCache.get(localeName);
+ if (localeData != null) {
+ return localeData;
}
- bundle = makeLocaleResourceBundle(locale);
- localeInstanceCache.put(localeName, bundle);
- boolean absent = (localeInstanceCache.putIfAbsent(localeName, bundle) == null);
- return absent ? bundle : localeInstanceCache.get(localeName);
+ localeData = makeLocaleData(locale);
+ boolean absent = (localeDataCache.putIfAbsent(localeName, localeData) == null);
+ return absent ? localeData : localeDataCache.get(localeName);
}
- private static LocaleResourceBundle makeLocaleResourceBundle(Locale locale) {
- LocaleResourceBundle result = new LocaleResourceBundle(locale);
-
- // Anything not found in this ResourceBundle should be passed on to
- // a parent ResourceBundle corresponding to the next-most-specific locale.
- String country = locale.getCountry();
+ private static LocaleData makeLocaleData(Locale locale) {
String language = locale.getLanguage();
- if (locale.getVariant().length() > 0) {
- result.setParent(getLocaleInstance(new Locale(language, country, "")));
+ String country = locale.getCountry();
+ String variant = locale.getVariant();
+ // Start with data from the parent (next-most-specific) locale...
+ LocaleData result = new LocaleData();
+ if (variant.length() > 0) {
+ result.overrideWithDataFrom(getLocaleData(new Locale(language, country, "")));
} else if (country.length() > 0) {
- result.setParent(getLocaleInstance(new Locale(language, "", "")));
+ result.overrideWithDataFrom(getLocaleData(new Locale(language, "", "")));
} else if (language.length() > 0) {
- result.setParent(getLocaleInstance(new Locale("", "", "")));
+ result.overrideWithDataFrom(getLocaleData(new Locale("", "", "")));
}
-
+ // Override with data from this locale.
+ result.overrideWithDataFrom(initLocaleData(locale));
return result;
}
@@ -270,7 +267,7 @@
return createTimeZoneNamesFor(locale);
}
- private static String[][] clone2dStringArray(String[][] array) {
+ public static String[][] clone2dStringArray(String[][] array) {
String[][] result = new String[array.length][];
for (int i = 0; i < array.length; ++i) {
result[i] = array[i].clone();
@@ -308,48 +305,6 @@
}
- /**
- * Internal ResourceBundle mimicking the Harmony "Locale_*" bundles.
- * The content covers a wide range of
- * data items, with values even being arrays in some cases. Note we are
- * cheating with the "timezones" entry, since we normally don't want to
- * waste our precious RAM on several thousand of these Strings.
- */
- private static final class LocaleResourceBundle extends ListResourceBundle {
- private final Locale locale;
-
- public LocaleResourceBundle(Locale locale) {
- this.locale = locale;
- }
-
- // We can't set the superclass' locale field, so we need our own, and our own accessor.
- @Override
- public Locale getLocale() {
- return locale;
- }
-
- @Override
- protected Object[][] getContents() {
- return getContentImpl(locale.toString());
- }
-
- // Increase accessibility of this method so we can call it.
- @Override
- public void setParent(ResourceBundle bundle) {
- this.parent = bundle;
- }
-
- @Override
- public String toString() {
- StringBuilder result = new StringBuilder();
- result.append("LocaleResourceBundle[locale=");
- result.append(getLocale());
- result.append(",contents=");
- result.append(Arrays.deepToString(getContents()));
- return result.toString();
- }
- }
-
// --- Native methods accessing ICU's database ----------------------------
public static native String getDisplayCountryNative(String countryCode, String locale);
@@ -374,5 +329,25 @@
private static native String getDisplayTimeZoneNative(String id, boolean isDST, int style,
String locale);
- private static native Object[][] getContentImpl(String locale);
+ private static LocaleData initLocaleData(Locale locale) {
+ LocaleData localeData = new LocaleData();
+ if (!initLocaleDataImpl(locale.toString(), localeData)) {
+ throw new AssertionError("couldn't initialize LocaleData for locale " + locale);
+ }
+ if (localeData.fullTimeFormat != null) {
+ // There are some full time format patterns in ICU that use the pattern character 'v'.
+ // Java doesn't accept this, so we replace it with 'z' which has about the same result
+ // as 'v', the timezone name.
+ // 'v' -> "PT", 'z' -> "PST", v is the generic timezone and z the standard tz
+ // "vvvv" -> "Pacific Time", "zzzz" -> "Pacific Standard Time"
+ localeData.fullTimeFormat = localeData.fullTimeFormat.replace('v', 'z');
+ }
+ if (localeData.numberPattern != null) {
+ String numberPattern = localeData.numberPattern;
+ localeData.integerPattern = numberPattern.substring(0, numberPattern.indexOf('.'));
+ }
+ return localeData;
+ }
+
+ private static native boolean initLocaleDataImpl(String locale, LocaleData result);
}
diff --git a/libcore/icu/src/main/native/ResourceInterface.cpp b/libcore/icu/src/main/native/ResourceInterface.cpp
index abb00a0..151b23e 100644
--- a/libcore/icu/src/main/native/ResourceInterface.cpp
+++ b/libcore/icu/src/main/native/ResourceInterface.cpp
@@ -66,17 +66,6 @@
return result;
}
-static void addObject(JNIEnv* env, jobjectArray result, const char* keyStr, jobject elem, int index) {
- jclass objArray_class = env->FindClass("java/lang/Object");
- jobjectArray element = env->NewObjectArray(2, objArray_class, NULL);
- jstring key = env->NewStringUTF(keyStr);
- env->SetObjectArrayElement(element, 0, key);
- env->SetObjectArrayElement(element, 1, elem);
- env->SetObjectArrayElement(result, index, element);
- env->DeleteLocalRef(key);
- env->DeleteLocalRef(element);
-}
-
static jint getCurrencyFractionDigitsNative(JNIEnv* env, jclass clazz, jstring currencyCode) {
UErrorCode status = U_ZERO_ERROR;
@@ -159,13 +148,13 @@
return NULL;
}
- ScopedResourceBundle rootElems(ures_getByKey(root.get(), "Currencies", NULL, &status));
+ ScopedResourceBundle currencies(ures_getByKey(root.get(), "Currencies", NULL, &status));
if (U_FAILURE(status)) {
return NULL;
}
const char* currName = env->GetStringUTFChars(currencyCode, NULL);
- ScopedResourceBundle currencyElems(ures_getByKey(rootElems.get(), currName, NULL, &status));
+ ScopedResourceBundle currencyElems(ures_getByKey(currencies.get(), currName, NULL, &status));
env->ReleaseStringUTFChars(currencyCode, currName);
if (U_FAILURE(status)) {
return NULL;
@@ -354,22 +343,23 @@
return result;
}
-static void getDayIntVector(JNIEnv* env, UResourceBundle* gregorian, int* values) {
-
+static bool getDayIntVector(JNIEnv* env, UResourceBundle* gregorian, int* values) {
// get the First day of week and the minimal days in first week numbers
UErrorCode status = U_ZERO_ERROR;
ScopedResourceBundle gregorianElems(ures_getByKey(gregorian, "DateTimeElements", NULL, &status));
if (U_FAILURE(status)) {
- return;
+ return false;
}
int intVectSize;
const int* result = ures_getIntVector(gregorianElems.get(), &intVectSize, &status);
if (U_FAILURE(status) || intVectSize != 2) {
- return;
+ return false;
}
+
values[0] = result[0];
values[1] = result[1];
+ return true;
}
static jobjectArray getAmPmMarkers(JNIEnv* env, UResourceBundle* gregorian) {
@@ -556,456 +546,139 @@
return env->NewString(patternChars, 10);
}
-static jstring getIntCurrencyCode(JNIEnv* env, jclass clazz, jstring locale) {
+static jstring getIntCurrencyCode(JNIEnv* env, jstring locale) {
const char* locStr = env->GetStringUTFChars(locale, NULL);
- char country[3] = {0,0,0};
- // getting the 2 character country name
- if(strlen(locStr) < 5) {
+ // Extract the 2-character country name.
+ if (strlen(locStr) < 5) {
env->ReleaseStringUTFChars(locale, locStr);
return NULL;
}
- if(locStr[3] < 'A' || locStr[3] > 'Z' || locStr[4] < 'A' || locStr[4] > 'Z') {
+ if (locStr[3] < 'A' || locStr[3] > 'Z' || locStr[4] < 'A' || locStr[4] > 'Z') {
env->ReleaseStringUTFChars(locale, locStr);
return NULL;
}
+
+ char country[3] = {0,0,0};
country[0] = locStr[3];
country[1] = locStr[4];
env->ReleaseStringUTFChars(locale, locStr);
- return getCurrencyCodeNative(env, clazz, env->NewStringUTF(country));
+ return getCurrencyCodeNative(env, NULL, env->NewStringUTF(country));
}
-static jobjectArray getContentImpl(JNIEnv* env, jclass clazz, jstring locale) {
+static void setIntegerField(JNIEnv* env, jobject obj, const char* fieldName, int value) {
+ // Convert our int to a java.lang.Integer.
+ // TODO: switch to Integer.valueOf, add error checking.
+ jclass integerClass = env->FindClass("java/lang/Integer");
+ jmethodID constructor = env->GetMethodID(integerClass, "<init>", "(I)V");
+ jobject integerValue = env->NewObject(integerClass, constructor, value);
+ // Set the field.
+ jclass localeDataClass = env->FindClass("com/ibm/icu4jni/util/LocaleData");
+ jfieldID fid = env->GetFieldID(localeDataClass, fieldName, "Ljava/lang/Integer;");
+ env->SetObjectField(obj, fid, integerValue);
+}
+
+static void setStringField(JNIEnv* env, jobject obj, const char* fieldName, jstring value) {
+ jclass localeDataClass = env->FindClass("com/ibm/icu4jni/util/LocaleData");
+ jfieldID fid = env->GetFieldID(localeDataClass, fieldName, "Ljava/lang/String;");
+ env->SetObjectField(obj, fid, value);
+}
+
+static void setStringArrayField(JNIEnv* env, jobject obj, const char* fieldName, jobjectArray value) {
+ jclass localeDataClass = env->FindClass("com/ibm/icu4jni/util/LocaleData");
+ jfieldID fid = env->GetFieldID(localeDataClass, fieldName, "[Ljava/lang/String;");
+ env->SetObjectField(obj, fid, value);
+}
+
+static void setStringField(JNIEnv* env, jobject obj, const char* fieldName, UResourceBundle* bundle, int index) {
+ UErrorCode status = U_ZERO_ERROR;
+ int charCount;
+ const UChar* chars = ures_getStringByIndex(bundle, index, &charCount, &status);
+ if (U_SUCCESS(status)) {
+ setStringField(env, obj, fieldName, env->NewString(chars, charCount));
+ }
+}
+
+static jboolean initLocaleDataImpl(JNIEnv* env, jclass clazz, jstring locale, jobject localeData) {
const char* loc = env->GetStringUTFChars(locale, NULL);
UErrorCode status = U_ZERO_ERROR;
- UResourceBundle* root = ures_openU(NULL, loc, &status);
+ ScopedResourceBundle root(ures_openU(NULL, loc, &status));
env->ReleaseStringUTFChars(locale, loc);
if (U_FAILURE(status)) {
- LOGE("Error getting resources: %s", u_errorName(status));
+ LOGE("Error getting ICU resource bundle: %s", u_errorName(status));
status = U_ZERO_ERROR;
- return NULL;
+ return JNI_FALSE;
}
- jclass obj_class = env->FindClass("[Ljava/lang/Object;");
- jclass integer_class = env->FindClass("java/lang/Integer");
- jmethodID integerInit = env->GetMethodID(integer_class, "<init>", "(I)V");
- jobjectArray result;
+ ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status));
+ if (U_FAILURE(status)) {
+ return JNI_FALSE;
+ }
- jobject firstDayOfWeek = NULL;
- jobject minimalDaysInFirstWeek = NULL;
- jobjectArray amPmMarkers = NULL;
- jobjectArray eras = NULL;
- jobjectArray weekdays = NULL;
- jobjectArray shortWeekdays = NULL;
- jobjectArray months = NULL;
- jobjectArray shortMonths = NULL;
- jstring time_SHORT = NULL;
- jstring time_MEDIUM = NULL;
- jstring time_LONG = NULL;
- jstring time_FULL = NULL;
- jstring date_SHORT = NULL;
- jstring date_MEDIUM = NULL;
- jstring date_LONG = NULL;
- jstring date_FULL = NULL;
- jstring decimalPatternChars = NULL;
- jstring naN = NULL;
- jstring infinity = NULL;
+ ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status));
+ if (U_FAILURE(status)) {
+ return JNI_FALSE;
+ }
+
+ int firstDayVals[2];
+ if (getDayIntVector(env, gregorian.get(), firstDayVals)) {
+ setIntegerField(env, localeData, "firstDayOfWeek", firstDayVals[0]);
+ setIntegerField(env, localeData, "minimalDaysInFirstWeek", firstDayVals[1]);
+ }
+
+ setStringArrayField(env, localeData, "amPm", getAmPmMarkers(env, gregorian.get()));
+ setStringArrayField(env, localeData, "eras", getEras(env, gregorian.get()));
+
+ setStringArrayField(env, localeData, "longMonthNames", getLongMonthNames(env, gregorian.get()));
+ setStringArrayField(env, localeData, "shortMonthNames", getShortMonthNames(env, gregorian.get()));
+ setStringArrayField(env, localeData, "longWeekdayNames", getLongWeekdayNames(env, gregorian.get()));
+ setStringArrayField(env, localeData, "shortWeekdayNames", getShortWeekdayNames(env, gregorian.get()));
+
+ ScopedResourceBundle gregorianElems(ures_getByKey(gregorian.get(), "DateTimePatterns", NULL, &status));
+ if (U_SUCCESS(status)) {
+ setStringField(env, localeData, "fullTimeFormat", gregorianElems.get(), 0);
+ setStringField(env, localeData, "longTimeFormat", gregorianElems.get(), 1);
+ setStringField(env, localeData, "mediumTimeFormat", gregorianElems.get(), 2);
+ setStringField(env, localeData, "shortTimeFormat", gregorianElems.get(), 3);
+ setStringField(env, localeData, "fullDateFormat", gregorianElems.get(), 4);
+ setStringField(env, localeData, "longDateFormat", gregorianElems.get(), 5);
+ setStringField(env, localeData, "mediumDateFormat", gregorianElems.get(), 6);
+ setStringField(env, localeData, "shortDateFormat", gregorianElems.get(), 7);
+ }
+ status = U_ZERO_ERROR;
+
+ ScopedResourceBundle numberElements(ures_getByKey(root.get(), "NumberElements", NULL, &status));
+ if (U_SUCCESS(status) && ures_getSize(numberElements.get()) >= 11) {
+ setStringField(env, localeData, "decimalPatternChars", getDecimalPatternChars(env, numberElements.get()));
+ setStringField(env, localeData, "infinity", numberElements.get(), 9);
+ setStringField(env, localeData, "NaN", numberElements.get(), 10);
+ }
+ status = U_ZERO_ERROR;
+
+ jstring internationalCurrencySymbol = getIntCurrencyCode(env, locale);
jstring currencySymbol = NULL;
- jstring intCurrencySymbol = NULL;
- jstring numberPattern = NULL;
- jstring integerPattern = NULL;
- jstring currencyPattern = NULL;
- jstring percentPattern = NULL;
- jobjectArray zones = NULL;
-
- int counter = 0;
-
-
- const jchar* nan = NULL;
- const jchar* inf = NULL;
- int nanL, infL;
-
-
- UResourceBundle* gregorian;
- UResourceBundle* gregorianElems;
- UResourceBundle* rootElems;
-
-
-
-
- // get the resources needed
- rootElems = ures_getByKey(root, "calendar", NULL, &status);
- if(U_FAILURE(status)) {
- return NULL;
- }
-
- gregorian = ures_getByKey(rootElems, "gregorian", NULL, &status);
- if(U_FAILURE(status)) {
- ures_close(rootElems);
- return NULL;
- }
-
-
-
- // adding the first day of week and minimal days in first week values
- int firstDayVals[2] = {-1, -1};
- getDayIntVector(env, gregorian, firstDayVals);
- if((firstDayVals[0] != -1) && (firstDayVals[1] != -1)) {
- firstDayOfWeek = env->NewObject(integer_class, integerInit, firstDayVals[0]);
- minimalDaysInFirstWeek = env->NewObject(integer_class, integerInit, firstDayVals[1]);
- // adding First_Day and Minimal_Days integer to the result
- counter += 2;
- }
-
-
- // adding ampm string array to the result");
- amPmMarkers = getAmPmMarkers(env, gregorian);
- if(amPmMarkers != NULL) {
- counter++;
- }
-
-
- // adding eras string array to the result
- eras = getEras(env, gregorian);
- if(eras != NULL) {
- counter++;
- }
-
-
- // adding month names string array to the result
- months = getLongMonthNames(env, gregorian);
- if(months != NULL) {
- counter++;
- }
-
-
- // adding short month names string array to the result
- shortMonths = getShortMonthNames(env, gregorian);
- if(shortMonths != NULL) {
- counter++;
- }
-
-
- // adding day names string array to the result
- weekdays = getLongWeekdayNames(env, gregorian);
- if(weekdays != NULL) {
- counter++;
- }
-
-
- // adding short day names string array to the result
- shortWeekdays = getShortWeekdayNames(env, gregorian);
- if(shortWeekdays != NULL) {
- counter++;
- }
-
- const UChar* pattern;
- jchar check[2] = {0, 0};
- u_uastrcpy(check, "v");
- jchar replacement[2] = {0, 0};
- u_uastrcpy(replacement, "z");
- jchar* pos;
- jchar* patternCopy;
- int patternLength;
-
- // adding date and time format patterns to the result
- gregorianElems = ures_getByKey(gregorian, "DateTimePatterns", NULL, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- goto endOfCalendar;
- }
-
- pattern = ures_getStringByIndex(gregorianElems, 0, &patternLength, &status);
- // there are some patterns in icu that use the pattern character 'v'
- // java doesn't accept this, so it gets replaced by 'z' which has
- // about the same result as 'v', the timezone name.
- // 'v' -> "PT", 'z' -> "PST", v is the generic timezone and z the standard tz
- // "vvvv" -> "Pacific Time", "zzzz" -> "Pacific Standard Time"
- patternCopy = new jchar[patternLength + 1];
- u_strcpy(patternCopy, pattern);
- if(U_FAILURE(status)) {
- delete[] patternCopy;
- status = U_ZERO_ERROR;
- goto endOfCalendar;
- }
- while((pos = u_strchr(patternCopy, check[0])) != NULL) {
- u_memset(pos, replacement[0], 1);
- }
- time_FULL = env->NewString(patternCopy, patternLength);
- delete[] patternCopy;
- counter++;
-
- pattern = ures_getStringByIndex(gregorianElems, 1, &patternLength, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- goto endOfCalendar;
- }
- time_LONG = env->NewString(pattern, patternLength);
- counter++;
-
- pattern = ures_getStringByIndex(gregorianElems, 2, &patternLength, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- goto endOfCalendar;
- }
- time_MEDIUM = env->NewString(pattern, patternLength);
- counter++;
-
- pattern = ures_getStringByIndex(gregorianElems, 3, &patternLength, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- goto endOfCalendar;
- }
- time_SHORT = env->NewString(pattern, patternLength);
- counter++;
-
- pattern = ures_getStringByIndex(gregorianElems, 4, &patternLength, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- goto endOfCalendar;
- }
- date_FULL = env->NewString(pattern, patternLength);
- counter++;
-
- pattern = ures_getStringByIndex(gregorianElems, 5, &patternLength, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- goto endOfCalendar;
- }
- date_LONG = env->NewString(pattern, patternLength);
- counter++;
-
- pattern = ures_getStringByIndex(gregorianElems, 6, &patternLength, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- goto endOfCalendar;
- }
- date_MEDIUM = env->NewString(pattern, patternLength);
- counter++;
-
- pattern = ures_getStringByIndex(gregorianElems, 7, &patternLength, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- goto endOfCalendar;
- }
- date_SHORT = env->NewString(pattern, patternLength);
- counter++;
-
-
-endOfCalendar:
-
- if(gregorianElems != NULL) {
- ures_close(gregorianElems);
- }
- ures_close(gregorian);
- ures_close(rootElems);
-
-
- rootElems = ures_getByKey(root, "NumberElements", NULL, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- }
-
- if(ures_getSize(rootElems) >= 11) {
-
- // adding decimal pattern chars to the result
- decimalPatternChars = getDecimalPatternChars(env, rootElems);
- if(decimalPatternChars != NULL) {
- counter++;
- }
-
- // adding NaN pattern char to the result
- nan = ures_getStringByIndex(rootElems, 10, &nanL, &status);
- if(U_SUCCESS(status)) {
- naN = env->NewString(nan, nanL);
- counter++;
- }
- status = U_ZERO_ERROR;
-
- // adding infinity pattern char to the result
- inf = ures_getStringByIndex(rootElems, 9, &infL, &status);
- if(U_SUCCESS(status)) {
- infinity = env->NewString(inf, infL);
- counter++;
- }
- status = U_ZERO_ERROR;
- }
-
- ures_close(rootElems);
-
-
- // adding intl currency code to result
- intCurrencySymbol = getIntCurrencyCode(env, clazz, locale);
- if(intCurrencySymbol != NULL) {
- // adding currency symbol to result
- currencySymbol = getCurrencySymbolNative(env, clazz, locale, intCurrencySymbol);
- // TODO: this is broken; the two will never be identical *unless*
- // they're NULL. Given that string equality is hard here, and this
- // code has always been broken, does this matter?
- if (currencySymbol == intCurrencySymbol) {
- currencySymbol = NULL;
- }
+ if (internationalCurrencySymbol != NULL) {
+ currencySymbol = getCurrencySymbolNative(env, clazz, locale, internationalCurrencySymbol);
} else {
- intCurrencySymbol = env->NewStringUTF("XXX");
+ internationalCurrencySymbol = env->NewStringUTF("XXX");
}
- if(currencySymbol == NULL) {
- // creating a new string explicitly with the UTF-8 encoding of "\u00a4"
+ if (currencySymbol == NULL) {
+ // This is the UTF-8 encoding of U+00A4 (CURRENCY SIGN).
currencySymbol = env->NewStringUTF("\xc2\xa4");
}
- counter += 2;
+ setStringField(env, localeData, "currencySymbol", currencySymbol);
+ setStringField(env, localeData, "internationalCurrencySymbol", internationalCurrencySymbol);
-
- // adding number format patterns to the result
- int numOfEntries;
- int decSepOffset;
- NumberFormat* nf;
- jchar* tmpPattern;
-
- rootElems = ures_getByKey(root, "NumberPatterns", NULL, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- goto zones;
+ ScopedResourceBundle numberPatterns(ures_getByKey(root.get(), "NumberPatterns", NULL, &status));
+ if (U_SUCCESS(status) && ures_getSize(numberPatterns.get()) >= 3) {
+ setStringField(env, localeData, "numberPattern", numberPatterns.get(), 0);
+ setStringField(env, localeData, "currencyPattern", numberPatterns.get(), 1);
+ setStringField(env, localeData, "percentPattern", numberPatterns.get(), 2);
}
- numOfEntries = ures_getSize(rootElems);
- if(numOfEntries < 3) {
- ures_close(rootElems);
- goto zones;
- }
-
- // number pattern
- pattern = ures_getStringByIndex(rootElems, 0, &patternLength, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- ures_close(rootElems);
- goto zones;
- }
- numberPattern = env->NewString(pattern, patternLength);
- counter++;
-
- // integer pattern derived from number pattern
- // We need to convert a C string literal to a UChar string for u_strcspn.
- static const char c_decSep[] = ".";
- UChar decSep[sizeof(c_decSep)];
- u_charsToUChars(c_decSep, decSep, sizeof(c_decSep));
- decSepOffset = u_strcspn(pattern, decSep);
- tmpPattern = new jchar[decSepOffset + 1];
- u_strncpy(tmpPattern, pattern, decSepOffset);
- integerPattern = env->NewString(tmpPattern, decSepOffset);
- delete[] tmpPattern;
- counter++;
-
- // currency pattern
- pattern = ures_getStringByIndex(rootElems, 1, &patternLength, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- ures_close(rootElems);
- goto zones;
- }
- currencyPattern = env->NewString(pattern, patternLength);
- counter++;
-
- // percent pattern
- pattern = ures_getStringByIndex(rootElems, 2, &patternLength, &status);
- if(U_FAILURE(status)) {
- status = U_ZERO_ERROR;
- ures_close(rootElems);
- goto zones;
- }
- percentPattern = env->NewString(pattern, patternLength);
- counter++;
-
- ures_close(rootElems);
-
-zones:
-
- ures_close(root);
-
-
- // collect all content and put it into an array
- result = env->NewObjectArray(counter, obj_class, NULL);
-
- int index = 0;
- if(firstDayOfWeek != NULL && index < counter) {
- addObject(env, result, "First_Day", firstDayOfWeek, index++);
- }
- if(minimalDaysInFirstWeek != NULL && index < counter) {
- addObject(env, result, "Minimal_Days", minimalDaysInFirstWeek, index++);
- }
- if(amPmMarkers != NULL && index < counter) {
- addObject(env, result, "ampm", amPmMarkers, index++);
- }
- if(eras != NULL && index < counter) {
- addObject(env, result, "eras", eras, index++);
- }
- if(weekdays != NULL && index < counter) {
- addObject(env, result, "weekdays", weekdays, index++);
- }
- if(shortWeekdays != NULL && index < counter) {
- addObject(env, result, "shortWeekdays", shortWeekdays, index++);
- }
- if(months != NULL && index < counter) {
- addObject(env, result, "months", months, index++);
- }
- if(shortMonths != NULL && index < counter) {
- addObject(env, result, "shortMonths", shortMonths, index++);
- }
- if(time_SHORT != NULL && index < counter) {
- addObject(env, result, "Time_SHORT", time_SHORT, index++);
- }
- if(time_MEDIUM != NULL && index < counter) {
- addObject(env, result, "Time_MEDIUM", time_MEDIUM, index++);
- }
- if(time_LONG != NULL && index < counter) {
- addObject(env, result, "Time_LONG", time_LONG, index++);
- }
- if(time_FULL != NULL && index < counter) {
- addObject(env, result, "Time_FULL", time_FULL, index++);
- }
- if(date_SHORT != NULL && index < counter) {
- addObject(env, result, "Date_SHORT", date_SHORT, index++);
- }
- if(date_MEDIUM != NULL && index < counter) {
- addObject(env, result, "Date_MEDIUM", date_MEDIUM, index++);
- }
- if(date_LONG != NULL && index < counter) {
- addObject(env, result, "Date_LONG", date_LONG, index++);
- }
- if(date_FULL != NULL && index < counter) {
- addObject(env, result, "Date_FULL", date_FULL, index++);
- }
- if(decimalPatternChars != NULL && index < counter) {
- addObject(env, result, "DecimalPatternChars", decimalPatternChars, index++);
- }
- if(naN != NULL && index < counter) {
- addObject(env, result, "NaN", naN, index++);
- }
- if(infinity != NULL && index < counter) {
- addObject(env, result, "Infinity", infinity, index++);
- }
- if(currencySymbol != NULL && index < counter) {
- addObject(env, result, "CurrencySymbol", currencySymbol, index++);
- }
- if(intCurrencySymbol != NULL && index < counter) {
- addObject(env, result, "IntCurrencySymbol", intCurrencySymbol, index++);
- }
- if(numberPattern != NULL && index < counter) {
- addObject(env, result, "Number", numberPattern, index++);
- }
- if(integerPattern != NULL && index < counter) {
- addObject(env, result, "Integer", integerPattern, index++);
- }
- if(currencyPattern != NULL && index < counter) {
- addObject(env, result, "Currency", currencyPattern, index++);
- }
- if(percentPattern != NULL && index < counter) {
- addObject(env, result, "Percent", percentPattern, index++);
- }
-
- return result;
-
+ return JNI_TRUE;
}
static JNINativeMethod gMethods[] = {
@@ -1043,9 +716,9 @@
{"getDisplayTimeZoneNative",
"(Ljava/lang/String;ZILjava/lang/String;)Ljava/lang/String;",
(void*) getDisplayTimeZoneNative},
- {"getContentImpl",
- "(Ljava/lang/String;)[[Ljava/lang/Object;",
- (void*) getContentImpl},
+ {"initLocaleDataImpl",
+ "(Ljava/lang/String;Lcom/ibm/icu4jni/util/LocaleData;)Z",
+ (void*) initLocaleDataImpl},
};
int register_com_ibm_icu4jni_util_Resources(JNIEnv* env) {
diff --git a/libcore/luni/src/main/java/java/util/Calendar.java b/libcore/luni/src/main/java/java/util/Calendar.java
index 3d1f4ad..7f2e92d 100644
--- a/libcore/luni/src/main/java/java/util/Calendar.java
+++ b/libcore/luni/src/main/java/java/util/Calendar.java
@@ -23,6 +23,8 @@
import java.io.ObjectStreamField;
import java.io.Serializable;
+import com.ibm.icu4jni.util.LocaleData;
+
/**
* {@code Calendar} is an abstract base class for converting between a
* {@code Date} object and a set of integer fields such as
@@ -686,15 +688,9 @@
protected Calendar(TimeZone timezone, Locale locale) {
this(timezone);
// BEGIN android-changed
- // com.ibm.icu.util.Calendar icuCalendar = com.ibm.icu.util.Calendar
- // .getInstance(com.ibm.icu.util.SimpleTimeZone
- // .getTimeZone(timezone.getID()), locale);
- // setFirstDayOfWeek(icuCalendar.getFirstDayOfWeek());
- // setMinimalDaysInFirstWeek(icuCalendar.getMinimalDaysInFirstWeek());
- ResourceBundle bundle = com.ibm.icu4jni.util.Resources.getLocaleInstance(locale);
- setFirstDayOfWeek(((Integer) bundle.getObject("First_Day")).intValue()); //$NON-NLS-1$
- setMinimalDaysInFirstWeek(((Integer) bundle.getObject("Minimal_Days")) //$NON-NLS-1$
- .intValue());
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ setFirstDayOfWeek(localeData.firstDayOfWeek.intValue());
+ setMinimalDaysInFirstWeek(localeData.minimalDaysInFirstWeek.intValue());
// END android-changed
}
diff --git a/libcore/luni/src/main/java/java/util/Currency.java b/libcore/luni/src/main/java/java/util/Currency.java
index 1673455..9ce92f6 100644
--- a/libcore/luni/src/main/java/java/util/Currency.java
+++ b/libcore/luni/src/main/java/java/util/Currency.java
@@ -18,6 +18,7 @@
package java.util;
// BEGIN android-added
+import com.ibm.icu4jni.util.LocaleData;
import com.ibm.icu4jni.util.Resources;
import java.util.logging.Logger;
import org.apache.harmony.luni.util.Msg;
@@ -163,10 +164,10 @@
return currencyCode;
}
- // Check the Locale bundle first, in case the locale has the same currency.
- ResourceBundle localeBundle = com.ibm.icu4jni.util.Resources.getLocaleInstance(locale);
- if (localeBundle.getString("IntCurrencySymbol").equals(currencyCode)) {
- return localeBundle.getString("CurrencySymbol");
+ // Check the locale first, in case the locale has the same currency.
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ if (localeData.internationalCurrencySymbol.equals(currencyCode)) {
+ return localeData.currencySymbol;
}
// check if the currency bundle for this locale has an entry for this currency
diff --git a/libcore/text/src/main/java/java/text/DateFormat.java b/libcore/text/src/main/java/java/text/DateFormat.java
index 531bed8..80f38c9 100644
--- a/libcore/text/src/main/java/java/text/DateFormat.java
+++ b/libcore/text/src/main/java/java/text/DateFormat.java
@@ -31,6 +31,7 @@
// BEGIN android-added
import java.util.TimeZone;
+import com.ibm.icu4jni.util.LocaleData;
import org.apache.harmony.text.internal.nls.Messages;
/**
@@ -470,9 +471,8 @@
public final static DateFormat getDateInstance(int style, Locale locale) {
checkDateStyle(style);
// BEGIN android-changed
- ResourceBundle bundle = getBundle(locale);
- String pattern = bundle.getString("Date_" + getStyleName(style)); //$NON-NLS-1$
- return new SimpleDateFormat(pattern, locale);
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ return new SimpleDateFormat(getDateFormat(localeData, style), locale);
// END android-changed
}
@@ -528,9 +528,8 @@
checkTimeStyle(timeStyle);
checkDateStyle(dateStyle);
// BEGIN android-changed
- ResourceBundle bundle = getBundle(locale);
- String pattern = bundle.getString("Date_" + getStyleName(dateStyle)) //$NON-NLS-1$
- + " " + bundle.getString("Time_" + getStyleName(timeStyle)); //$NON-NLS-1$ //$NON-NLS-2$
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ String pattern = getDateFormat(localeData, dateStyle) + " " + getTimeFormat(localeData, timeStyle);
return new SimpleDateFormat(pattern, locale);
// END android-changed
}
@@ -555,26 +554,37 @@
return numberFormat;
}
- static String getStyleName(int style) {
- String styleName;
+ // BEGIN android-added
+ protected static String getDateFormat(LocaleData localeData, int style) {
switch (style) {
- case SHORT:
- styleName = "SHORT"; //$NON-NLS-1$
- break;
- case MEDIUM:
- styleName = "MEDIUM"; //$NON-NLS-1$
- break;
- case LONG:
- styleName = "LONG"; //$NON-NLS-1$
- break;
- case FULL:
- styleName = "FULL"; //$NON-NLS-1$
- break;
- default:
- styleName = ""; //$NON-NLS-1$
+ case SHORT:
+ return localeData.shortDateFormat;
+ case MEDIUM:
+ return localeData.mediumDateFormat;
+ case LONG:
+ return localeData.longDateFormat;
+ case FULL:
+ return localeData.fullDateFormat;
}
- return styleName;
+ throw new AssertionError();
}
+ // END android-added
+
+ // BEGIN android-added
+ protected static String getTimeFormat(LocaleData localeData, int style) {
+ switch (style) {
+ case SHORT:
+ return localeData.shortTimeFormat;
+ case MEDIUM:
+ return localeData.mediumTimeFormat;
+ case LONG:
+ return localeData.longTimeFormat;
+ case FULL:
+ return localeData.fullTimeFormat;
+ }
+ throw new AssertionError();
+ }
+ // END android-added
/**
* Returns a {@code DateFormat} instance for formatting and parsing time
@@ -620,9 +630,8 @@
public final static DateFormat getTimeInstance(int style, Locale locale) {
checkTimeStyle(style);
// BEGIN android-changed
- ResourceBundle bundle = getBundle(locale);
- String pattern = bundle.getString("Time_" + getStyleName(style)); //$NON-NLS-1$
- return new SimpleDateFormat(pattern, locale);
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ return new SimpleDateFormat(getTimeFormat(localeData, style), locale);
// END android-changed
}
diff --git a/libcore/text/src/main/java/java/text/DateFormatSymbols.java b/libcore/text/src/main/java/java/text/DateFormatSymbols.java
index e8e1f69..767a301 100644
--- a/libcore/text/src/main/java/java/text/DateFormatSymbols.java
+++ b/libcore/text/src/main/java/java/text/DateFormatSymbols.java
@@ -31,6 +31,7 @@
// END android-added
// BEGIN android-added
+import com.ibm.icu4jni.util.LocaleData;
import com.ibm.icu4jni.util.Resources;
// END android-added
/**
@@ -121,16 +122,16 @@
* the locale.
*/
public DateFormatSymbols(Locale locale) {
- // BEGIN android-changed
- localPatternChars = SimpleDateFormat.patternChars;
- ResourceBundle bundle = Format.getBundle(locale);
- ampms = bundle.getStringArray("ampm"); //$NON-NLS-1$
- eras = bundle.getStringArray("eras"); //$NON-NLS-1$
- months = bundle.getStringArray("months"); //$NON-NLS-1$
- shortMonths = bundle.getStringArray("shortMonths"); //$NON-NLS-1$
- shortWeekdays = bundle.getStringArray("shortWeekdays"); //$NON-NLS-1$
- weekdays = bundle.getStringArray("weekdays"); //$NON-NLS-1$
this.locale = locale;
+ // BEGIN android-changed
+ this.localPatternChars = SimpleDateFormat.patternChars;
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ this.ampms = localeData.amPm;
+ this.eras = localeData.eras;
+ this.months = localeData.longMonthNames;
+ this.shortMonths = localeData.shortMonthNames;
+ this.weekdays = localeData.longWeekdayNames;
+ this.shortWeekdays = localeData.shortWeekdayNames;
// END android-changed
}
@@ -334,13 +335,8 @@
*/
public String[][] getZoneStrings() {
// BEGIN android-changed
- String[][] zoneStrings = internalZoneStrings();
+ return Resources.clone2dStringArray(internalZoneStrings());
// END android-changed
- String[][] clone = new String[zoneStrings.length][];
- for (int i = zoneStrings.length; --i >= 0;) {
- clone[i] = zoneStrings[i].clone();
- }
- return clone;
}
@Override
@@ -477,6 +473,6 @@
* the two-dimensional array of strings.
*/
public void setZoneStrings(String[][] data) {
- zoneStrings = data.clone();
+ zoneStrings = Resources.clone2dStringArray(data);
}
}
diff --git a/libcore/text/src/main/java/java/text/DecimalFormat.java b/libcore/text/src/main/java/java/text/DecimalFormat.java
index 7a0f529..480d79d 100644
--- a/libcore/text/src/main/java/java/text/DecimalFormat.java
+++ b/libcore/text/src/main/java/java/text/DecimalFormat.java
@@ -32,6 +32,8 @@
import java.util.Currency;
import java.util.Locale;
+import com.ibm.icu4jni.util.LocaleData;
+
/**
* A concrete subclass of {@link NumberFormat} that formats decimal numbers. It
* has a variety of features designed to make it possible to parse and format
@@ -565,8 +567,8 @@
icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
symbols = new DecimalFormatSymbols(locale);
// BEGIN android-changed
- dform = new com.ibm.icu4jni.text.DecimalFormat(
- getPattern(Locale.getDefault(), "Number"), icuSymbols);
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(Locale.getDefault());
+ dform = new com.ibm.icu4jni.text.DecimalFormat(localeData.numberPattern, icuSymbols);
// END android-changed
super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
diff --git a/libcore/text/src/main/java/java/text/DecimalFormatSymbols.java b/libcore/text/src/main/java/java/text/DecimalFormatSymbols.java
index 46849ef..1a35d0a 100644
--- a/libcore/text/src/main/java/java/text/DecimalFormatSymbols.java
+++ b/libcore/text/src/main/java/java/text/DecimalFormatSymbols.java
@@ -33,6 +33,8 @@
import java.util.ResourceBundle;
// END android-added
+import com.ibm.icu4jni.util.LocaleData;
+
/**
* Encapsulates the set of symbols (such as the decimal separator, the grouping
* separator, and so on) needed by {@code DecimalFormat} to format numbers.
@@ -82,10 +84,10 @@
*/
public DecimalFormatSymbols(Locale locale) {
// BEGIN android-changed
- ResourceBundle bundle = Format.getBundle(locale);
- patternChars = bundle.getString("DecimalPatternChars").toCharArray(); //$NON-NLS-1$
- infinity = bundle.getString("Infinity"); //$NON-NLS-1$
- NaN = bundle.getString("NaN"); //$NON-NLS-1$
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ this.patternChars = localeData.decimalPatternChars.toCharArray();
+ this.infinity = localeData.infinity;
+ this.NaN = localeData.NaN;
this.locale = locale;
try {
currency = Currency.getInstance(locale);
@@ -93,8 +95,8 @@
intlCurrencySymbol = currency.getCurrencyCode();
} catch (IllegalArgumentException e) {
currency = Currency.getInstance("XXX"); //$NON-NLS-1$
- currencySymbol = bundle.getString("CurrencySymbol"); //$NON-NLS-1$
- intlCurrencySymbol = bundle.getString("IntCurrencySymbol"); //$NON-NLS-1$
+ currencySymbol = localeData.currencySymbol;
+ intlCurrencySymbol = localeData.internationalCurrencySymbol;
}
// END android-changed
}
diff --git a/libcore/text/src/main/java/java/text/Format.java b/libcore/text/src/main/java/java/text/Format.java
index 7660f8e..eb1b837 100644
--- a/libcore/text/src/main/java/java/text/Format.java
+++ b/libcore/text/src/main/java/java/text/Format.java
@@ -88,12 +88,6 @@
}
}
- // BEGIN android-added
- static ResourceBundle getBundle(Locale locale) {
- return com.ibm.icu4jni.util.Resources.getLocaleInstance(locale);
- }
- // END android-added
-
String convertPattern(String template, String fromChars, String toChars,
boolean check) {
if (!check && fromChars.equals(toChars)) {
diff --git a/libcore/text/src/main/java/java/text/NumberFormat.java b/libcore/text/src/main/java/java/text/NumberFormat.java
index 23b0e27..ecf4483 100644
--- a/libcore/text/src/main/java/java/text/NumberFormat.java
+++ b/libcore/text/src/main/java/java/text/NumberFormat.java
@@ -32,6 +32,7 @@
import java.util.ResourceBundle;
// END android-added
+import com.ibm.icu4jni.util.LocaleData;
import org.apache.harmony.text.internal.nls.Messages;
/**
@@ -356,7 +357,8 @@
*/
public static NumberFormat getCurrencyInstance(Locale locale) {
// BEGIN android-changed
- return getInstance(locale, "Currency"); //$NON-NLS-1$
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ return getInstance(locale, localeData.currencyPattern);
// END android-changed
}
@@ -380,9 +382,10 @@
*/
public static NumberFormat getIntegerInstance(Locale locale) {
// BEGIN android-changed
- NumberFormat format = getInstance(locale, "Integer"); //$NON-NLS-1$
- format.setParseIntegerOnly(true);
- return format;
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ NumberFormat result = getInstance(locale, localeData.integerPattern);
+ result.setParseIntegerOnly(true);
+ return result;
// END android-changed
}
@@ -409,9 +412,8 @@
}
// BEGIN android-added
- static NumberFormat getInstance(Locale locale, String type) {
- return new DecimalFormat(getPattern(locale, type),
- new DecimalFormatSymbols(locale));
+ private static NumberFormat getInstance(Locale locale, String pattern) {
+ return new DecimalFormat(pattern, new DecimalFormatSymbols(locale));
}
// END android-added
@@ -477,17 +479,11 @@
*/
public static NumberFormat getNumberInstance(Locale locale) {
// BEGIN android-changed
- return getInstance(locale, "Number"); //$NON-NLS-1$
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ return getInstance(locale, localeData.numberPattern);
// END android-changed
}
- // BEGIN android-added
- static String getPattern(Locale locale, String type) {
- ResourceBundle bundle = getBundle(locale);
- return bundle.getString(type);
- }
- // END android-added
-
/**
* Returns a {@code NumberFormat} for formatting and parsing percentage
* values for the default locale.
@@ -508,7 +504,8 @@
*/
public static NumberFormat getPercentInstance(Locale locale) {
// BEGIN android-changed
- return getInstance(locale, "Percent"); //$NON-NLS-1$
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+ return getInstance(locale, localeData.percentPattern);
// END android-changed
}
diff --git a/libcore/text/src/main/java/java/text/SimpleDateFormat.java b/libcore/text/src/main/java/java/text/SimpleDateFormat.java
index 47ff930..9f54ba1 100644
--- a/libcore/text/src/main/java/java/text/SimpleDateFormat.java
+++ b/libcore/text/src/main/java/java/text/SimpleDateFormat.java
@@ -36,6 +36,7 @@
// END android-added
import java.util.Vector;
+import com.ibm.icu4jni.util.LocaleData;
import org.apache.harmony.text.internal.nls.Messages;
/**
@@ -618,10 +619,8 @@
// BEGIN android-added
private static String defaultPattern() {
- ResourceBundle bundle = getBundle(Locale.getDefault());
- String styleName = getStyleName(SHORT);
- return bundle.getString("Date_" + styleName) + " " //$NON-NLS-1$ //$NON-NLS-2$
- + bundle.getString("Time_" + styleName); //$NON-NLS-1$
+ LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(Locale.getDefault());
+ return getDateFormat(localeData, SHORT) + " " + getTimeFormat(localeData, SHORT);
}
// END android-added