summaryrefslogtreecommitdiffstats
path: root/icu/src/main
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2010-01-25 23:13:46 -0800
committerElliott Hughes <enh@google.com>2010-01-26 16:05:42 -0800
commitf2d5062b67e57ef00ee81fec67480f0d58d66b50 (patch)
tree2b549c42ac9ab9dab0e2c0a4bb165a40d9e956fb /icu/src/main
parentab3c1e059b3df3b81b7945ea160e1c6296811bc4 (diff)
downloadlibcore-f2d5062b67e57ef00ee81fec67480f0d58d66b50.zip
libcore-f2d5062b67e57ef00ee81fec67480f0d58d66b50.tar.gz
libcore-f2d5062b67e57ef00ee81fec67480f0d58d66b50.tar.bz2
Simplify our DecimalFormat.
Both the is-a and has-a hierarchies for our DecimalFormat implementation were over-complicated. This patch starts to address that, and makes cloning twice as fast (50us versus 100us), but not as fast as I'd like (<10us), and without making much of a dent in the time it takes to create a new NumberFormat (550us versus 600us). The speed of cloning is important because Formatter has a hack that uses it, and I want to change NumberFormat so that it always hands out clones... at least until I have time to make "new NumberFormat" acceptably fast. Also fixes DecimalFormat.applyLocalizedPattern (which used to behave as if you'd called applyPattern).
Diffstat (limited to 'icu/src/main')
-rw-r--r--icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java218
-rw-r--r--icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java268
-rw-r--r--icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java26
-rw-r--r--icu/src/main/native/NativeDecimalFormat.cpp124
-rw-r--r--icu/src/main/native/Resources.cpp5
5 files changed, 177 insertions, 464 deletions
diff --git a/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java b/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
index 4b296d5..d995dc6 100644
--- a/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
+++ b/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
@@ -18,11 +18,13 @@ package com.ibm.icu4jni.text;
import com.ibm.icu4jni.text.NativeDecimalFormat.UNumberFormatAttribute;
import com.ibm.icu4jni.text.NativeDecimalFormat.UNumberFormatTextAttribute;
+import com.ibm.icu4jni.util.LocaleData;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
+import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;
import java.text.Format;
import java.text.NumberFormat;
@@ -30,19 +32,32 @@ import java.text.ParsePosition;
import java.util.Currency;
import java.util.Locale;
-public class DecimalFormat extends NumberFormat {
-
- private int addr;
-
- private DecimalFormatSymbols symbols;
-
- // fix to be icu4j conform (harmony wants this field to exist)
- // for serialization of java.text.DecimalFormat
- @SuppressWarnings("unused")
- private boolean useExponentialNotation = false;
- @SuppressWarnings("unused")
- private byte minExponentDigits = 0;
-
+public class DecimalFormat {
+ // Constants corresponding to the native type UNumberFormatSymbol, for use with getSymbol/setSymbol.
+ private static final int UNUM_DECIMAL_SEPARATOR_SYMBOL = 0;
+ private static final int UNUM_GROUPING_SEPARATOR_SYMBOL = 1;
+ private static final int UNUM_PATTERN_SEPARATOR_SYMBOL = 2;
+ private static final int UNUM_PERCENT_SYMBOL = 3;
+ private static final int UNUM_ZERO_DIGIT_SYMBOL = 4;
+ private static final int UNUM_DIGIT_SYMBOL = 5;
+ private static final int UNUM_MINUS_SIGN_SYMBOL = 6;
+ private static final int UNUM_PLUS_SIGN_SYMBOL = 7;
+ private static final int UNUM_CURRENCY_SYMBOL = 8;
+ private static final int UNUM_INTL_CURRENCY_SYMBOL = 9;
+ private static final int UNUM_MONETARY_SEPARATOR_SYMBOL = 10;
+ private static final int UNUM_EXPONENTIAL_SYMBOL = 11;
+ private static final int UNUM_PERMILL_SYMBOL = 12;
+ private static final int UNUM_PAD_ESCAPE_SYMBOL = 13;
+ private static final int UNUM_INFINITY_SYMBOL = 14;
+ private static final int UNUM_NAN_SYMBOL = 15;
+ private static final int UNUM_SIGNIFICANT_DIGIT_SYMBOL = 16;
+ private static final int UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL = 17;
+ private static final int UNUM_FORMAT_SYMBOL_COUNT = 18;
+
+ // The address of the ICU DecimalFormat* on the native heap.
+ private final int addr;
+
+ // TODO: store all these in java.text.DecimalFormat instead!
private boolean negPrefNull;
private boolean negSuffNull;
private boolean posPrefNull;
@@ -50,37 +65,52 @@ public class DecimalFormat extends NumberFormat {
/**
* Cache the BigDecimal form of the multiplier. This is null until we've
- * formatted a BigDecimal (with a multipler that is not 1), or the user has
+ * formatted a BigDecimal (with a multiplier that is not 1), or the user has
* explicitly called {@link #setMultiplier(int)} with any multiplier.
*/
private transient BigDecimal multiplierBigDecimal = null;
- public DecimalFormat(String pattern, DecimalFormatSymbols icuSymbols) {
- this.addr = icuSymbols.getAddr();
- this.symbols = icuSymbols;
- applyPattern(pattern);
+ public DecimalFormat(String pattern, Locale locale, DecimalFormatSymbols symbols) {
+ this.addr = NativeDecimalFormat.openDecimalFormat(locale.toString(), pattern);
+ setDecimalFormatSymbols(symbols);
}
+ // Used to implement clone.
+ private DecimalFormat(DecimalFormat other) {
+ this.addr = NativeDecimalFormat.cloneDecimalFormatImpl(other.addr);
+ this.negPrefNull = other.negPrefNull;
+ this.negSuffNull = other.negSuffNull;
+ this.posPrefNull = other.posPrefNull;
+ this.posSuffNull = other.posSuffNull;
+ }
+
+ // TODO: remove this and just have java.text.DecimalFormat.hashCode do the right thing itself.
@Override
public int hashCode() {
- return super.hashCode() * 37 + this.getPositivePrefix().hashCode();
+ return this.getPositivePrefix().hashCode();
}
@Override
public Object clone() {
- String pat = this.toPattern();
- DecimalFormatSymbols sym = (DecimalFormatSymbols) this.symbols.clone();
- DecimalFormat newdf = new DecimalFormat(pat, sym);
- newdf.setMaximumIntegerDigits(this.getMaximumIntegerDigits());
- newdf.setMaximumFractionDigits(this.getMaximumFractionDigits());
- newdf.setMinimumIntegerDigits(this.getMinimumIntegerDigits());
- newdf.setMinimumFractionDigits(this.getMinimumFractionDigits());
- newdf.setGroupingUsed(this.isGroupingUsed());
- newdf.setGroupingSize(this.getGroupingSize());
- return newdf;
+ return new DecimalFormat(this);
}
@Override
+ protected void finalize() {
+ NativeDecimalFormat.closeDecimalFormatImpl(this.addr);
+ }
+
+ /**
+ * Note: this doesn't check that the underlying native DecimalFormat objects' configured
+ * native DecimalFormatSymbols objects are equal. It is assumed that the
+ * caller (java.text.DecimalFormat) will check the java.text.DecimalFormatSymbols objects
+ * instead, for performance.
+ *
+ * This is also unreasonably expensive, calling down to JNI multiple times.
+ *
+ * TODO: remove this and just have java.text.DecimalFormat.equals do the right thing itself.
+ */
+ @Override
public boolean equals(Object object) {
if (object == this) {
return true;
@@ -89,39 +119,47 @@ public class DecimalFormat extends NumberFormat {
return false;
}
DecimalFormat obj = (DecimalFormat) object;
-
- if(obj.addr == this.addr) {
+ if (obj.addr == this.addr) {
return true;
}
+ return obj.toPattern().equals(this.toPattern()) &&
+ obj.isDecimalSeparatorAlwaysShown() == this.isDecimalSeparatorAlwaysShown() &&
+ obj.getGroupingSize() == this.getGroupingSize() &&
+ obj.getMultiplier() == this.getMultiplier() &&
+ obj.getNegativePrefix().equals(this.getNegativePrefix()) &&
+ obj.getNegativeSuffix().equals(this.getNegativeSuffix()) &&
+ obj.getPositivePrefix().equals(this.getPositivePrefix()) &&
+ obj.getPositiveSuffix().equals(this.getPositiveSuffix()) &&
+ obj.getMaximumIntegerDigits() == this.getMaximumIntegerDigits() &&
+ obj.getMaximumFractionDigits() == this.getMaximumFractionDigits() &&
+ obj.getMinimumIntegerDigits() == this.getMinimumIntegerDigits() &&
+ obj.getMinimumFractionDigits() == this.getMinimumFractionDigits() &&
+ obj.isGroupingUsed() == this.isGroupingUsed() &&
+ obj.getCurrency() == this.getCurrency();
+ }
- boolean result = super.equals(object);
-
-
- result &= obj.toPattern().equals(this.toPattern());
- result &= obj.isDecimalSeparatorAlwaysShown() == this.isDecimalSeparatorAlwaysShown();
- result &= obj.getGroupingSize() == this.getGroupingSize();
- result &= obj.getMultiplier() == this.getMultiplier();
- result &= obj.getNegativePrefix().equals(this.getNegativePrefix());
- result &= obj.getNegativeSuffix().equals(this.getNegativeSuffix());
- result &= obj.getPositivePrefix().equals(this.getPositivePrefix());
- result &= obj.getPositiveSuffix().equals(this.getPositiveSuffix());
- result &= obj.getMaximumIntegerDigits() == this.getMaximumIntegerDigits();
- result &= obj.getMaximumFractionDigits() == this.getMaximumFractionDigits();
- result &= obj.getMinimumIntegerDigits() == this.getMinimumIntegerDigits();
- result &= obj.getMinimumFractionDigits() == this.getMinimumFractionDigits();
- result &= obj.isGroupingUsed() == this.isGroupingUsed();
- Currency objCurr = obj.getCurrency();
- Currency thisCurr = this.getCurrency();
- if(objCurr != null) {
- result &= objCurr.getCurrencyCode().equals(thisCurr.getCurrencyCode());
- result &= objCurr.getSymbol().equals(thisCurr.getSymbol());
- result &= objCurr.getDefaultFractionDigits() == thisCurr.getDefaultFractionDigits();
- } else {
- result &= thisCurr == null;
- }
- result &= obj.getDecimalFormatSymbols().equals(this.getDecimalFormatSymbols());
+ /**
+ * Copies the java.text.DecimalFormatSymbols' settings into our native peer.
+ */
+ public void setDecimalFormatSymbols(final java.text.DecimalFormatSymbols dfs) {
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_CURRENCY_SYMBOL, dfs.getCurrencySymbol());
- return result;
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_DECIMAL_SEPARATOR_SYMBOL, dfs.getDecimalSeparator());
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_DIGIT_SYMBOL, dfs.getDigit());
+
+ char groupingSeparator = dfs.getGroupingSeparator();
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_GROUPING_SEPARATOR_SYMBOL, groupingSeparator);
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, groupingSeparator);
+
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_INFINITY_SYMBOL, dfs.getInfinity());
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL, dfs.getInternationalCurrencySymbol());
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_MINUS_SIGN_SYMBOL, dfs.getMinusSign());
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_MONETARY_SEPARATOR_SYMBOL, dfs.getMonetaryDecimalSeparator());
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_NAN_SYMBOL, dfs.getNaN());
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_PATTERN_SEPARATOR_SYMBOL, dfs.getPatternSeparator());
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_PERCENT_SYMBOL, dfs.getPercent());
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_PERMILL_SYMBOL, dfs.getPerMill());
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_ZERO_DIGIT_SYMBOL, dfs.getZeroDigit());
}
private BigDecimal applyMultiplier(BigDecimal valBigDecimal) {
@@ -132,7 +170,6 @@ public class DecimalFormat extends NumberFormat {
return valBigDecimal.multiply(multiplierBigDecimal);
}
- @Override
public StringBuffer format(Object value, StringBuffer buffer, FieldPosition field) {
if (!(value instanceof Number)) {
throw new IllegalArgumentException();
@@ -170,7 +207,6 @@ public class DecimalFormat extends NumberFormat {
}
}
- @Override
public StringBuffer format(long value, StringBuffer buffer, FieldPosition field) {
if (buffer == null || field == null) {
throw new NullPointerException();
@@ -180,7 +216,6 @@ public class DecimalFormat extends NumberFormat {
return buffer;
}
- @Override
public StringBuffer format(double value, StringBuffer buffer, FieldPosition field) {
if (buffer == null || field == null) {
throw new NullPointerException();
@@ -191,30 +226,13 @@ public class DecimalFormat extends NumberFormat {
}
public void applyLocalizedPattern(String pattern) {
- if (pattern == null) {
- throw new NullPointerException("pattern was null");
- }
- try {
- NativeDecimalFormat.applyPatternImpl(this.addr, false, pattern);
- } catch(RuntimeException re) {
- throw new IllegalArgumentException(
- "applying localized pattern failed for pattern: " + pattern, re);
- }
+ NativeDecimalFormat.applyPattern(this.addr, true, pattern);
}
public void applyPattern(String pattern) {
- if (pattern == null) {
- throw new NullPointerException("pattern was null");
- }
- try {
- NativeDecimalFormat.applyPatternImpl(this.addr, false, pattern);
- } catch(RuntimeException re) {
- throw new IllegalArgumentException(
- "applying pattern failed for pattern: " + pattern, re);
- }
+ NativeDecimalFormat.applyPattern(this.addr, false, pattern);
}
- @Override
public AttributedCharacterIterator formatToCharacterIterator(Object object) {
if (!(object instanceof Number)) {
throw new IllegalArgumentException();
@@ -283,40 +301,38 @@ public class DecimalFormat extends NumberFormat {
return NativeDecimalFormat.toPatternImpl(this.addr, false);
}
- @Override
public Number parse(String string, ParsePosition position) {
return NativeDecimalFormat.parse(addr, string, position);
}
// start getter and setter
- @Override
public int getMaximumFractionDigits() {
- return NativeDecimalFormat.getAttribute(this .addr,
+ return NativeDecimalFormat.getAttribute(this.addr,
UNumberFormatAttribute.UNUM_MAX_FRACTION_DIGITS.ordinal());
}
- @Override
public int getMaximumIntegerDigits() {
- return NativeDecimalFormat.getAttribute(this .addr,
+ return NativeDecimalFormat.getAttribute(this.addr,
UNumberFormatAttribute.UNUM_MAX_INTEGER_DIGITS.ordinal());
}
- @Override
public int getMinimumFractionDigits() {
- return NativeDecimalFormat.getAttribute(this .addr,
+ return NativeDecimalFormat.getAttribute(this.addr,
UNumberFormatAttribute.UNUM_MIN_FRACTION_DIGITS.ordinal());
}
- @Override
public int getMinimumIntegerDigits() {
- return NativeDecimalFormat.getAttribute(this .addr,
+ return NativeDecimalFormat.getAttribute(this.addr,
UNumberFormatAttribute.UNUM_MIN_INTEGER_DIGITS.ordinal());
}
- @Override
public Currency getCurrency() {
- return this.symbols.getCurrency();
+ String curr = NativeDecimalFormat.getSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL);
+ if (curr.equals("") || curr.equals("\u00a4\u00a4")) {
+ return null;
+ }
+ return Currency.getInstance(curr);
}
public int getGroupingSize() {
@@ -366,35 +382,25 @@ public class DecimalFormat extends NumberFormat {
UNumberFormatAttribute.UNUM_DECIMAL_ALWAYS_SHOWN.ordinal()) != 0;
}
- @Override
public boolean isParseIntegerOnly() {
return NativeDecimalFormat.getAttribute(this.addr,
UNumberFormatAttribute.UNUM_PARSE_INT_ONLY.ordinal()) != 0;
}
- @Override
public boolean isGroupingUsed() {
return NativeDecimalFormat.getAttribute(this.addr,
UNumberFormatAttribute.UNUM_GROUPING_USED.ordinal()) != 0;
}
- public DecimalFormatSymbols getDecimalFormatSymbols() {
- return this.symbols;
- }
-
- public void setDecimalFormatSymbols(DecimalFormatSymbols icuSymbols) {
- this.symbols = icuSymbols;
- }
-
public void setDecimalSeparatorAlwaysShown(boolean value) {
int i = value ? -1 : 0;
NativeDecimalFormat.setAttribute(this.addr,
UNumberFormatAttribute.UNUM_DECIMAL_ALWAYS_SHOWN.ordinal(), i);
}
- @Override
public void setCurrency(Currency currency) {
- this.symbols.setCurrency(currency);
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_CURRENCY_SYMBOL, currency.getSymbol());
+ NativeDecimalFormat.setSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL, currency.getCurrencyCode());
}
public void setGroupingSize(int value) {
@@ -402,32 +408,27 @@ public class DecimalFormat extends NumberFormat {
UNumberFormatAttribute.UNUM_GROUPING_SIZE.ordinal(), value);
}
- @Override
public void setGroupingUsed(boolean value) {
int i = value ? -1 : 0;
NativeDecimalFormat.setAttribute(this.addr,
UNumberFormatAttribute.UNUM_GROUPING_USED.ordinal(), i);
}
- @Override
public void setMaximumFractionDigits(int value) {
NativeDecimalFormat.setAttribute(this.addr,
UNumberFormatAttribute.UNUM_MAX_FRACTION_DIGITS.ordinal(), value);
}
- @Override
public void setMaximumIntegerDigits(int value) {
NativeDecimalFormat.setAttribute(this.addr,
UNumberFormatAttribute.UNUM_MAX_INTEGER_DIGITS.ordinal(), value);
}
- @Override
public void setMinimumFractionDigits(int value) {
NativeDecimalFormat.setAttribute(this.addr,
UNumberFormatAttribute.UNUM_MIN_FRACTION_DIGITS.ordinal(), value);
}
- @Override
public void setMinimumIntegerDigits(int value) {
NativeDecimalFormat.setAttribute(this.addr,
UNumberFormatAttribute.UNUM_MIN_INTEGER_DIGITS.ordinal(), value);
@@ -476,7 +477,6 @@ public class DecimalFormat extends NumberFormat {
}
}
- @Override
public void setParseIntegerOnly(boolean value) {
int i = value ? -1 : 0;
NativeDecimalFormat.setAttribute(this.addr,
diff --git a/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java b/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
deleted file mode 100644
index 2d5ae02..0000000
--- a/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2008 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.text;
-
-import com.ibm.icu4jni.util.LocaleData;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Currency;
-import java.util.Locale;
-import java.util.ResourceBundle;
-
-public class DecimalFormatSymbols implements Cloneable {
-
- // Constants corresponding to the native type UNumberFormatSymbol, for use with getSymbol/setSymbol.
- private static final int UNUM_DECIMAL_SEPARATOR_SYMBOL = 0;
- private static final int UNUM_GROUPING_SEPARATOR_SYMBOL = 1;
- private static final int UNUM_PATTERN_SEPARATOR_SYMBOL = 2;
- private static final int UNUM_PERCENT_SYMBOL = 3;
- private static final int UNUM_ZERO_DIGIT_SYMBOL = 4;
- private static final int UNUM_DIGIT_SYMBOL = 5;
- private static final int UNUM_MINUS_SIGN_SYMBOL = 6;
- private static final int UNUM_PLUS_SIGN_SYMBOL = 7;
- private static final int UNUM_CURRENCY_SYMBOL = 8;
- private static final int UNUM_INTL_CURRENCY_SYMBOL = 9;
- private static final int UNUM_MONETARY_SEPARATOR_SYMBOL = 10;
- private static final int UNUM_EXPONENTIAL_SYMBOL = 11;
- private static final int UNUM_PERMILL_SYMBOL = 12;
- private static final int UNUM_PAD_ESCAPE_SYMBOL = 13;
- private static final int UNUM_INFINITY_SYMBOL = 14;
- private static final int UNUM_NAN_SYMBOL = 15;
- private static final int UNUM_SIGNIFICANT_DIGIT_SYMBOL = 16;
- private static final int UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL = 17;
- private static final int UNUM_FORMAT_SYMBOL_COUNT = 18;
-
- private final int addr;
-
- // Used to implement clone.
- private DecimalFormatSymbols(DecimalFormatSymbols other) {
- this.addr = NativeDecimalFormat.cloneImpl(other.addr);
- }
-
- public DecimalFormatSymbols(Locale locale) {
- LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
- this.addr = NativeDecimalFormat.openDecimalFormatImpl(locale.toString(),
- localeData.numberPattern);
- NativeDecimalFormat.setSymbol(this.addr, UNUM_CURRENCY_SYMBOL, localeData.currencySymbol);
- NativeDecimalFormat.setSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL,
- localeData.internationalCurrencySymbol);
- }
-
- public DecimalFormatSymbols(Locale locale, java.text.DecimalFormatSymbols symbols) {
- LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(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) {
- 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) {
- return false;
- }
- if(!(object instanceof DecimalFormatSymbols)) {
- return false;
- }
-
- DecimalFormatSymbols sym = (DecimalFormatSymbols) object;
-
- if(sym.addr == this.addr) {
- return true;
- }
-
- boolean result = true;
-
- Currency objCurr = sym.getCurrency();
- Currency thisCurr = this.getCurrency();
- if(objCurr != null) {
- result &= objCurr.getCurrencyCode().equals(thisCurr.getCurrencyCode());
- result &= objCurr.getSymbol().equals(thisCurr.getSymbol());
- result &= objCurr.getDefaultFractionDigits() == thisCurr.getDefaultFractionDigits();
- } else {
- result &= thisCurr == null;
- }
- result &= sym.getCurrencySymbol().equals(this.getCurrencySymbol());
- result &= sym.getDecimalSeparator() == this.getDecimalSeparator();
- result &= sym.getDigit() == this.getDigit();
- result &= sym.getGroupingSeparator() == this.getGroupingSeparator();
- result &= sym.getInfinity().equals(this.getInfinity());
- result &= sym.getInternationalCurrencySymbol().equals(
- this.getInternationalCurrencySymbol());
- result &= sym.getMinusSign() == this.getMinusSign();
- result &= sym.getMonetaryDecimalSeparator() ==
- this.getMonetaryDecimalSeparator();
- result &= sym.getNaN().equals(this.getNaN());
- result &= sym.getPatternSeparator() == this.getPatternSeparator();
- result &= sym.getPercent() == this.getPercent();
- result &= sym.getPerMill() == this.getPerMill();
- result &= sym.getZeroDigit() == this.getZeroDigit();
-
- return result;
- }
-
- @Override
- public Object clone() {
- return new DecimalFormatSymbols(this);
- }
-
- public void setCurrency(Currency currency) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_CURRENCY_SYMBOL, currency.getSymbol());
- NativeDecimalFormat.setSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL,
- currency.getCurrencyCode());
- }
-
- public void setCurrencySymbol(String symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_CURRENCY_SYMBOL, symbol);
- }
-
- public void setDecimalSeparator(char symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_DECIMAL_SEPARATOR_SYMBOL, symbol);
- }
-
- public void setDigit(char symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_DIGIT_SYMBOL, symbol);
- }
-
- public void setGroupingSeparator(char symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_GROUPING_SEPARATOR_SYMBOL, symbol);
- NativeDecimalFormat.setSymbol(this.addr, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, symbol);
- }
-
- public void setInfinity(String symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_INFINITY_SYMBOL, symbol);
- }
-
- public void setInternationalCurrencySymbol(String symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL, symbol);
- }
-
- public void setMinusSign(char symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_MINUS_SIGN_SYMBOL, symbol);
- }
-
- public void setMonetaryDecimalSeparator(char symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_MONETARY_SEPARATOR_SYMBOL, symbol);
- }
-
- public void setNaN(String symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_NAN_SYMBOL, symbol);
- }
-
- public void setPatternSeparator(char symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_PATTERN_SEPARATOR_SYMBOL, symbol);
- }
-
- public void setPercent(char symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_PERCENT_SYMBOL, symbol);
- }
-
- public void setPerMill(char symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_PERMILL_SYMBOL, symbol);
- }
-
- public void setZeroDigit(char symbol) {
- NativeDecimalFormat.setSymbol(this.addr, UNUM_ZERO_DIGIT_SYMBOL, symbol);
- }
-
- public Currency getCurrency() {
- String curr = NativeDecimalFormat.getSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL);
- if (curr.equals("") || curr.equals("\u00a4\u00a4")) {
- return null;
- }
- return Currency.getInstance(curr);
- }
-
- public String getCurrencySymbol() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_CURRENCY_SYMBOL);
- }
-
- public char getDecimalSeparator() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_DECIMAL_SEPARATOR_SYMBOL).charAt(0);
- }
-
- public char getDigit() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_DIGIT_SYMBOL).charAt(0);
- }
-
- public char getGroupingSeparator() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_GROUPING_SEPARATOR_SYMBOL).charAt(0);
- }
-
- public String getInfinity() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_INFINITY_SYMBOL);
- }
-
- public String getInternationalCurrencySymbol() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_INTL_CURRENCY_SYMBOL);
- }
-
- public char getMinusSign() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_MINUS_SIGN_SYMBOL).charAt(0);
- }
-
- public char getMonetaryDecimalSeparator() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_MONETARY_SEPARATOR_SYMBOL).charAt(0);
- }
-
- public String getNaN() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_NAN_SYMBOL);
- }
-
- public char getPatternSeparator() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_PATTERN_SEPARATOR_SYMBOL).charAt(0);
- }
-
- public char getPercent() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_PERCENT_SYMBOL).charAt(0);
- }
-
- public char getPerMill() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_PERMILL_SYMBOL).charAt(0);
- }
-
- public char getZeroDigit() {
- return NativeDecimalFormat.getSymbol(this.addr, UNUM_ZERO_DIGIT_SYMBOL).charAt(0);
- }
-
- int getAddr() {
- return this.addr;
- }
-
- protected void finalize() {
- NativeDecimalFormat.closeDecimalFormatImpl(this.addr);
- }
-}
diff --git a/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java b/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java
index 88e0d5f..ec07fbd 100644
--- a/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java
+++ b/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java
@@ -55,15 +55,26 @@ final class NativeDecimalFormat {
UNUM_PUBLIC_RULESETS
}
- static native int openDecimalFormatImpl(String locale, String pattern);
+ static int openDecimalFormat(String locale, String pattern) {
+ try {
+ // FIXME: if we're about to override everything, should we just ask for the cheapest locale (presumably the root locale)?
+ return NativeDecimalFormat.openDecimalFormatImpl(locale, pattern);
+ } catch (NullPointerException npe) {
+ throw npe;
+ } catch (RuntimeException re) {
+ throw new IllegalArgumentException("syntax error: " + re.getMessage() + ": " + pattern);
+ }
+ }
+ private static native int openDecimalFormatImpl(String locale, String pattern);
static native void closeDecimalFormatImpl(int addr);
- static native int cloneImpl(int addr);
+ static native int cloneDecimalFormatImpl(int addr);
static native void setSymbol(int addr, int symbol, String str);
static native void setSymbol(int addr, int symbol, char ch);
+ // FIXME: do we need this any more? the Java-side object should be the canonical source.
static native String getSymbol(int addr, int symbol);
static native void setAttribute(int addr, int symbol, int i);
@@ -74,7 +85,16 @@ final class NativeDecimalFormat {
static native String getTextAttribute(int addr, int symbol);
- static native void applyPatternImpl(int addr, boolean localized, String pattern);
+ static void applyPattern(int addr, boolean localized, String pattern) {
+ try {
+ NativeDecimalFormat.applyPatternImpl(addr, localized, pattern);
+ } catch (NullPointerException npe) {
+ throw npe;
+ } catch (RuntimeException re) {
+ throw new IllegalArgumentException("syntax error: " + re.getMessage() + ": " + pattern);
+ }
+ }
+ private static native void applyPatternImpl(int addr, boolean localized, String pattern);
static native String toPatternImpl(int addr, boolean localized);
diff --git a/icu/src/main/native/NativeDecimalFormat.cpp b/icu/src/main/native/NativeDecimalFormat.cpp
index cde2001..e974521 100644
--- a/icu/src/main/native/NativeDecimalFormat.cpp
+++ b/icu/src/main/native/NativeDecimalFormat.cpp
@@ -14,8 +14,10 @@
* limitations under the License.
*/
+#define LOG_TAG "NativeDecimalFormat"
#include "JNIHelp.h"
#include "AndroidSystemNatives.h"
+#include "cutils/log.h"
#include "unicode/unum.h"
#include "unicode/numfmt.h"
#include "unicode/decimfmt.h"
@@ -26,14 +28,20 @@
#include <stdlib.h>
#include <string.h>
-#define LOG_TAG "NativeDecimalFormat"
-#include "cutils/log.h"
+// FIXME: move to JNIHelp.h
+static void jniThrowNullPointerException(JNIEnv* env) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+}
-static jint openDecimalFormatImpl(JNIEnv *env, jclass clazz, jstring locale,
- jstring pattern) {
+DecimalFormat* toDecimalFormat(jint addr) {
+ return reinterpret_cast<DecimalFormat*>(static_cast<uintptr_t>(addr));
+}
- // the errorcode returned by unum_open
- UErrorCode status = U_ZERO_ERROR;
+static jint openDecimalFormatImpl(JNIEnv* env, jclass clazz, jstring locale, jstring pattern) {
+ if (pattern == NULL) {
+ jniThrowNullPointerException(env);
+ return 0;
+ }
// prepare the pattern string for the call to unum_open
const UChar *pattChars = env->GetStringChars(pattern, NULL);
@@ -43,6 +51,7 @@ static jint openDecimalFormatImpl(JNIEnv *env, jclass clazz, jstring locale,
const char *localeChars = env->GetStringUTFChars(locale, NULL);
// open a default type number format
+ UErrorCode status = U_ZERO_ERROR;
UNumberFormat *fmt = unum_open(UNUM_PATTERN_DECIMAL, pattChars, pattLen,
localeChars, NULL, &status);
@@ -50,13 +59,8 @@ static jint openDecimalFormatImpl(JNIEnv *env, jclass clazz, jstring locale,
env->ReleaseStringChars(pattern, pattChars);
env->ReleaseStringUTFChars(locale, localeChars);
- // check for an error
- if (icu4jni_error(env, status) != FALSE) {
- return 0;
- }
-
- // return the handle to the number format
- return (long) fmt;
+ icu4jni_error(env, status);
+ return static_cast<jint>(reinterpret_cast<uintptr_t>(fmt));
}
static void closeDecimalFormatImpl(JNIEnv *env, jclass clazz, jint addr) {
@@ -71,7 +75,7 @@ static void closeDecimalFormatImpl(JNIEnv *env, jclass clazz, jint addr) {
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);
+ UNumberFormat* fmt = reinterpret_cast<UNumberFormat*>(static_cast<uintptr_t>(addr));
unum_setSymbol(fmt, static_cast<UNumberFormatSymbol>(symbol),
chars, charCount, &status);
icu4jni_error(env, status);
@@ -199,59 +203,29 @@ static jstring getTextAttribute(JNIEnv *env, jclass clazz, jint addr,
return res;
}
-static void applyPatternImpl(JNIEnv *env, jclass clazz, jint addr,
- jboolean localized, jstring pattern) {
-
- // the errorcode returned by unum_applyPattern
+static void applyPatternImpl(JNIEnv *env, jclass clazz, jint addr, jboolean localized, jstring pattern) {
+ if (pattern == NULL) {
+ jniThrowNullPointerException(env);
+ return;
+ }
+ UNumberFormat* fmt = reinterpret_cast<UNumberFormat*>(static_cast<uintptr_t>(addr));
+ const UChar* chars = env->GetStringChars(pattern, NULL);
+ jsize charCount = env->GetStringLength(pattern);
UErrorCode status = U_ZERO_ERROR;
-
- // get the pointer to the number format
- UNumberFormat *fmt = (UNumberFormat *)(int)addr;
-
- const UChar *pattChars = env->GetStringChars(pattern, NULL);
- int pattLen = env->GetStringLength(pattern);
-
- unum_applyPattern(fmt, localized, pattChars, pattLen, NULL, &status);
-
- env->ReleaseStringChars(pattern, pattChars);
-
+ unum_applyPattern(fmt, localized, chars, charCount, NULL, &status);
+ env->ReleaseStringChars(pattern, chars);
icu4jni_error(env, status);
}
-static jstring toPatternImpl(JNIEnv *env, jclass clazz, jint addr,
- jboolean localized) {
-
- uint32_t resultlength, reslenneeded;
-
- // the errorcode returned by unum_toPattern
- UErrorCode status = U_ZERO_ERROR;
-
- // get the pointer to the number format
- UNumberFormat *fmt = (UNumberFormat *)(int)addr;
-
- UChar* result = NULL;
- resultlength=0;
-
- // find out how long the result will be
- reslenneeded=unum_toPattern(fmt, localized, result, resultlength, &status);
-
- result = NULL;
- if(status==U_BUFFER_OVERFLOW_ERROR) {
- status=U_ZERO_ERROR;
- resultlength=reslenneeded+1;
- result=(UChar*)malloc(sizeof(UChar) * resultlength);
- reslenneeded=unum_toPattern(fmt, localized, result, resultlength,
- &status);
- }
- if (icu4jni_error(env, status) != FALSE) {
- return NULL;
+static jstring toPatternImpl(JNIEnv *env, jclass, jint addr, jboolean localized) {
+ DecimalFormat* fmt = toDecimalFormat(addr);
+ UnicodeString pattern;
+ if (localized) {
+ fmt->toLocalizedPattern(pattern);
+ } else {
+ fmt->toPattern(pattern);
}
-
- jstring res = env->NewString(result, reslenneeded);
-
- free(result);
-
- return res;
+ return env->NewString(pattern.getBuffer(), pattern.length());
}
template <typename T>
@@ -274,7 +248,7 @@ static jstring format(JNIEnv *env, jint addr, jobject field, jstring fieldType,
fp.setField(FieldPosition::DONT_CARE);
UnicodeString str;
- DecimalFormat* fmt = reinterpret_cast<DecimalFormat*>(static_cast<uintptr_t>(addr));
+ DecimalFormat* fmt = toDecimalFormat(addr);
fmt->format(val, str, fp, attrBufferPtr);
if (attrBufferPtr && strlen(attrBuffer.buffer) > 0) {
@@ -314,8 +288,7 @@ static jstring format(JNIEnv *env, jint addr, jobject field, jstring fieldType,
}
}
- const UChar* chars = str.getBuffer();
- jstring result = env->NewString(chars, str.length());
+ jstring result = env->NewString(str.getBuffer(), str.length());
delete[] attrBuffer.buffer;
return result;
}
@@ -362,7 +335,7 @@ static jstring formatDigitList(JNIEnv *env, jclass clazz, jint addr, jstring val
const char *digits = (isPositive ? valueChars : valueChars + 1);
int length = strlen(digits);
- DecimalFormat* fmt = reinterpret_cast<DecimalFormat*>(static_cast<uintptr_t>(addr));
+ DecimalFormat* fmt = toDecimalFormat(addr);
// The length of our digit list buffer must be the actual string length + 3,
// because ICU will append some additional characters at the head and at the
@@ -609,20 +582,9 @@ static jobject parse(JNIEnv *env, jclass clazz, jint addr, jstring text,
}
}
-static jint cloneImpl(JNIEnv *env, jclass clazz, jint addr) {
-
- UErrorCode status = U_ZERO_ERROR;
-
- UNumberFormat *fmt = (UNumberFormat *)(int)addr;
-
- UNumberFormat *result = unum_clone(fmt, &status);
-
- if(icu4jni_error(env, status) != FALSE) {
- return 0;
- }
-
- return (long) result;
-
+static jint cloneDecimalFormatImpl(JNIEnv *env, jclass, jint addr) {
+ DecimalFormat* fmt = toDecimalFormat(addr);
+ return static_cast<jint>(reinterpret_cast<uintptr_t>(fmt->clone()));
}
static JNINativeMethod gMethods[] = {
@@ -651,7 +613,7 @@ static JNINativeMethod gMethods[] = {
{"parse",
"(ILjava/lang/String;Ljava/text/ParsePosition;)Ljava/lang/Number;",
(void*) parse},
- {"cloneImpl", "(I)I", (void*) cloneImpl}
+ {"cloneDecimalFormatImpl", "(I)I", (void*) cloneDecimalFormatImpl}
};
int register_com_ibm_icu4jni_text_NativeDecimalFormat(JNIEnv* env) {
return jniRegisterNativeMethods(env,
diff --git a/icu/src/main/native/Resources.cpp b/icu/src/main/native/Resources.cpp
index 0df2859..00bf746 100644
--- a/icu/src/main/native/Resources.cpp
+++ b/icu/src/main/native/Resources.cpp
@@ -14,8 +14,10 @@
* limitations under the License.
*/
+#define LOG_TAG "Resources"
#include "JNIHelp.h"
#include "AndroidSystemNatives.h"
+#include "cutils/log.h"
#include "unicode/numfmt.h"
#include "unicode/locid.h"
#include "unicode/ucal.h"
@@ -37,9 +39,6 @@
#include <time.h>
#include <sys/time.h>
-#define LOG_TAG "Resources"
-#include "cutils/log.h"
-
static jclass string_class;
class ScopedResourceBundle {