From: Shane Carr Date: Fri, 23 Mar 2018 07:51:52 +0000 (+0000) Subject: ICU-8610 More general progress in C++; generation code is largely implemented. Probab... X-Git-Tag: release-62-rc~200^2~76 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=52c665a2bda32091ec1d3e769d51e5c8bd47e811;p=icu ICU-8610 More general progress in C++; generation code is largely implemented. Probably not building yet. X-SVN-Rev: 41143 --- diff --git a/icu4c/source/i18n/number_formatimpl.cpp b/icu4c/source/i18n/number_formatimpl.cpp index 102a786a227..b3e843206fd 100644 --- a/icu4c/source/i18n/number_formatimpl.cpp +++ b/icu4c/source/i18n/number_formatimpl.cpp @@ -125,22 +125,6 @@ getCurrencyFormatInfo(const Locale& locale, const char* isoCode, UErrorCode& sta return result; } -inline bool unitIsCurrency(const MeasureUnit& unit) { - return uprv_strcmp("currency", unit.getType()) == 0; -} - -inline bool unitIsNoUnit(const MeasureUnit& unit) { - return uprv_strcmp("none", unit.getType()) == 0; -} - -inline bool unitIsPercent(const MeasureUnit& unit) { - return uprv_strcmp("percent", unit.getSubtype()) == 0; -} - -inline bool unitIsPermille(const MeasureUnit& unit) { - return uprv_strcmp("permille", unit.getSubtype()) == 0; -} - } // namespace NumberFormatterImpl* NumberFormatterImpl::fromMacros(const MacroProps& macros, UErrorCode& status) { @@ -325,7 +309,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, if (!macros.integerWidth.isBogus()) { fMicros.integerWidth = macros.integerWidth; } else { - fMicros.integerWidth = IntegerWidth::zeroFillTo(1); + fMicros.integerWidth = IntegerWidth::standard(); } // Sign display diff --git a/icu4c/source/i18n/number_grouping.cpp b/icu4c/source/i18n/number_grouping.cpp index a77e505a221..90bcc4fb5b3 100644 --- a/icu4c/source/i18n/number_grouping.cpp +++ b/icu4c/source/i18n/number_grouping.cpp @@ -37,15 +37,15 @@ int16_t getMinGroupingForLocale(const Locale& locale) { Grouper Grouper::forStrategy(UGroupingStrategy grouping) { switch (grouping) { case UNUM_GROUPING_OFF: - return {-1, -1, -2}; + return {-1, -1, -2, grouping}; case UNUM_GROUPING_AUTO: - return {-2, -2, -2}; + return {-2, -2, -2, grouping}; case UNUM_GROUPING_MIN2: - return {-2, -2, -3}; + return {-2, -2, -3, grouping}; case UNUM_GROUPING_ON_ALIGNED: - return {-4, -4, 1}; + return {-4, -4, 1, grouping}; case UNUM_GROUPING_THOUSANDS: - return {3, 3, 1}; + return {3, 3, 1, grouping}; default: U_ASSERT(FALSE); } @@ -57,7 +57,7 @@ Grouper Grouper::forProperties(const DecimalFormatProperties& properties) { auto minGrouping = static_cast(properties.minimumGroupingDigits); grouping1 = grouping1 > 0 ? grouping1 : grouping2 > 0 ? grouping2 : grouping1; grouping2 = grouping2 > 0 ? grouping2 : grouping1; - return {grouping1, grouping2, minGrouping}; + return {grouping1, grouping2, minGrouping, UNUM_GROUPING_COUNT}; } void Grouper::setLocaleData(const impl::ParsedPatternInfo &patternInfo, const Locale& locale) { diff --git a/icu4c/source/i18n/number_integerwidth.cpp b/icu4c/source/i18n/number_integerwidth.cpp index 4a612273f5e..464c2230fff 100644 --- a/icu4c/source/i18n/number_integerwidth.cpp +++ b/icu4c/source/i18n/number_integerwidth.cpp @@ -1,6 +1,7 @@ // © 2017 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html +#include #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT @@ -48,4 +49,13 @@ void IntegerWidth::apply(impl::DecimalQuantity &quantity, UErrorCode &status) co } } +bool IntegerWidth::operator==(const IntegerWidth& other) const { + if (fHasError) { + return other.fHasError && fUnion.errorCode == other.fUnion.errorCode; + } else { + return !other.fHasError && fUnion.minMaxInt.fMinInt == other.fUnion.minMaxInt.fMinInt && + fUnion.minMaxInt.fMaxInt == other.fUnion.minMaxInt.fMaxInt; + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/i18n/number_skeletons.cpp b/icu4c/source/i18n/number_skeletons.cpp index 1431459a4a4..dbb94852285 100644 --- a/icu4c/source/i18n/number_skeletons.cpp +++ b/icu4c/source/i18n/number_skeletons.cpp @@ -1,6 +1,7 @@ // © 2018 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html +#include #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT @@ -15,6 +16,7 @@ #include "hash.h" #include "patternprops.h" #include "unicode/ucharstriebuilder.h" +#include "number_utils.h" using namespace icu; using namespace icu::number; @@ -327,7 +329,7 @@ UnicodeString skeleton::generate(const MacroProps& macros, UErrorCode& status) { if (U_FAILURE(status)) { return {}; } UnicodeString sb; - generateSkeleton(macros, sb, status); + GeneratorHelpers::generateSkeleton(macros, sb, status); return sb; } @@ -559,5 +561,332 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se } } +ParseState skeleton::parseOption(ParseState stem, const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + + ///// Required options: ///// + + switch (stem) { + case STATE_CURRENCY_UNIT: + blueprint_helpers::parseCurrencyOption(segment, macros, status); + return STATE_NULL; + case STATE_MEASURE_UNIT: + blueprint_helpers::parseMeasureUnitOption(segment, macros, status); + return STATE_NULL; + case STATE_PER_MEASURE_UNIT: + blueprint_helpers::parseMeasurePerUnitOption(segment, macros, status); + return STATE_NULL; + case STATE_INCREMENT_ROUNDER: + blueprint_helpers::parseIncrementOption(segment, macros, status); + return STATE_ROUNDER; + case STATE_INTEGER_WIDTH: + blueprint_helpers::parseIntegerWidthOption(segment, macros, status); + return STATE_NULL; + case STATE_NUMBERING_SYSTEM: + blueprint_helpers::parseNumberingSystemOption(segment, macros, status); + return STATE_NULL; + default: + break; + } + + ///// Non-required options: ///// + + // Scientific options + switch (stem) { + case STATE_SCIENTIFIC: + if (blueprint_helpers::parseExponentWidthOption(segment, macros, status)) { + return STATE_SCIENTIFIC; + } + if (blueprint_helpers::parseExponentSignOption(segment, macros, status)) { + return STATE_SCIENTIFIC; + } + break; + default: + break; + } + + // Frac-sig option + switch (stem) { + case STATE_FRACTION_ROUNDER: + if (blueprint_helpers::parseFracSigOption(segment, macros, status)) { + return STATE_ROUNDER; + } + break; + default: + break; + } + + // Rounding mode option + switch (stem) { + case STATE_ROUNDER: + case STATE_FRACTION_ROUNDER: + if (blueprint_helpers::parseRoundingModeOption(segment, macros, status)) { + return STATE_ROUNDER; + } + break; + default: + break; + } + + // Unknown option + // throw new SkeletonSyntaxException("Invalid option", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return STATE_NULL; +} + +void GeneratorHelpers::generateSkeleton(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + // Supported options + if (GeneratorHelpers::notation(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::unit(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::perUnit(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::rounding(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::grouping(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::integerWidth(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::symbols(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::unitWidth(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::sign(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::decimal(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + + // Unsupported options + if (!macros.padder.isBogus()) { + status = U_UNSUPPORTED_ERROR; + return; + } + if (macros.affixProvider != nullptr) { + status = U_UNSUPPORTED_ERROR; + return; + } + if (macros.multiplier.isValid()) { + status = U_UNSUPPORTED_ERROR; + return; + } + if (macros.rules != nullptr) { + status = U_UNSUPPORTED_ERROR; + return; + } + if (macros.currencySymbols != nullptr) { + status = U_UNSUPPORTED_ERROR; + return; + } + + // Remove the trailing space + if (sb.length() > 0) { + sb.truncate(sb.length() - 1); + } +} + + +bool GeneratorHelpers::notation(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.notation.fType == Notation::NTN_COMPACT) { + UNumberCompactStyle style = macros.notation.fUnion.compactStyle; + if (style == UNumberCompactStyle::UNUM_LONG) { + sb.append(u"compact-long", -1); + return true; + } else if (style == UNumberCompactStyle::UNUM_SHORT) { + sb.append(u"compact-short", -1); + return true; + } else { + // Compact notation generated from custom data (not supported in skeleton) + // The other compact notations are literals + status = U_UNSUPPORTED_ERROR; + return false; + } + } else if (macros.notation.fType == Notation::NTN_SCIENTIFIC) { + const Notation::ScientificSettings& impl = macros.notation.fUnion.scientific; + if (impl.fEngineeringInterval == 3) { + sb.append(u"engineering", -1); + } else { + sb.append(u"scientific", -1); + } + if (impl.fMinExponentDigits > 1) { + sb.append(u'/'); + blueprint_helpers::generateExponentWidthOption(impl.fMinExponentDigits, sb, status); + } + if (impl.fExponentSignDisplay != UNUM_SIGN_AUTO) { + sb.append(u'/'); + enum_to_stem_string::signDisplay(impl.fExponentSignDisplay, sb); + } + return true; + } else { + // Default value is not shown in normalized form + return false; + } +} + +bool GeneratorHelpers::unit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (unitIsCurrency(macros.unit)) { + sb.append(u"currency/", -1); + blueprint_helpers::generateCurrencyOption({macros.unit, status}, sb, status); + return true; + } else if (unitIsNoUnit(macros.unit)) { + if (unitIsPercent(macros.unit)) { + sb.append(u"percent", -1); + return true; + } else if (unitIsPermille(macros.unit)) { + sb.append(u"permille", -1); + return true; + } else { + // Default value is not shown in normalized form + return false; + } + } else { + sb.append(u"measure-unit/", -1); + blueprint_helpers::generateMeasureUnitOption(macros.unit, sb, status); + return true; + } +} + +bool GeneratorHelpers::perUnit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + // Per-units are currently expected to be only MeasureUnits. + if (unitIsCurrency(macros.perUnit) || unitIsNoUnit(macros.perUnit)) { + status = U_UNSUPPORTED_ERROR; + } else { + sb.append(u"per-measure-unit/", -1); + blueprint_helpers::generateMeasureUnitOption(macros.perUnit, sb, status); + return true; + } +} + +bool GeneratorHelpers::rounding(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.rounder.fType == Rounder::RND_NONE) { + sb.append(u"round-unlimited", -1); + } else if (macros.rounder.fType == Rounder::RND_FRACTION) { + const Rounder::FractionSignificantSettings& impl = macros.rounder.fUnion.fracSig; + blueprint_helpers::generateFractionStem(impl.fMinFrac, impl.fMaxFrac, sb, status); + } else if (macros.rounder.fType == Rounder::RND_SIGNIFICANT) { + const Rounder::FractionSignificantSettings& impl = macros.rounder.fUnion.fracSig; + blueprint_helpers::generateDigitsStem(impl.fMinSig, impl.fMaxSig, sb, status); + } else if (macros.rounder.fType == Rounder::RND_FRACTION_SIGNIFICANT) { + const Rounder::FractionSignificantSettings& impl = macros.rounder.fUnion.fracSig; + blueprint_helpers::generateFractionStem(impl.fMinFrac, impl.fMaxFrac, sb, status); + sb.append(u'/'); + if (impl.fMinSig == -1) { + blueprint_helpers::generateDigitsStem(1, impl.fMaxSig, sb, status); + } else { + blueprint_helpers::generateDigitsStem(impl.fMinSig, -1, sb, status); + } + } else if (macros.rounder.fType == Rounder::RND_INCREMENT) { + const Rounder::IncrementSettings& impl = macros.rounder.fUnion.increment; + sb.append(u"round-increment/", -1); + blueprint_helpers::generateIncrementOption(impl.fIncrement, sb, status); + } else if (macros.rounder.fType == Rounder::RND_CURRENCY) { + UCurrencyUsage usage = macros.rounder.fUnion.currencyUsage; + if (usage == UCURR_USAGE_STANDARD) { + sb.append(u"round-currency-standard", -1); + } else { + sb.append(u"round-currency-cash", -1); + } + } else { + // Bogus or Error + return false; + } + + // Generate the options + if (macros.rounder.fRoundingMode != kDefaultMode) { + sb.append(u'/'); + blueprint_helpers::generateRoundingModeOption(macros.rounder.fRoundingMode, sb, status); + } + + // NOTE: Always return true for rounding because the default value depends on other options. + return true; +} + +bool GeneratorHelpers::grouping(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.grouper.isBogus() || macros.grouper.fStrategy == UNUM_GROUPING_COUNT) { + status = U_UNSUPPORTED_ERROR; + } else if (macros.grouper.fStrategy == UNUM_GROUPING_AUTO) { + return false; // Default value + } else { + enum_to_stem_string::groupingStrategy(macros.grouper.fStrategy, sb); + } +} + +bool GeneratorHelpers::integerWidth(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.integerWidth.fHasError || macros.integerWidth == IntegerWidth::standard()) { + // Error or Default + return false; + } + sb.append(u"integer-width/", -1); + blueprint_helpers::generateIntegerWidthOption( + macros.integerWidth.fUnion.minMaxInt.fMinInt, + macros.integerWidth.fUnion.minMaxInt.fMaxInt, + sb, + status); + return true; +} + +bool GeneratorHelpers::symbols(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.symbols.isNumberingSystem()) { + const NumberingSystem& ns = *macros.symbols.getNumberingSystem(); + if (uprv_strcmp(ns.getName(), "latn") == 0) { + sb.append(u"latin", -1); + } else { + sb.append(u"numbering-system/", -1); + blueprint_helpers::generateNumberingSystemOption(ns, sb, status); + } + return true; + } else if (macros.symbols.isDecimalFormatSymbols()) { + status = U_UNSUPPORTED_ERROR; + return false; + } else { + // No custom symbols + return false; + } +} + +bool GeneratorHelpers::unitWidth(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.unitWidth == UNUM_UNIT_WIDTH_SHORT || macros.unitWidth == UNUM_UNIT_WIDTH_COUNT) { + return false; // Default or Bogus + } + enum_to_stem_string::unitWidth(macros.unitWidth, sb); + return true; +} + +bool GeneratorHelpers::sign(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.sign == UNUM_SIGN_AUTO || macros.sign == UNUM_SIGN_COUNT) { + return false; // Default or Bogus + } + enum_to_stem_string::signDisplay(macros.sign, sb); + return true; +} + +bool GeneratorHelpers::decimal(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.decimal == UNUM_DECIMAL_SEPARATOR_AUTO || macros.decimal == UNUM_DECIMAL_SEPARATOR_COUNT) { + return false; // Default or Bogus + } + enum_to_stem_string::decimalSeparatorDisplay(macros.decimal, sb); + return true; +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/i18n/number_skeletons.h b/icu4c/source/i18n/number_skeletons.h index 74f2fd193f0..843f1390af4 100644 --- a/icu4c/source/i18n/number_skeletons.h +++ b/icu4c/source/i18n/number_skeletons.h @@ -143,14 +143,6 @@ ParseState parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, S ParseState parseOption(ParseState stem, const StringSegment& segment, MacroProps& macros, UErrorCode& status); -/** - * Main skeleton generator function. Appends the normalized skeleton for the MacroProps to the given - * StringBuilder. - * - * Internal: use the create() endpoint instead of this function. - */ -void generateSkeleton(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); - } // namespace skeleton @@ -241,37 +233,48 @@ void generateIntegerWidthOption(int32_t minInt, int32_t maxInt, UnicodeString& s void parseNumberingSystemOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); -void generateNumberingSystemOption(NumberingSystem, UnicodeString& sb, UErrorCode& status); +void generateNumberingSystemOption(const NumberingSystem& ns, UnicodeString& sb, UErrorCode& status); } // namespace blueprint_helpers /** - * Namespace for utility methods for generating a token corresponding to each macro-prop. Each method + * Class for utility methods for generating a token corresponding to each macro-prop. Each method * returns whether or not a token was written to the string builder. + * + * This needs to be a class, not a namespace, so it can be friended. */ -namespace generator_helpers { +class GeneratorHelpers { + public: + /** + * Main skeleton generator function. Appends the normalized skeleton for the MacroProps to the given + * StringBuilder. + * + * Internal: use the create() endpoint instead of this function. + */ + static void generateSkeleton(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -bool notation(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + private: + static bool notation(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -bool unit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + static bool unit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -bool perUnit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + static bool perUnit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -bool rounding(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + static bool rounding(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -bool grouping(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + static bool grouping(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -bool integerWidth(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + static bool integerWidth(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -bool symbols(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + static bool symbols(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -bool unitWidth(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + static bool unitWidth(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -bool sign(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + static bool sign(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -bool decimal(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + static bool decimal(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); -} // namespace generator_helpers +}; /** * Struct for null-checking. diff --git a/icu4c/source/i18n/number_utils.h b/icu4c/source/i18n/number_utils.h index 1e5494dc813..6ca205dc2b6 100644 --- a/icu4c/source/i18n/number_utils.h +++ b/icu4c/source/i18n/number_utils.h @@ -122,6 +122,22 @@ inline int32_t insertDigitFromSymbols(NumberStringBuilder& output, int32_t index return output.insert(index, symbols.getConstDigitSymbol(digit), field, status); } +inline bool unitIsCurrency(const MeasureUnit& unit) { + return uprv_strcmp("currency", unit.getType()) == 0; +} + +inline bool unitIsNoUnit(const MeasureUnit& unit) { + return uprv_strcmp("none", unit.getType()) == 0; +} + +inline bool unitIsPercent(const MeasureUnit& unit) { + return uprv_strcmp("percent", unit.getSubtype()) == 0; +} + +inline bool unitIsPermille(const MeasureUnit& unit) { + return uprv_strcmp("permille", unit.getSubtype()) == 0; +} + } // namespace impl } // namespace number U_NAMESPACE_END diff --git a/icu4c/source/i18n/unicode/numberformatter.h b/icu4c/source/i18n/unicode/numberformatter.h index 87b1c6f196d..fdc6bdc285c 100644 --- a/icu4c/source/i18n/unicode/numberformatter.h +++ b/icu4c/source/i18n/unicode/numberformatter.h @@ -454,6 +454,7 @@ class NumberPropertyMapper; struct DecimalFormatProperties; class MultiplierChain; class CurrencySymbols; +class GeneratorHelpers; } // namespace impl @@ -658,6 +659,9 @@ class U_I18N_API Notation : public UMemory { friend class impl::NumberFormatterImpl; friend class impl::ScientificModifier; friend class impl::ScientificHandler; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; }; /** @@ -1045,6 +1049,9 @@ class U_I18N_API Rounder : public UMemory { friend class FractionRounder; friend class CurrencyRounder; friend class IncrementRounder; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; }; /** @@ -1237,6 +1244,11 @@ class U_I18N_API IntegerWidth : public UMemory { fUnion.minMaxInt.fMinInt = -1; } + /** Returns the default instance. */ + static IntegerWidth standard() { + return IntegerWidth::zeroFillTo(1); + } + bool isBogus() const { return !fHasError && fUnion.minMaxInt.fMinInt == -1; } @@ -1251,12 +1263,17 @@ class U_I18N_API IntegerWidth : public UMemory { void apply(impl::DecimalQuantity &quantity, UErrorCode &status) const; + bool operator==(const IntegerWidth& other) const; + // To allow MacroProps/MicroProps to initialize empty instances: friend struct impl::MacroProps; friend struct impl::MicroProps; // To allow NumberFormatterImpl to access isBogus() and perform other operations: friend class impl::NumberFormatterImpl; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; }; namespace impl { @@ -1362,8 +1379,11 @@ class U_I18N_API Grouper : public UMemory { // Future: static Grouper forProperties(DecimalFormatProperties& properties); /** @internal */ - Grouper(int16_t grouping1, int16_t grouping2, int16_t minGrouping) - : fGrouping1(grouping1), fGrouping2(grouping2), fMinGrouping(minGrouping) {} + Grouper(int16_t grouping1, int16_t grouping2, int16_t minGrouping, UGroupingStrategy strategy) + : fGrouping1(grouping1), + fGrouping2(grouping2), + fMinGrouping(minGrouping), + fStrategy(strategy) {} /** @internal */ int16_t getPrimary() const; @@ -1384,7 +1404,7 @@ class U_I18N_API Grouper : public UMemory { int16_t fGrouping2; /** - * The minimum gropuing size, with the following special values: + * The minimum grouping size, with the following special values: *
    *
  • -2 = needs locale data *
  • -3 = no less than 2 @@ -1392,6 +1412,12 @@ class U_I18N_API Grouper : public UMemory { */ int16_t fMinGrouping; + /** + * The UGroupingStrategy that was used to create this Grouper, or UNUM_GROUPING_COUNT if this + * was not created from a UGroupingStrategy. + */ + UGroupingStrategy fStrategy; + Grouper() : fGrouping1(-3) {}; bool isBogus() const { @@ -1412,6 +1438,9 @@ class U_I18N_API Grouper : public UMemory { // To allow NumberParserImpl to perform setLocaleData(): friend class ::icu::numparse::impl::NumberParserImpl; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; }; /** @internal */ @@ -1472,6 +1501,9 @@ class U_I18N_API Padder : public UMemory { // To allow NumberFormatterImpl to access isBogus() and perform other operations: friend class impl::NumberFormatterImpl; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; }; /** @internal */ @@ -1504,6 +1536,9 @@ class U_I18N_API Multiplier : public UMemory { // To allow the helper class MultiplierChain access to private fields: friend class impl::MultiplierChain; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; }; /** @internal */ diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java index 19ea62f68ba..dc831d2dd5c 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java @@ -686,6 +686,8 @@ class NumberSkeletonImpl { case STATE_NUMBERING_SYSTEM: BlueprintHelpers.parseNumberingSystemOption(segment, macros); return ParseState.STATE_NULL; + default: + break; } ///// Non-required options: ///// @@ -699,6 +701,9 @@ class NumberSkeletonImpl { if (BlueprintHelpers.parseExponentSignOption(segment, macros)) { return ParseState.STATE_SCIENTIFIC; } + break; + default: + break; } // Frac-sig option @@ -707,6 +712,9 @@ class NumberSkeletonImpl { if (BlueprintHelpers.parseFracSigOption(segment, macros)) { return ParseState.STATE_ROUNDER; } + break; + default: + break; } // Rounding mode option @@ -716,6 +724,9 @@ class NumberSkeletonImpl { if (BlueprintHelpers.parseRoundingModeOption(segment, macros)) { return ParseState.STATE_ROUNDER; } + break; + default: + break; } // Unknown option @@ -1210,7 +1221,7 @@ class NumberSkeletonImpl { private static boolean perUnit(MacroProps macros, StringBuilder sb) { // Per-units are currently expected to be only MeasureUnits. - if (macros.unit instanceof Currency || macros.unit instanceof NoUnit) { + if (macros.perUnit instanceof Currency || macros.perUnit instanceof NoUnit) { throw new UnsupportedOperationException( "Cannot generate number skeleton with per-unit that is not a standard measure unit"); } else { @@ -1242,8 +1253,6 @@ class NumberSkeletonImpl { Rounder.IncrementRounderImpl impl = (Rounder.IncrementRounderImpl) macros.rounder; sb.append("round-increment/"); BlueprintHelpers.generateIncrementOption(impl.increment, sb); - } else if (macros.rounder instanceof Rounder.InfiniteRounderImpl) { - sb.append("round-unlimited"); } else { assert macros.rounder instanceof Rounder.CurrencyRounderImpl; Rounder.CurrencyRounderImpl impl = (Rounder.CurrencyRounderImpl) macros.rounder;