From: Shane Carr Date: Tue, 13 Jun 2017 20:42:33 +0000 (+0000) Subject: ICU-13177 Merging trunk to branch X-Git-Tag: release-60-rc~98^2~43 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d177e8b645f74d0b4520a10ead51978badc35fb9;p=icu ICU-13177 Merging trunk to branch X-SVN-Rev: 40168 --- d177e8b645f74d0b4520a10ead51978badc35fb9 diff --cc icu4c/source/i18n/nfrs.cpp index 05941e8b293,05941e8b293..ea4a05d749d --- a/icu4c/source/i18n/nfrs.cpp +++ b/icu4c/source/i18n/nfrs.cpp @@@ -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; diff --cc icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PositiveDecimalFormat.java index fdb26062f4c,b4a33dcc8ac..41a427f8d43 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PositiveDecimalFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/formatters/PositiveDecimalFormat.java @@@ -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 threadLocalTransientStruct = ++ new ThreadLocal() { ++ @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); } } @@@ -212,11 -224,11 +258,13 @@@ 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); } } diff --cc icu4j/main/classes/core/src/com/ibm/icu/text/Normalizer.java index f4bd467ee6b,f4bd467ee6b..458baa67f19 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/Normalizer.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/Normalizer.java @@@ -1590,7 -1590,7 +1590,7 @@@ public final class Normalizer implement * String over which this Normalizer is iterating * @deprecated ICU 2.2. Use startIndex() instead. * @return The codepoint as an int -- * @see #startIndex ++ * @see #index */ @Deprecated public int getBeginIndex() {