OSDN Git Service

Speed up DecimalFormatSymbols.
authorElliott Hughes <enh@google.com>
Mon, 4 Jan 2010 23:23:25 +0000 (15:23 -0800)
committerElliott Hughes <enh@google.com>
Tue, 5 Jan 2010 00:20:43 +0000 (16:20 -0800)
We don't need to create temporary String objects; we can just pass a char
directly. We also don't need to initialize aspects of our native peer if
we know we're going to overwrite them straight away, and making copying
into ICU the responsibility of the icu4jni class rather than the java.text
is slightly cleaner.

Together, these changes make creating a new NumberFormat about 20% faster.

libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java
libcore/icu/src/main/native/DecimalFormatInterface.cpp
libcore/text/src/main/java/java/text/DecimalFormat.java

index 43ac3f2..7ae5f3f 100644 (file)
@@ -27,9 +27,9 @@ import java.util.ResourceBundle;
 
 public class DecimalFormatSymbols implements Cloneable {
     
-    private int addr;
+    private final int addr;
     
-    private Locale loc;
+    private final Locale loc;
 
     private DecimalFormatSymbols(int addr, Locale loc) {
         this.addr = addr;
@@ -44,10 +44,44 @@ public class DecimalFormatSymbols implements Cloneable {
         NativeDecimalFormat.setSymbol(this.addr,
                 UNumberFormatSymbol.UNUM_CURRENCY_SYMBOL.ordinal(), localeData.currencySymbol);
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_INTL_CURRENCY_SYMBOL.ordinal(), 
+                UNumberFormatSymbol.UNUM_INTL_CURRENCY_SYMBOL.ordinal(),
                 localeData.internationalCurrencySymbol);
     }
     
+    public DecimalFormatSymbols(Locale locale, java.text.DecimalFormatSymbols symbols) {
+        LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+        this.loc = locale;
+        this.addr = NativeDecimalFormat.openDecimalFormatImpl(locale.toString(),
+                localeData.numberPattern);
+        copySymbols(symbols);
+    }
+    
+    /**
+     * Copies the java.text.DecimalFormatSymbols' settings into this object.
+     */
+    public void copySymbols(final java.text.DecimalFormatSymbols dfs) {
+        Currency currency = dfs.getCurrency();
+        if (currency == null) {
+            setCurrency(Currency.getInstance("XXX")); //$NON-NLS-1$
+        } else {
+            setCurrency(Currency.getInstance(currency.getCurrencyCode()));
+        }
+        
+        setCurrencySymbol(dfs.getCurrencySymbol());
+        setDecimalSeparator(dfs.getDecimalSeparator());
+        setDigit(dfs.getDigit());
+        setGroupingSeparator(dfs.getGroupingSeparator());
+        setInfinity(dfs.getInfinity());
+        setInternationalCurrencySymbol(dfs.getInternationalCurrencySymbol());
+        setMinusSign(dfs.getMinusSign());
+        setMonetaryDecimalSeparator(dfs.getMonetaryDecimalSeparator());
+        setNaN(dfs.getNaN());
+        setPatternSeparator(dfs.getPatternSeparator());
+        setPercent(dfs.getPercent());
+        setPerMill(dfs.getPerMill());
+        setZeroDigit(dfs.getZeroDigit());
+    }
+    
     @Override
     public boolean equals(Object object) {
         if(object == null) {
@@ -117,77 +151,64 @@ public class DecimalFormatSymbols implements Cloneable {
 
     public void setDecimalSeparator(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_DECIMAL_SEPARATOR_SYMBOL.ordinal(),
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_DECIMAL_SEPARATOR_SYMBOL.ordinal(), symbol);
     }
 
     public void setDigit(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_DIGIT_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_DIGIT_SYMBOL.ordinal(), symbol);
     }
 
     public void setGroupingSeparator(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_GROUPING_SEPARATOR_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_GROUPING_SEPARATOR_SYMBOL.ordinal(), symbol);
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL.ordinal(), symbol);
     }
 
     public void setInfinity(String symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_INFINITY_SYMBOL.ordinal(), 
-                symbol);
+                UNumberFormatSymbol.UNUM_INFINITY_SYMBOL.ordinal(), symbol);
     }
 
     public void setInternationalCurrencySymbol(String symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_INTL_CURRENCY_SYMBOL.ordinal(), 
-                symbol);
+                UNumberFormatSymbol.UNUM_INTL_CURRENCY_SYMBOL.ordinal(), symbol);
     }
 
     public void setMinusSign(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_MINUS_SIGN_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_MINUS_SIGN_SYMBOL.ordinal(), symbol);
     }
 
     public void setMonetaryDecimalSeparator(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_MONETARY_SEPARATOR_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_MONETARY_SEPARATOR_SYMBOL.ordinal(), symbol);
     }
 
     public void setNaN(String symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_NAN_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_NAN_SYMBOL.ordinal(), symbol);
     }
 
     public void setPatternSeparator(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_PATTERN_SEPARATOR_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_PATTERN_SEPARATOR_SYMBOL.ordinal(), symbol);
     }
 
     public void setPercent(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_PERCENT_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_PERCENT_SYMBOL.ordinal(), symbol);
     }
 
     public void setPerMill(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_PERMILL_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_PERMILL_SYMBOL.ordinal(), symbol);
     }
 
     public void setZeroDigit(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_ZERO_DIGIT_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_ZERO_DIGIT_SYMBOL.ordinal(), symbol);
     }
  
     public Currency getCurrency() {
index 39f7307..aa10efa 100644 (file)
@@ -84,6 +84,7 @@ final class NativeDecimalFormat {
     static native int cloneImpl(int addr);
     
     static native void setSymbol(int addr, int symbol, String str);
+    static native void setSymbol(int addr, int symbol, char ch);
     
     static native String getSymbol(int addr, int symbol);
     
index f553e0a..0b19716 100644 (file)
@@ -68,28 +68,24 @@ static void closeDecimalFormatImpl(JNIEnv *env, jclass clazz, jint addr) {
     unum_close(fmt);
 }
 
-static void setSymbol(JNIEnv *env, jclass clazz, jint addr, jint symbol,
-        jstring text) {
-
-    // the errorcode returned by unum_setSymbol
+static void setSymbol(JNIEnv *env, uintptr_t addr, jint symbol,
+        const UChar* chars, int32_t charCount) {
     UErrorCode status = U_ZERO_ERROR;
+    UNumberFormat* fmt = reinterpret_cast<UNumberFormat*>(addr);
+    unum_setSymbol(fmt, static_cast<UNumberFormatSymbol>(symbol),
+            chars, charCount, &status);
+    icu4jni_error(env, status);
+}
 
-    // get the pointer to the number format
-    UNumberFormat *fmt = (UNumberFormat *)(int)addr;
-
-    // prepare the symbol string for the call to unum_setSymbol
-    const UChar *textChars = env->GetStringChars(text, NULL);
-    int textLen = env->GetStringLength(text);
-
-    // set the symbol
-    unum_setSymbol(fmt, (UNumberFormatSymbol) symbol, textChars, textLen,
-            &status);
-
-    // release previously allocated space
-    env->ReleaseStringChars(text, textChars);
+static void setSymbol_String(JNIEnv *env, jclass, jint addr, jint symbol, jstring s) {
+    const UChar* chars = env->GetStringChars(s, NULL);
+    const int32_t charCount = env->GetStringLength(s);
+    setSymbol(env, addr, symbol, chars, charCount);
+    env->ReleaseStringChars(s, chars);
+}
 
-    // check if an error occurred
-    icu4jni_error(env, status);
+static void setSymbol_char(JNIEnv *env, jclass, jint addr, jint symbol, jchar ch) {
+    setSymbol(env, addr, symbol, &ch, 1);
 }
 
 static jstring getSymbol(JNIEnv *env, jclass clazz, jint addr, jint symbol) {
@@ -773,7 +769,8 @@ static JNINativeMethod gMethods[] = {
     {"openDecimalFormatImpl", "(Ljava/lang/String;Ljava/lang/String;)I",
             (void*) openDecimalFormatImpl},
     {"closeDecimalFormatImpl", "(I)V", (void*) closeDecimalFormatImpl},
-    {"setSymbol", "(IILjava/lang/String;)V", (void*) setSymbol},
+    {"setSymbol", "(IIC)V", (void*) setSymbol_char},
+    {"setSymbol", "(IILjava/lang/String;)V", (void*) setSymbol_String},
     {"getSymbol", "(II)Ljava/lang/String;", (void*) getSymbol},
     {"setAttribute", "(III)V", (void*) setAttribute},
     {"getAttribute", "(II)I", (void*) getAttribute},
index 480d79d..7a85e71 100644 (file)
@@ -564,9 +564,9 @@ public class DecimalFormat extends NumberFormat {
      */
     public DecimalFormat() {
         Locale locale = Locale.getDefault();
+        // BEGIN android-changed
         icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
         symbols = new DecimalFormatSymbols(locale);
-        // BEGIN android-changed
         LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(Locale.getDefault());
         dform = new com.ibm.icu4jni.text.DecimalFormat(localeData.numberPattern, icuSymbols);
         // END android-changed
@@ -588,7 +588,9 @@ public class DecimalFormat extends NumberFormat {
      */
     public DecimalFormat(String pattern) {
         Locale locale = Locale.getDefault();
+        // BEGIN android-changed
         icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
+        // END android-changed
         symbols = new DecimalFormatSymbols(locale);
         dform = new com.ibm.icu4jni.text.DecimalFormat(pattern, icuSymbols);
 
@@ -612,9 +614,9 @@ public class DecimalFormat extends NumberFormat {
     public DecimalFormat(String pattern, DecimalFormatSymbols value) {
         symbols = (DecimalFormatSymbols) value.clone();
         Locale locale = symbols.getLocale();
-        icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
-        copySymbols(icuSymbols, symbols);
-
+        // BEGIN android-changed
+        icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale, symbols);
+        // END android-changed
         dform = new com.ibm.icu4jni.text.DecimalFormat(pattern, icuSymbols);
 
         super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
@@ -1045,7 +1047,7 @@ public class DecimalFormat extends NumberFormat {
         if (value != null) {
             symbols = (DecimalFormatSymbols) value.clone();
             icuSymbols = dform.getDecimalFormatSymbols();
-            copySymbols(icuSymbols, symbols);
+            icuSymbols.copySymbols(symbols); // android-changed
             dform.setDecimalFormatSymbols(icuSymbols);
         }
     }
@@ -1386,16 +1388,11 @@ public class DecimalFormat extends NumberFormat {
         this.serialVersionOnStream = fields.get("serialVersionOnStream", 0);
 
         Locale locale = (Locale) Format.getInternalField("locale", symbols);
-        // BEGIN android-removed
-        // dform = new com.ibm.icu4jni.text.DecimalFormat("", //$NON-NLS-1$
-        //         new com.ibm.icu4jni.text.DecimalFormatSymbols(locale));
-        // END android-removed
-        // BEGIN android-added
-        icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
-        copySymbols(icuSymbols, symbols);
+        // BEGIN android-changed
+        icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale, symbols);
         dform = new com.ibm.icu4jni.text.DecimalFormat("", //$NON-NLS-1$
                 icuSymbols);
-        // END android-added
+        // END android-changed
         setInternalField("useExponentialNotation", dform, Boolean
                 .valueOf(useExponentialNotation));
         setInternalField("minExponentDigits", dform,
@@ -1434,41 +1431,6 @@ public class DecimalFormat extends NumberFormat {
     }
 
     /*
-     * Copies decimal format symbols from text object to ICU one.
-     * 
-     * @param icu the object which receives the new values. @param dfs the
-     * object which contains the new values.
-     */
-    private void copySymbols(final com.ibm.icu4jni.text.DecimalFormatSymbols icu,
-            final DecimalFormatSymbols dfs) {
-        Currency currency = dfs.getCurrency();
-        // BEGIN android-changed
-        if (currency == null) {
-            icu.setCurrency(Currency.getInstance("XXX")); //$NON-NLS-1$
-        } else {
-            icu.setCurrency(Currency.getInstance(dfs.getCurrency()
-                    .getCurrencyCode()));
-        }
-        // END android-changed
-       
-        icu.setCurrencySymbol(dfs.getCurrencySymbol());
-        icu.setDecimalSeparator(dfs.getDecimalSeparator());
-        icu.setDigit(dfs.getDigit());
-        icu.setGroupingSeparator(dfs.getGroupingSeparator());
-        icu.setInfinity(dfs.getInfinity());
-        icu
-                .setInternationalCurrencySymbol(dfs
-                        .getInternationalCurrencySymbol());
-        icu.setMinusSign(dfs.getMinusSign());
-        icu.setMonetaryDecimalSeparator(dfs.getMonetaryDecimalSeparator());
-        icu.setNaN(dfs.getNaN());
-        icu.setPatternSeparator(dfs.getPatternSeparator());
-        icu.setPercent(dfs.getPercent());
-        icu.setPerMill(dfs.getPerMill());
-        icu.setZeroDigit(dfs.getZeroDigit());
-    }
-
-    /*
      * Sets private field value by reflection.
      * 
      * @param fieldName the field name to be set @param target the object which