]> granicus.if.org Git - icu/commitdiff
ICU-8610 More general progress in C++; generation code is largely implemented. Probab...
authorShane Carr <shane@unicode.org>
Fri, 23 Mar 2018 07:51:52 +0000 (07:51 +0000)
committerShane Carr <shane@unicode.org>
Fri, 23 Mar 2018 07:51:52 +0000 (07:51 +0000)
X-SVN-Rev: 41143

icu4c/source/i18n/number_formatimpl.cpp
icu4c/source/i18n/number_grouping.cpp
icu4c/source/i18n/number_integerwidth.cpp
icu4c/source/i18n/number_skeletons.cpp
icu4c/source/i18n/number_skeletons.h
icu4c/source/i18n/number_utils.h
icu4c/source/i18n/unicode/numberformatter.h
icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java

index 102a786a2270698972bd32e9d5aa6bed557ef280..b3e843206fd6460b523863e43fffa9ba1e45c810 100644 (file)
@@ -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
index a77e505a2213be506bdc3b7819dd868a8253554f..90bcc4fb5b39f42d31b5ec1e1428b1ce8b01b9f2 100644 (file)
@@ -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<int16_t>(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) {
index 4a612273f5e530f25f7fd729325e32b8a06ec183..464c2230fffe108308b6d3d43320e651b8c11e1f 100644 (file)
@@ -1,6 +1,7 @@
 // © 2017 and later: Unicode, Inc. and others.
 // License & terms of use: http://www.unicode.org/copyright.html
 
+#include <unicode/numberformatter.h>
 #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 */
index 1431459a4a43a5bf81d61c0d5d1ef7626f296edb..dbb94852285cb31174bec71c886ce648f376761c 100644 (file)
@@ -1,6 +1,7 @@
 // © 2018 and later: Unicode, Inc. and others.
 // License & terms of use: http://www.unicode.org/copyright.html
 
+#include <unicode/numberformatter.h>
 #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 */
index 74f2fd193f0b7291ddba99838da8e69c8b1efe79..843f1390af4e4c5204809e566f9e84e29bf29536 100644 (file)
@@ -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.
index 1e5494dc8137dd9b5546ac0145455d21a7e75a5e..6ca205dc2b6e1a8cf139bacb7b969c079b16829a 100644 (file)
@@ -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
index 87b1c6f196da20bc3ce821e3d22ca8ee760f8fa1..fdc6bdc285cda9e285023b3afceddea88b383db2 100644 (file)
@@ -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:
      * <ul>
      * <li>-2 = needs locale data
      * <li>-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 */
index 19ea62f68babd742f7345ac0c18abbf92a96dcda..dc831d2dd5c6e238a75ed2a824ac205e44d6b10e 100644 (file)
@@ -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;