]> granicus.if.org Git - icu/commitdiff
ICU-13177 Merging trunk to branch
authorShane Carr <shane@unicode.org>
Tue, 13 Jun 2017 20:42:33 +0000 (20:42 +0000)
committerShane Carr <shane@unicode.org>
Tue, 13 Jun 2017 20:42:33 +0000 (20:42 +0000)
X-SVN-Rev: 40168

1  2 
icu4c/source/i18n/nfrs.cpp
icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PositiveDecimalFormat.java
icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java
icu4j/main/classes/core/src/com/ibm/icu/text/Normalizer.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java

index 05941e8b2934b63c54f5c23902eb59f46fbabc26,05941e8b2934b63c54f5c23902eb59f46fbabc26..ea4a05d749d1c4841c4fb6dac0e0896995183fc2
@@@ -24,6 -24,6 +24,7 @@@
  #include "nfrlist.h"
  #include "patternprops.h"
  #include "putilimp.h"
++#include "uassert.h"
  
  #ifdef RBNF_DEBUG
  #include "cmemory.h"
@@@ -836,11 -836,11 +837,18 @@@ int64_t util64_pow(int32_t base, uint16
      }
      int64_t result = 1;
      int64_t pow = base;
--    while (exponent > 0) { 
--        if ((exponent & 1) == 1) { 
++    UBool safe = TRUE;
++    while (exponent > 0) {
++        U_ASSERT(safe);
++        if ((exponent & 1) == 1) {
              result *= pow; 
          } 
--        pow *= pow; 
++        if (pow >= 0x100000000L) {
++            // The next step will push us out of bounds
++            safe = FALSE;
++        } else {
++            pow *= pow;
++        }
          exponent >>= 1; 
      } 
      return result;
index fdb26062f4c07b351373827605312db0f98f1ce1,b4a33dcc8ac17411772ee8a8835c9207498b7078..41a427f8d436df02a728fcb201fc02483348b835
@@@ -90,121 -90,133 +90,167 @@@ public class PositiveDecimalFormat impl
          || properties.getMaximumFractionDigits() != 0;
    }
  
--  // Properties
--  private final boolean alwaysShowDecimal;
--  private final int primaryGroupingSize;
--  private final int secondaryGroupingSize;
--  private final int minimumGroupingDigits;
--
--  // Symbols
--  private final String infinityString;
--  private final String nanString;
--  private final String groupingSeparator;
--  private final String decimalSeparator;
--  private final String[] digitStrings;
--  private final int codePointZero;
 -
 -  public PositiveDecimalFormat(DecimalFormatSymbols symbols, IProperties properties) {
 -    int _primary = properties.getGroupingSize();
 -    int _secondary = properties.getSecondaryGroupingSize();
 -    primaryGroupingSize = _primary > 0 ? _primary : _secondary > 0 ? _secondary : 0;
 -    secondaryGroupingSize = _secondary > 0 ? _secondary : primaryGroupingSize;
 -
 -    minimumGroupingDigits = properties.getMinimumGroupingDigits();
 -    alwaysShowDecimal = properties.getDecimalSeparatorAlwaysShown();
 -    infinityString = symbols.getInfinity();
 -    nanString = symbols.getNaN();
 -
 -    if (CurrencyFormat.useCurrency(properties)) {
 -      groupingSeparator = symbols.getMonetaryGroupingSeparatorString();
 -      decimalSeparator = symbols.getMonetaryDecimalSeparatorString();
 -    } else {
 -      groupingSeparator = symbols.getGroupingSeparatorString();
 -      decimalSeparator = symbols.getDecimalSeparatorString();
 -    }
++  private static class ParameterStruct {
++
++    // Properties
++    boolean alwaysShowDecimal;
++    int primaryGroupingSize;
++    int secondaryGroupingSize;
++    int minimumGroupingDigits;
++
++    // Symbols
++    String infinityString;
++    String nanString;
++    String groupingSeparator;
++    String decimalSeparator;
++    String[] digitStrings;
++    int codePointZero;
++
++    void setProperties(DecimalFormatSymbols symbols, IProperties properties) {
++      int _primary = properties.getGroupingSize();
++      int _secondary = properties.getSecondaryGroupingSize();
++      primaryGroupingSize = _primary > 0 ? _primary : _secondary > 0 ? _secondary : 0;
++      secondaryGroupingSize = _secondary > 0 ? _secondary : primaryGroupingSize;
++
++      minimumGroupingDigits = properties.getMinimumGroupingDigits();
++      alwaysShowDecimal = properties.getDecimalSeparatorAlwaysShown();
++      infinityString = symbols.getInfinity();
++      nanString = symbols.getNaN();
++
++      if (CurrencyFormat.useCurrency(properties)) {
++        groupingSeparator = symbols.getMonetaryGroupingSeparatorString();
++        decimalSeparator = symbols.getMonetaryDecimalSeparatorString();
++      } else {
++        groupingSeparator = symbols.getGroupingSeparatorString();
++        decimalSeparator = symbols.getDecimalSeparatorString();
++      }
  
-   public PositiveDecimalFormat(DecimalFormatSymbols symbols, IProperties properties) {
-     int _primary = properties.getGroupingSize();
-     int _secondary = properties.getSecondaryGroupingSize();
-     primaryGroupingSize = _primary > 0 ? _primary : _secondary > 0 ? _secondary : 0;
-     secondaryGroupingSize = _secondary > 0 ? _secondary : primaryGroupingSize;
-     minimumGroupingDigits = properties.getMinimumGroupingDigits();
-     alwaysShowDecimal = properties.getDecimalSeparatorAlwaysShown();
-     infinityString = symbols.getInfinity();
-     nanString = symbols.getNaN();
-     if (CurrencyFormat.useCurrency(properties)) {
-       groupingSeparator = symbols.getMonetaryGroupingSeparatorString();
-       decimalSeparator = symbols.getMonetaryDecimalSeparatorString();
-     } else {
-       groupingSeparator = symbols.getGroupingSeparatorString();
-       decimalSeparator = symbols.getDecimalSeparatorString();
 -    // Check to see if we can use code points instead of strings (~15% format performance boost)
 -    int _codePointZero = -1;
 -    String[] _digitStrings = symbols.getDigitStringsLocal();
 -    for (int i = 0; i < _digitStrings.length; i++) {
 -      int cp = Character.codePointAt(_digitStrings[i], 0);
 -      int cc = Character.charCount(cp);
 -      if (cc != _digitStrings[i].length()) {
 -        _codePointZero = -1;
 -        break;
 -      } else if (i == 0) {
 -        _codePointZero = cp;
 -      } else if (cp != _codePointZero + i) {
 -        _codePointZero = -1;
 -        break;
++      // Check to see if we can use code points instead of strings
++      int _codePointZero = symbols.getCodePointZero();
++      if (_codePointZero != -1) {
++        // Fast Path (9-25% faster than slow path when formatting long strings)
++        digitStrings = null;
++        codePointZero = _codePointZero;
++      } else {
++        // Slow Path
++        digitStrings = symbols.getDigitStrings(); // makes a copy
++        codePointZero = -1;
+       }
      }
 -    if (_codePointZero != -1) {
 -      digitStrings = null;
 -      codePointZero = _codePointZero;
 -    } else {
 -      digitStrings = symbols.getDigitStrings(); // makes a copy
 -      codePointZero = -1;
 -    }
+   }
  
-     // Check to see if we can use code points instead of strings
-     int _codePointZero = symbols.getCodePointZero();
-     if (_codePointZero != -1) {
-       // Fast Path (~9% faster than slow path when formatting long strings)
-       digitStrings = null;
-       codePointZero = _codePointZero;
-     } else {
-       // Slow Path
-       digitStrings = symbols.getDigitStrings(); // makes a copy
-       codePointZero = -1;
-     }
++  private static class TransientStruct {
++    FormatQuantity input;
++    NumberStringBuilder string;
++    int index;
++    ParameterStruct params;
++  }
++
++  private final ParameterStruct params;
++
++  public PositiveDecimalFormat(DecimalFormatSymbols symbols, IProperties properties) {
++    params = new ParameterStruct();
++    params.setProperties(symbols, properties);
 +  }
 +
++  //    private static void apply(
++  //        FormatQuantity input,
++  //        NumberStringBuilder string,
++  //        int startIndex,
++  //        DecimalFormatSymbols symbols,
++  //        IProperties properties) {
++  //
++  //    }
++
++  private static final ThreadLocal<TransientStruct> threadLocalTransientStruct =
++      new ThreadLocal<TransientStruct>() {
++        @Override
++        protected TransientStruct initialValue() {
++          return new TransientStruct();
++        }
++      };
++
++  private static final TransientStruct staticTransientStruct = new TransientStruct();
++
    @Override
    public int target(FormatQuantity input, NumberStringBuilder string, int startIndex) {
--    int length = 0;
++    //    TransientStruct trans = staticTransientStruct;
++    TransientStruct trans = threadLocalTransientStruct.get();
++    trans.input = input;
++    trans.string = string;
++    trans.index = startIndex;
++    trans.params = params;
++    target(trans);
++    return trans.index - startIndex;
++  }
  
--    if (input.isInfinite()) {
--      length += string.insert(startIndex, infinityString, NumberFormat.Field.INTEGER);
++  private static void target(TransientStruct trans) {
++    if (trans.input.isInfinite()) {
++      trans.index +=
++          trans.string.insert(trans.index, trans.params.infinityString, NumberFormat.Field.INTEGER);
  
--    } else if (input.isNaN()) {
--      length += string.insert(startIndex, nanString, NumberFormat.Field.INTEGER);
++    } else if (trans.input.isNaN()) {
++      trans.index +=
++          trans.string.insert(trans.index, trans.params.nanString, NumberFormat.Field.INTEGER);
  
      } else {
        // Add the integer digits
--      length += addIntegerDigits(input, string, startIndex);
++      trans.index += addIntegerDigits(trans);
  
        // Add the decimal point
--      if (input.getLowerDisplayMagnitude() < 0 || alwaysShowDecimal) {
--        length +=
--            string.insert(
--                startIndex + length, decimalSeparator, NumberFormat.Field.DECIMAL_SEPARATOR);
++      if (trans.input.getLowerDisplayMagnitude() < 0 || trans.params.alwaysShowDecimal) {
++        trans.index +=
++            trans.string.insert(
++                trans.index, trans.params.decimalSeparator, NumberFormat.Field.DECIMAL_SEPARATOR);
        }
  
        // Add the fraction digits
--      length += addFractionDigits(input, string, startIndex + length);
++      trans.index += addFractionDigits(trans);
      }
--
--    return length;
    }
  
--  private int addIntegerDigits(FormatQuantity input, NumberStringBuilder string, int startIndex) {
++  private static int addIntegerDigits(TransientStruct trans) {
      int length = 0;
--    int integerCount = input.getUpperDisplayMagnitude() + 1;
++    int integerCount = trans.input.getUpperDisplayMagnitude() + 1;
      for (int i = 0; i < integerCount; i++) {
        // Add grouping separator
--      if (primaryGroupingSize > 0
--          && i == primaryGroupingSize
--          && integerCount - i >= minimumGroupingDigits) {
++      if (trans.params.primaryGroupingSize > 0
++          && i == trans.params.primaryGroupingSize
++          && integerCount - i >= trans.params.minimumGroupingDigits) {
          length +=
--            string.insert(startIndex, groupingSeparator, NumberFormat.Field.GROUPING_SEPARATOR);
--      } else if (secondaryGroupingSize > 0
--          && i > primaryGroupingSize
--          && (i - primaryGroupingSize) % secondaryGroupingSize == 0) {
++            trans.string.insert(
++                trans.index, trans.params.groupingSeparator, NumberFormat.Field.GROUPING_SEPARATOR);
++      } else if (trans.params.secondaryGroupingSize > 0
++          && i > trans.params.primaryGroupingSize
++          && (i - trans.params.primaryGroupingSize) % trans.params.secondaryGroupingSize == 0) {
          length +=
--            string.insert(startIndex, groupingSeparator, NumberFormat.Field.GROUPING_SEPARATOR);
++            trans.string.insert(
++                trans.index, trans.params.groupingSeparator, NumberFormat.Field.GROUPING_SEPARATOR);
        }
  
        // Get and append the next digit value
--      byte nextDigit = input.getDigit(i);
--      length += addDigit(nextDigit, string, startIndex, NumberFormat.Field.INTEGER);
++      byte nextDigit = trans.input.getDigit(i);
++      length += addDigit(nextDigit, trans.index, NumberFormat.Field.INTEGER, trans);
      }
--
      return length;
    }
  
--  private int addFractionDigits(FormatQuantity input, NumberStringBuilder string, int index) {
++  private static int addFractionDigits(TransientStruct trans) {
      int length = 0;
--    int fractionCount = -input.getLowerDisplayMagnitude();
++    int fractionCount = -trans.input.getLowerDisplayMagnitude();
      for (int i = 0; i < fractionCount; i++) {
        // Get and append the next digit value
--      byte nextDigit = input.getDigit(-i - 1);
--      length += addDigit(nextDigit, string, index + length, NumberFormat.Field.FRACTION);
++      byte nextDigit = trans.input.getDigit(-i - 1);
++      length += addDigit(nextDigit, trans.index + length, NumberFormat.Field.FRACTION, trans);
      }
      return length;
    }
  
--  private int addDigit(byte digit, NumberStringBuilder outputString, int index, Field field) {
--    if (codePointZero != -1) {
--      return outputString.insertCodePoint(index, codePointZero + digit, field);
++  private static int addDigit(byte digit, int index, Field field, TransientStruct trans) {
++    if (trans.params.codePointZero != -1) {
++      return trans.string.insertCodePoint(index, trans.params.codePointZero + digit, field);
      } else {
--      return outputString.insert(index, digitStrings[digit], field);
++      return trans.string.insert(index, trans.params.digitStrings[digit], field);
      }
    }
  
    public void export(Properties properties) {
      // For backwards compatibility, export 0 as secondary grouping if primary and secondary are the same
      int effectiveSecondaryGroupingSize =
--        secondaryGroupingSize == primaryGroupingSize ? 0 : secondaryGroupingSize;
++        params.secondaryGroupingSize == params.primaryGroupingSize
++            ? 0
++            : params.secondaryGroupingSize;
  
--    properties.setDecimalSeparatorAlwaysShown(alwaysShowDecimal);
--    properties.setGroupingSize(primaryGroupingSize);
++    properties.setDecimalSeparatorAlwaysShown(params.alwaysShowDecimal);
++    properties.setGroupingSize(params.primaryGroupingSize);
      properties.setSecondaryGroupingSize(effectiveSecondaryGroupingSize);
--    properties.setMinimumGroupingDigits(minimumGroupingDigits);
++    properties.setMinimumGroupingDigits(params.minimumGroupingDigits);
    }
  }
index f4bd467ee6b6da60108cdf2e9d3b7585a5e9ee8e,f4bd467ee6b6da60108cdf2e9d3b7585a5e9ee8e..458baa67f196ae5b81eb33b0a2eb08fc57535d06
@@@ -1590,7 -1590,7 +1590,7 @@@ public final class Normalizer implement
       * <tt>String</tt> over which this <tt>Normalizer</tt> is iterating
       * @deprecated ICU 2.2. Use startIndex() instead.
       * @return The codepoint as an int
--     * @see #startIndex
++     * @see #index
       */
      @Deprecated
      public int getBeginIndex() {