Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/payments/CurrencyStringFormatter.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/CurrencyStringFormatter.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/CurrencyStringFormatter.java |
| index 693bc0344b742c9794ad17fe36721f4bc8b314cb..4264224b4db573fdc749d57a4f3d06adc1c1e0a3 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/CurrencyStringFormatter.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/CurrencyStringFormatter.java |
| @@ -4,22 +4,19 @@ |
| package org.chromium.chrome.browser.payments; |
| -import java.text.DecimalFormatSymbols; |
| -import java.util.Currency; |
| +import org.chromium.base.annotations.JNINamespace; |
| + |
| import java.util.Locale; |
| -import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| /** |
| - * Formatter for currency strings that can be too large to parse into numbers. |
| + * Formatter for currency amounts. |
| * https://w3c.github.io/browser-payment-api/specs/paymentrequest.html#currencyamount |
| */ |
| +@JNINamespace("payments") |
| public class CurrencyStringFormatter { |
| - // Amount value pattern and capture group numbers. |
| + // Amount value pattern. |
| private static final String AMOUNT_VALUE_PATTERN = "^(-?)([0-9]+)(\\.([0-9]+))?$"; |
| - private static final int OPTIONAL_NEGATIVE_GROUP = 1; |
| - private static final int DIGITS_BETWEEN_NEGATIVE_AND_PERIOD_GROUP = 2; |
| - private static final int DIGITS_AFTER_PERIOD_GROUP = 4; |
| // Max currency code length. Maximum length of currency code can be at most 2048. |
| private static final int MAX_CURRENCY_CODE_LEN = 2048; |
| @@ -30,11 +27,6 @@ public class CurrencyStringFormatter { |
| // Unicode character for ellipsis. |
| private static final String ELLIPSIS = "\u2026"; |
| - // Formatting constants. |
| - private static final int DIGIT_GROUPING_SIZE = 3; |
| - |
| - private final Pattern mAmountValuePattern; |
| - |
| /** |
| * The currency formatted for display. Currency can be any string of at most |
| * 2048 characters.Currency code more than 6 character is formatted to first |
| @@ -43,79 +35,35 @@ public class CurrencyStringFormatter { |
| public final String mFormattedCurrencyCode; |
| /** |
| - * The symbol for the currency specified on the bill. For example, the symbol for "USD" is "$". |
| - */ |
| - private final String mCurrencySymbol; |
| - |
| - /** |
| - * The number of digits after the decimal separator for the currency specified on the bill. For |
| - * example, 2 for "USD" and 0 for "JPY". |
| - */ |
| - private final int mDefaultFractionDigits; |
| - |
| - /** |
| - * The number grouping separator for the current locale. For example, "," in US. 3-digit groups |
| - * are assumed. |
| + * Pointer to the native implementation. |
| */ |
| - private final char mGroupingSeparator; |
| + private final long mCurrencyFormatterAndroid; |
| - /** |
| - * The monetary decimal separator for the current locale. For example, "." in US and "," in |
| - * France. |
| - */ |
| - private final char mMonetaryDecimalSeparator; |
| + private final Pattern mAmountValuePattern; |
|
please use gerrit instead
2017/01/13 21:16:25
No longer used in this file, so can be deleted.
Mathieu
2017/01/13 22:27:01
Done.
|
| /** |
| * Builds the formatter for the given currency code and the current user locale. |
| * |
| - * @param currencyCode The currency code. Most commonly, this follows ISO 4217 format: 3 upper |
| - * case ASCII letters. For example, "USD". Format is not restricted. Should |
| - * not be null. |
| + * @param currencyCode The currency code. Most commonly, this follows ISO 4217 format: 3 upper |
| + * case ASCII letters. For example, "USD". Format is not restricted. Should |
| + * not be null. |
| + * @param currencySystem URI specifying the ISO4217 currency code specification. See for |
| + * details: https://w3c.github.io/browser-payment-api/#paymentcurrencyamount-dictionary |
| + * Can be null, in which case "urn:iso:std:iso:4217" is assumed. |
| * @param userLocale User's current locale. Should not be null. |
| */ |
| - public CurrencyStringFormatter(String currencyCode, Locale userLocale) { |
| + public CurrencyStringFormatter(String currencyCode, String currencySystem, Locale userLocale) { |
|
please use gerrit instead
2017/01/13 21:16:24
@Nullable String currencySystem.
Mathieu
2017/01/13 22:27:01
Done.
|
| assert currencyCode != null : "currencyCode should not be null"; |
| assert userLocale != null : "userLocale should not be null"; |
| - mAmountValuePattern = Pattern.compile(AMOUNT_VALUE_PATTERN); |
| + // Note that this technically leaks the native object. |
|
please use gerrit instead
2017/01/13 21:16:25
Is there a remedy for the leak?
Mathieu
2017/01/13 22:27:01
added destroy() (Calling nativeDestroy() which cal
|
| + mCurrencyFormatterAndroid = nativeInitCurrencyFormatterAndroid( |
| + currencyCode, currencySystem == null ? "" : currencySystem, userLocale.toString()); |
| + mAmountValuePattern = Pattern.compile(AMOUNT_VALUE_PATTERN); |
| mFormattedCurrencyCode = currencyCode.length() <= MAX_CURRENCY_CHARS |
|
please use gerrit instead
2017/01/13 21:16:25
Can we similarly format the currency code in C++?
Mathieu
2017/01/13 22:27:01
Sure thing, done
|
| ? currencyCode |
| : currencyCode.substring(0, MAX_CURRENCY_CHARS - 1) + ELLIPSIS; |
| - |
| - String currencySymbol; |
| - int defaultFractionDigits; |
| - try { |
| - Currency currency = Currency.getInstance(currencyCode); |
| - currencySymbol = currency.getSymbol(); |
| - defaultFractionDigits = currency.getDefaultFractionDigits(); |
| - } catch (IllegalArgumentException e) { |
| - // The spec does not limit the currencies to official ISO 4217 currency code list, which |
| - // is used by java.util.Currency. For example, "BTX" (bitcoin) is not an official ISO |
| - // 4217 currency code, but is allowed by the spec. |
| - currencySymbol = ""; |
| - defaultFractionDigits = 0; |
| - } |
| - |
| - // If the prefix of the currency symbol matches the prefix of the currency code, remove the |
| - // matching prefix from the symbol. The UI already shows the currency code, so there's no |
| - // need to show duplicate information. |
| - String symbol = ""; |
| - for (int i = 0; i < currencySymbol.length(); i++) { |
| - if (i >= currencyCode.length() || currencySymbol.charAt(i) != currencyCode.charAt(i)) { |
| - symbol = currencySymbol.substring(i); |
| - break; |
| - } |
| - } |
| - mCurrencySymbol = symbol; |
| - |
| - mDefaultFractionDigits = defaultFractionDigits; |
| - |
| - // Use the symbols from user's current locale. For example, use "," for decimal separator in |
| - // France, even if paying in "USD". |
| - DecimalFormatSymbols symbols = new DecimalFormatSymbols(userLocale); |
| - mGroupingSeparator = symbols.getGroupingSeparator(); |
| - mMonetaryDecimalSeparator = symbols.getMonetaryDecimalSeparator(); |
| } |
| /** |
| @@ -145,44 +93,22 @@ public class CurrencyStringFormatter { |
| /** |
| * Formats the currency string for display. Does not parse the string into a number, because it |
| - * might be too large. The number is formatted for the current locale and follows the symbol of |
| - * the currency code. |
| + * might be too large. The number is formatted for the current locale and can include a |
| + * currency symbol (e.g. $) anywhere in the string, but will not contain the currency code |
| + * (e.g. USD/US). All spaces in the currency are unicode non-breaking space. |
| * |
| * @param amountValue The number to format. Should be in "^-?[0-9]+(\.[0-9]+)?$" format. Should |
| * not be null. |
| - * @return The currency symbol followed by a space and the formatted number. |
| + * @return The amount formatted with the specified currency. See description for details. |
| */ |
| public String format(String amountValue) { |
| assert amountValue != null : "amountValue should not be null"; |
| - Matcher m = mAmountValuePattern.matcher(amountValue); |
| - |
| - // Required to capture the groups. |
| - boolean matches = m.matches(); |
| - assert matches; |
| - |
| - StringBuilder result = new StringBuilder(m.group(OPTIONAL_NEGATIVE_GROUP)); |
| - result.append(mCurrencySymbol); |
| - int digitStart = result.length(); |
| - |
| - result.append(m.group(DIGITS_BETWEEN_NEGATIVE_AND_PERIOD_GROUP)); |
| - for (int i = result.length() - DIGIT_GROUPING_SIZE; i > digitStart; |
| - i -= DIGIT_GROUPING_SIZE) { |
| - result.insert(i, mGroupingSeparator); |
| - } |
| - |
| - String decimals = m.group(DIGITS_AFTER_PERIOD_GROUP); |
| - int numberOfDecimals = decimals == null ? 0 : decimals.length(); |
| - |
| - if (numberOfDecimals > 0 || mDefaultFractionDigits > 0) { |
| - result.append(mMonetaryDecimalSeparator); |
| - if (null != decimals) result.append(decimals); |
| - |
| - for (int i = numberOfDecimals; i < mDefaultFractionDigits; i++) { |
| - result.append("0"); |
| - } |
| - } |
| - |
| - return result.toString(); |
| + return nativeFormat(mCurrencyFormatterAndroid, amountValue); |
| } |
| + |
| + private native long nativeInitCurrencyFormatterAndroid( |
| + String currencyCode, String currencySystem, String localeName); |
| + private native String nativeFormat( |
| + long nativeCurrencyFormatterAndroid, String amountValue); |
| } |