ICU 73.2  73.2
numberformatter.h
Go to the documentation of this file.
00001 // © 2017 and later: Unicode, Inc. and others.
00002 // License & terms of use: http://www.unicode.org/copyright.html
00003 
00004 #ifndef __NUMBERFORMATTER_H__
00005 #define __NUMBERFORMATTER_H__
00006 
00007 #include "unicode/utypes.h"
00008 
00009 #if U_SHOW_CPLUSPLUS_API
00010 
00011 #if !UCONFIG_NO_FORMATTING
00012 
00013 #include "unicode/appendable.h"
00014 #include "unicode/bytestream.h"
00015 #include "unicode/currunit.h"
00016 #include "unicode/dcfmtsym.h"
00017 #include "unicode/displayoptions.h"
00018 #include "unicode/fieldpos.h"
00019 #include "unicode/fpositer.h"
00020 #include "unicode/measunit.h"
00021 #include "unicode/nounit.h"
00022 #include "unicode/parseerr.h"
00023 #include "unicode/plurrule.h"
00024 #include "unicode/ucurr.h"
00025 #include "unicode/unum.h"
00026 #include "unicode/unumberformatter.h"
00027 #include "unicode/uobject.h"
00028 #include "unicode/unumberoptions.h"
00029 #include "unicode/formattednumber.h"
00030 
00086 U_NAMESPACE_BEGIN
00087 
00088 // Forward declarations:
00089 class IFixedDecimal;
00090 class FieldPositionIteratorHandler;
00091 class FormattedStringBuilder;
00092 
00093 namespace numparse {
00094 namespace impl {
00095 
00096 // Forward declarations:
00097 class NumberParserImpl;
00098 class MultiplierParseHandler;
00099 
00100 }
00101 }
00102 
00103 namespace units {
00104 
00105 // Forward declarations:
00106 class UnitsRouter;
00107 
00108 } // namespace units
00109 
00110 namespace number {  // icu::number
00111 
00112 // Forward declarations:
00113 class UnlocalizedNumberFormatter;
00114 class LocalizedNumberFormatter;
00115 class SimpleNumberFormatter;
00116 class FormattedNumber;
00117 class Notation;
00118 class ScientificNotation;
00119 class Precision;
00120 class FractionPrecision;
00121 class CurrencyPrecision;
00122 class IncrementPrecision;
00123 class IntegerWidth;
00124 
00125 namespace impl {
00126 
00127 // can't be #ifndef U_HIDE_INTERNAL_API; referenced throughout this file in public classes
00133 typedef int16_t digits_t;
00134 
00135 // can't be #ifndef U_HIDE_INTERNAL_API; needed for struct initialization
00142 static constexpr int32_t kInternalDefaultThreshold = 3;
00143 
00144 // Forward declarations:
00145 class Padder;
00146 struct MacroProps;
00147 struct MicroProps;
00148 class DecimalQuantity;
00149 class UFormattedNumberData;
00150 class NumberFormatterImpl;
00151 struct ParsedPatternInfo;
00152 class ScientificModifier;
00153 class MultiplierProducer;
00154 class RoundingImpl;
00155 class ScientificHandler;
00156 class Modifier;
00157 class AffixPatternProvider;
00158 class NumberPropertyMapper;
00159 struct DecimalFormatProperties;
00160 class MultiplierFormatHandler;
00161 class CurrencySymbols;
00162 class GeneratorHelpers;
00163 class DecNum;
00164 class NumberRangeFormatterImpl;
00165 struct RangeMacroProps;
00166 struct UFormattedNumberImpl;
00167 class MutablePatternModifier;
00168 class ImmutablePatternModifier;
00169 struct DecimalFormatWarehouse;
00170 struct SimpleMicroProps;
00171 class AdoptingSignumModifierStore;
00172 
00179 void touchRangeLocales(impl::RangeMacroProps& macros);
00180 
00181 } // namespace impl
00182 
00188 typedef Notation CompactNotation;
00189 
00195 typedef Notation SimpleNotation;
00196 
00202 class U_I18N_API Notation : public UMemory {
00203   public:
00228     static ScientificNotation scientific();
00229 
00252     static ScientificNotation engineering();
00253 
00295     static CompactNotation compactShort();
00296 
00319     static CompactNotation compactLong();
00320 
00345     static SimpleNotation simple();
00346 
00347   private:
00348     enum NotationType {
00349         NTN_SCIENTIFIC, NTN_COMPACT, NTN_SIMPLE, NTN_ERROR
00350     } fType;
00351 
00352     union NotationUnion {
00353         // For NTN_SCIENTIFIC
00355         struct ScientificSettings {
00357             int8_t fEngineeringInterval;
00359             bool fRequireMinInt;
00361             impl::digits_t fMinExponentDigits;
00363             UNumberSignDisplay fExponentSignDisplay;
00364         } scientific;
00365 
00366         // For NTN_COMPACT
00367         UNumberCompactStyle compactStyle;
00368 
00369         // For NTN_ERROR
00370         UErrorCode errorCode;
00371     } fUnion;
00372 
00373     typedef NotationUnion::ScientificSettings ScientificSettings;
00374 
00375     Notation(const NotationType &type, const NotationUnion &union_) : fType(type), fUnion(union_) {}
00376 
00377     Notation(UErrorCode errorCode) : fType(NTN_ERROR) {
00378         fUnion.errorCode = errorCode;
00379     }
00380 
00381     Notation() : fType(NTN_SIMPLE), fUnion() {}
00382 
00383     UBool copyErrorTo(UErrorCode &status) const {
00384         if (fType == NTN_ERROR) {
00385             status = fUnion.errorCode;
00386             return true;
00387         }
00388         return false;
00389     }
00390 
00391     // To allow MacroProps to initialize empty instances:
00392     friend struct impl::MacroProps;
00393     friend class ScientificNotation;
00394 
00395     // To allow implementation to access internal types:
00396     friend class impl::NumberFormatterImpl;
00397     friend class impl::ScientificModifier;
00398     friend class impl::ScientificHandler;
00399 
00400     // To allow access to the skeleton generation code:
00401     friend class impl::GeneratorHelpers;
00402 };
00403 
00412 class U_I18N_API ScientificNotation : public Notation {
00413   public:
00427     ScientificNotation withMinExponentDigits(int32_t minExponentDigits) const;
00428 
00442     ScientificNotation withExponentSignDisplay(UNumberSignDisplay exponentSignDisplay) const;
00443 
00444   private:
00445     // Inherit constructor
00446     using Notation::Notation;
00447 
00448     // Raw constructor for NumberPropertyMapper
00449     ScientificNotation(int8_t fEngineeringInterval, bool fRequireMinInt, impl::digits_t fMinExponentDigits,
00450                        UNumberSignDisplay fExponentSignDisplay);
00451 
00452     friend class Notation;
00453 
00454     // So that NumberPropertyMapper can create instances
00455     friend class impl::NumberPropertyMapper;
00456 };
00457 
00463 typedef Precision SignificantDigitsPrecision;
00464 
00473 class U_I18N_API Precision : public UMemory {
00474 
00475   public:
00493     static Precision unlimited();
00494 
00501     static FractionPrecision integer();
00502 
00530     static FractionPrecision fixedFraction(int32_t minMaxFractionPlaces);
00531 
00545     static FractionPrecision minFraction(int32_t minFractionPlaces);
00546 
00557     static FractionPrecision maxFraction(int32_t maxFractionPlaces);
00558 
00572     static FractionPrecision minMaxFraction(int32_t minFractionPlaces, int32_t maxFractionPlaces);
00573 
00587     static SignificantDigitsPrecision fixedSignificantDigits(int32_t minMaxSignificantDigits);
00588 
00601     static SignificantDigitsPrecision minSignificantDigits(int32_t minSignificantDigits);
00602 
00611     static SignificantDigitsPrecision maxSignificantDigits(int32_t maxSignificantDigits);
00612 
00624     static SignificantDigitsPrecision minMaxSignificantDigits(int32_t minSignificantDigits,
00625                                                               int32_t maxSignificantDigits);
00626 
00646     static IncrementPrecision increment(double roundingIncrement);
00647 
00671     static IncrementPrecision incrementExact(uint64_t mantissa, int16_t magnitude);
00672 
00690     static CurrencyPrecision currency(UCurrencyUsage currencyUsage);
00691 
00699     Precision trailingZeroDisplay(UNumberTrailingZeroDisplay trailingZeroDisplay) const;
00700 
00701   private:
00702     enum PrecisionType {
00703         RND_BOGUS,
00704         RND_NONE,
00705         RND_FRACTION,
00706         RND_SIGNIFICANT,
00707         RND_FRACTION_SIGNIFICANT,
00708 
00709         // Used for strange increments like 3.14.
00710         RND_INCREMENT,
00711 
00712         // Used for increments with 1 as the only digit. This is different than fraction
00713         // rounding because it supports having additional trailing zeros. For example, this
00714         // class is used to round with the increment 0.010.
00715         RND_INCREMENT_ONE,
00716 
00717         // Used for increments with 5 as the only digit (nickel rounding).
00718         RND_INCREMENT_FIVE,
00719 
00720         RND_CURRENCY,
00721         RND_ERROR
00722     } fType;
00723 
00724     union PrecisionUnion {
00726         struct FractionSignificantSettings {
00727             // For RND_FRACTION, RND_SIGNIFICANT, and RND_FRACTION_SIGNIFICANT
00729             impl::digits_t fMinFrac;
00731             impl::digits_t fMaxFrac;
00733             impl::digits_t fMinSig;
00735             impl::digits_t fMaxSig;
00737             UNumberRoundingPriority fPriority;
00742             bool fRetain;
00743         } fracSig;
00745         struct IncrementSettings {
00746             // For RND_INCREMENT, RND_INCREMENT_ONE, and RND_INCREMENT_FIVE
00747             // Note: This is a union, so we shouldn't own memory, since
00748             // the default destructor would leak it.
00750             uint64_t fIncrement;
00752             impl::digits_t fIncrementMagnitude;
00754             impl::digits_t fMinFrac;
00755         } increment;
00756         UCurrencyUsage currencyUsage; // For RND_CURRENCY
00757         UErrorCode errorCode; // For RND_ERROR
00758     } fUnion;
00759 
00760     UNumberTrailingZeroDisplay fTrailingZeroDisplay = UNUM_TRAILING_ZERO_AUTO;
00761 
00762     typedef PrecisionUnion::FractionSignificantSettings FractionSignificantSettings;
00763     typedef PrecisionUnion::IncrementSettings IncrementSettings;
00764 
00765     Precision(const PrecisionType& type, const PrecisionUnion& union_)
00766             : fType(type), fUnion(union_) {}
00767 
00768     Precision(UErrorCode errorCode) : fType(RND_ERROR) {
00769         fUnion.errorCode = errorCode;
00770     }
00771 
00772     Precision() : fType(RND_BOGUS) {}
00773 
00774     bool isBogus() const {
00775         return fType == RND_BOGUS;
00776     }
00777 
00778     UBool copyErrorTo(UErrorCode &status) const {
00779         if (fType == RND_ERROR) {
00780             status = fUnion.errorCode;
00781             return true;
00782         }
00783         return false;
00784     }
00785 
00786     // On the parent type so that this method can be called internally on Precision instances.
00787     Precision withCurrency(const CurrencyUnit &currency, UErrorCode &status) const;
00788 
00789     static FractionPrecision constructFraction(int32_t minFrac, int32_t maxFrac);
00790 
00791     static Precision constructSignificant(int32_t minSig, int32_t maxSig);
00792 
00793     static Precision constructFractionSignificant(
00794         const FractionPrecision &base,
00795         int32_t minSig,
00796         int32_t maxSig,
00797         UNumberRoundingPriority priority,
00798         bool retain);
00799 
00800     static IncrementPrecision constructIncrement(uint64_t increment, impl::digits_t magnitude);
00801 
00802     static CurrencyPrecision constructCurrency(UCurrencyUsage usage);
00803 
00804     // To allow MacroProps/MicroProps to initialize bogus instances:
00805     friend struct impl::MacroProps;
00806     friend struct impl::MicroProps;
00807 
00808     // To allow NumberFormatterImpl to access isBogus() and other internal methods:
00809     friend class impl::NumberFormatterImpl;
00810 
00811     // To allow NumberPropertyMapper to create instances from DecimalFormatProperties:
00812     friend class impl::NumberPropertyMapper;
00813 
00814     // To allow access to the main implementation class:
00815     friend class impl::RoundingImpl;
00816 
00817     // To allow child classes to call private methods:
00818     friend class FractionPrecision;
00819     friend class CurrencyPrecision;
00820     friend class IncrementPrecision;
00821 
00822     // To allow access to the skeleton generation code:
00823     friend class impl::GeneratorHelpers;
00824 
00825     // To allow access to isBogus and the default (bogus) constructor:
00826     friend class units::UnitsRouter;
00827 };
00828 
00838 class U_I18N_API FractionPrecision : public Precision {
00839   public:
00854     Precision withSignificantDigits(
00855         int32_t minSignificantDigits,
00856         int32_t maxSignificantDigits,
00857         UNumberRoundingPriority priority) const;
00858 
00876     Precision withMinDigits(int32_t minSignificantDigits) const;
00877 
00895     Precision withMaxDigits(int32_t maxSignificantDigits) const;
00896 
00897   private:
00898     // Inherit constructor
00899     using Precision::Precision;
00900 
00901     // To allow parent class to call this class's constructor:
00902     friend class Precision;
00903 };
00904 
00914 class U_I18N_API CurrencyPrecision : public Precision {
00915   public:
00933     Precision withCurrency(const CurrencyUnit &currency) const;
00934 
00935   private:
00936     // Inherit constructor
00937     using Precision::Precision;
00938 
00939     // To allow parent class to call this class's constructor:
00940     friend class Precision;
00941 };
00942 
00952 class U_I18N_API IncrementPrecision : public Precision {
00953   public:
00969     Precision withMinFraction(int32_t minFrac) const;
00970 
00971   private:
00972     // Inherit constructor
00973     using Precision::Precision;
00974 
00975     // To allow parent class to call this class's constructor:
00976     friend class Precision;
00977 };
00978 
00988 class U_I18N_API IntegerWidth : public UMemory {
00989   public:
01001     static IntegerWidth zeroFillTo(int32_t minInt);
01002 
01014     IntegerWidth truncateAt(int32_t maxInt);
01015 
01016   private:
01017     union {
01018         struct {
01019             impl::digits_t fMinInt;
01020             impl::digits_t fMaxInt;
01021             bool fFormatFailIfMoreThanMaxDigits;
01022         } minMaxInt;
01023         UErrorCode errorCode;
01024     } fUnion;
01025     bool fHasError = false;
01026 
01027     IntegerWidth(impl::digits_t minInt, impl::digits_t maxInt, bool formatFailIfMoreThanMaxDigits);
01028 
01029     IntegerWidth(UErrorCode errorCode) { // NOLINT
01030         fUnion.errorCode = errorCode;
01031         fHasError = true;
01032     }
01033 
01034     IntegerWidth() { // NOLINT
01035         fUnion.minMaxInt.fMinInt = -1;
01036     }
01037 
01039     static IntegerWidth standard() {
01040         return IntegerWidth::zeroFillTo(1);
01041     }
01042 
01043     bool isBogus() const {
01044         return !fHasError && fUnion.minMaxInt.fMinInt == -1;
01045     }
01046 
01047     UBool copyErrorTo(UErrorCode &status) const {
01048         if (fHasError) {
01049             status = fUnion.errorCode;
01050             return true;
01051         }
01052         return false;
01053     }
01054 
01055     void apply(impl::DecimalQuantity &quantity, UErrorCode &status) const;
01056 
01057     bool operator==(const IntegerWidth& other) const;
01058 
01059     // To allow MacroProps/MicroProps to initialize empty instances:
01060     friend struct impl::MacroProps;
01061     friend struct impl::MicroProps;
01062 
01063     // To allow NumberFormatterImpl to access isBogus():
01064     friend class impl::NumberFormatterImpl;
01065 
01066     // To allow the use of this class when formatting:
01067     friend class impl::MutablePatternModifier;
01068     friend class impl::ImmutablePatternModifier;
01069 
01070     // So that NumberPropertyMapper can create instances
01071     friend class impl::NumberPropertyMapper;
01072 
01073     // To allow access to the skeleton generation code:
01074     friend class impl::GeneratorHelpers;
01075 };
01076 
01085 class U_I18N_API Scale : public UMemory {
01086   public:
01093     static Scale none();
01094 
01105     static Scale powerOfTen(int32_t power);
01106 
01119     static Scale byDecimal(StringPiece multiplicand);
01120 
01129     static Scale byDouble(double multiplicand);
01130 
01137     static Scale byDoubleAndPowerOfTen(double multiplicand, int32_t power);
01138 
01139     // We need a custom destructor for the DecNum, which means we need to declare
01140     // the copy/move constructor/assignment quartet.
01141 
01143     Scale(const Scale& other);
01144 
01146     Scale& operator=(const Scale& other);
01147 
01149     Scale(Scale&& src) noexcept;
01150 
01152     Scale& operator=(Scale&& src) noexcept;
01153 
01155     ~Scale();
01156 
01157 #ifndef U_HIDE_INTERNAL_API
01158 
01159     Scale(int32_t magnitude, impl::DecNum* arbitraryToAdopt);
01160 #endif  /* U_HIDE_INTERNAL_API */
01161 
01162   private:
01163     int32_t fMagnitude;
01164     impl::DecNum* fArbitrary;
01165     UErrorCode fError;
01166 
01167     Scale(UErrorCode error) : fMagnitude(0), fArbitrary(nullptr), fError(error) {}
01168 
01169     Scale() : fMagnitude(0), fArbitrary(nullptr), fError(U_ZERO_ERROR) {}
01170 
01171     bool isValid() const {
01172         return fMagnitude != 0 || fArbitrary != nullptr;
01173     }
01174 
01175     UBool copyErrorTo(UErrorCode &status) const {
01176         if (U_FAILURE(fError)) {
01177             status = fError;
01178             return true;
01179         }
01180         return false;
01181     }
01182 
01183     void applyTo(impl::DecimalQuantity& quantity) const;
01184 
01185     void applyReciprocalTo(impl::DecimalQuantity& quantity) const;
01186 
01187     // To allow MacroProps/MicroProps to initialize empty instances:
01188     friend struct impl::MacroProps;
01189     friend struct impl::MicroProps;
01190 
01191     // To allow NumberFormatterImpl to access isBogus() and perform other operations:
01192     friend class impl::NumberFormatterImpl;
01193 
01194     // To allow the helper class MultiplierFormatHandler access to private fields:
01195     friend class impl::MultiplierFormatHandler;
01196 
01197     // To allow access to the skeleton generation code:
01198     friend class impl::GeneratorHelpers;
01199 
01200     // To allow access to parsing code:
01201     friend class ::icu::numparse::impl::NumberParserImpl;
01202     friend class ::icu::numparse::impl::MultiplierParseHandler;
01203 };
01204 
01205 namespace impl {
01206 
01207 // Do not enclose entire StringProp with #ifndef U_HIDE_INTERNAL_API, needed for a protected field.
01208 // And do not enclose its class boilerplate within #ifndef U_HIDE_INTERNAL_API.
01213 class U_I18N_API StringProp : public UMemory {
01214 
01215   public:
01217     ~StringProp();
01218 
01220     StringProp(const StringProp &other);
01221 
01223     StringProp &operator=(const StringProp &other);
01224 
01225 #ifndef U_HIDE_INTERNAL_API
01226 
01228     StringProp(StringProp &&src) noexcept;
01229 
01231     StringProp &operator=(StringProp &&src) noexcept;
01232 
01234     int16_t length() const {
01235         return fLength;
01236     }
01237 
01241     void set(StringPiece value);
01242 
01244     bool isSet() const {
01245         return fLength > 0;
01246     }
01247 
01248 #endif // U_HIDE_INTERNAL_API
01249 
01250   private:
01251     char *fValue;
01252     int16_t fLength;
01253     UErrorCode fError;
01254 
01255     StringProp() : fValue(nullptr), fLength(0), fError(U_ZERO_ERROR) {
01256     }
01257 
01259     UBool copyErrorTo(UErrorCode &status) const {
01260         if (U_FAILURE(fError)) {
01261             status = fError;
01262             return true;
01263         }
01264         return false;
01265     }
01266 
01267     // Allow NumberFormatterImpl to access fValue.
01268     friend class impl::NumberFormatterImpl;
01269 
01270     // Allow skeleton generation code to access private members.
01271     friend class impl::GeneratorHelpers;
01272 
01273     // Allow MacroProps/MicroProps to initialize empty instances and to call
01274     // copyErrorTo().
01275     friend struct impl::MacroProps;
01276 };
01277 
01278 // Do not enclose entire SymbolsWrapper with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
01280 class U_I18N_API SymbolsWrapper : public UMemory {
01281   public:
01283     SymbolsWrapper() : fType(SYMPTR_NONE), fPtr{nullptr} {}
01284 
01286     SymbolsWrapper(const SymbolsWrapper &other);
01287 
01289     SymbolsWrapper &operator=(const SymbolsWrapper &other);
01290 
01292     SymbolsWrapper(SymbolsWrapper&& src) noexcept;
01293 
01295     SymbolsWrapper &operator=(SymbolsWrapper&& src) noexcept;
01296 
01298     ~SymbolsWrapper();
01299 
01300 #ifndef U_HIDE_INTERNAL_API
01301 
01306     void setTo(const DecimalFormatSymbols &dfs);
01307 
01312     void setTo(const NumberingSystem *ns);
01313 
01318     bool isDecimalFormatSymbols() const;
01319 
01324     bool isNumberingSystem() const;
01325 
01330     const DecimalFormatSymbols *getDecimalFormatSymbols() const;
01331 
01336     const NumberingSystem *getNumberingSystem() const;
01337 
01338 #endif  // U_HIDE_INTERNAL_API
01339 
01341     UBool copyErrorTo(UErrorCode &status) const {
01342         if (fType == SYMPTR_DFS && fPtr.dfs == nullptr) {
01343             status = U_MEMORY_ALLOCATION_ERROR;
01344             return true;
01345         } else if (fType == SYMPTR_NS && fPtr.ns == nullptr) {
01346             status = U_MEMORY_ALLOCATION_ERROR;
01347             return true;
01348         }
01349         return false;
01350     }
01351 
01352   private:
01353     enum SymbolsPointerType {
01354         SYMPTR_NONE, SYMPTR_DFS, SYMPTR_NS
01355     } fType;
01356 
01357     union {
01358         const DecimalFormatSymbols *dfs;
01359         const NumberingSystem *ns;
01360     } fPtr;
01361 
01362     void doCopyFrom(const SymbolsWrapper &other);
01363 
01364     void doMoveFrom(SymbolsWrapper&& src);
01365 
01366     void doCleanup();
01367 };
01368 
01369 // Do not enclose entire Grouper with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
01371 class U_I18N_API Grouper : public UMemory {
01372   public:
01373 #ifndef U_HIDE_INTERNAL_API
01374 
01375     static Grouper forStrategy(UNumberGroupingStrategy grouping);
01376 
01381     static Grouper forProperties(const DecimalFormatProperties& properties);
01382 
01383     // Future: static Grouper forProperties(DecimalFormatProperties& properties);
01384 
01386     Grouper(int16_t grouping1, int16_t grouping2, int16_t minGrouping, UNumberGroupingStrategy strategy)
01387             : fGrouping1(grouping1),
01388               fGrouping2(grouping2),
01389               fMinGrouping(minGrouping),
01390               fStrategy(strategy) {}
01391 
01393     int16_t getPrimary() const;
01394 
01396     int16_t getSecondary() const;
01397 #endif  // U_HIDE_INTERNAL_API
01398 
01399   private:
01408     int16_t fGrouping1;
01409     int16_t fGrouping2;
01410 
01418     int16_t fMinGrouping;
01419 
01424     UNumberGroupingStrategy fStrategy;
01425 
01426     Grouper() : fGrouping1(-3) {}
01427 
01428     bool isBogus() const {
01429         return fGrouping1 == -3;
01430     }
01431 
01433     void setLocaleData(const impl::ParsedPatternInfo &patternInfo, const Locale& locale);
01434 
01435     bool groupAtPosition(int32_t position, const impl::DecimalQuantity &value) const;
01436 
01437     // To allow MacroProps/MicroProps to initialize empty instances:
01438     friend struct MacroProps;
01439     friend struct MicroProps;
01440     friend struct SimpleMicroProps;
01441 
01442     // To allow NumberFormatterImpl to access isBogus() and perform other operations:
01443     friend class NumberFormatterImpl;
01444     friend class ::icu::number::SimpleNumberFormatter;
01445 
01446     // To allow NumberParserImpl to perform setLocaleData():
01447     friend class ::icu::numparse::impl::NumberParserImpl;
01448 
01449     // To allow access to the skeleton generation code:
01450     friend class impl::GeneratorHelpers;
01451 };
01452 
01453 // Do not enclose entire Padder with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
01455 class U_I18N_API Padder : public UMemory {
01456   public:
01457 #ifndef U_HIDE_INTERNAL_API
01458 
01459     static Padder none();
01460 
01462     static Padder codePoints(UChar32 cp, int32_t targetWidth, UNumberFormatPadPosition position);
01463 
01465     static Padder forProperties(const DecimalFormatProperties& properties);
01466 #endif  // U_HIDE_INTERNAL_API
01467 
01468   private:
01469     UChar32 fWidth;  // -3 = error; -2 = bogus; -1 = no padding
01470     union {
01471         struct {
01472             int32_t fCp;
01473             UNumberFormatPadPosition fPosition;
01474         } padding;
01475         UErrorCode errorCode;
01476     } fUnion;
01477 
01478     Padder(UChar32 cp, int32_t width, UNumberFormatPadPosition position);
01479 
01480     Padder(int32_t width);
01481 
01482     Padder(UErrorCode errorCode) : fWidth(-3) { // NOLINT
01483         fUnion.errorCode = errorCode;
01484     }
01485 
01486     Padder() : fWidth(-2) {} // NOLINT
01487 
01488     bool isBogus() const {
01489         return fWidth == -2;
01490     }
01491 
01492     UBool copyErrorTo(UErrorCode &status) const {
01493         if (fWidth == -3) {
01494             status = fUnion.errorCode;
01495             return true;
01496         }
01497         return false;
01498     }
01499 
01500     bool isValid() const {
01501         return fWidth > 0;
01502     }
01503 
01504     int32_t padAndApply(const impl::Modifier &mod1, const impl::Modifier &mod2,
01505                         FormattedStringBuilder &string, int32_t leftIndex, int32_t rightIndex,
01506                         UErrorCode &status) const;
01507 
01508     // To allow MacroProps/MicroProps to initialize empty instances:
01509     friend struct MacroProps;
01510     friend struct MicroProps;
01511 
01512     // To allow NumberFormatterImpl to access isBogus() and perform other operations:
01513     friend class impl::NumberFormatterImpl;
01514 
01515     // To allow access to the skeleton generation code:
01516     friend class impl::GeneratorHelpers;
01517 };
01518 
01519 // Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
01521 struct U_I18N_API MacroProps : public UMemory {
01523     Notation notation;
01524 
01526     MeasureUnit unit;  // = MeasureUnit();  (the base dimensionless unit)
01527 
01529     MeasureUnit perUnit;  // = MeasureUnit();  (the base dimensionless unit)
01530 
01532     Precision precision;  // = Precision();  (bogus)
01533 
01535     UNumberFormatRoundingMode roundingMode = UNUM_ROUND_HALFEVEN;
01536 
01538     Grouper grouper;  // = Grouper();  (bogus)
01539 
01541     Padder padder;    // = Padder();   (bogus)
01542 
01544     IntegerWidth integerWidth; // = IntegerWidth(); (bogus)
01545 
01547     SymbolsWrapper symbols;
01548 
01549     // UNUM_XYZ_COUNT denotes null (bogus) values.
01550 
01552     UNumberUnitWidth unitWidth = UNUM_UNIT_WIDTH_COUNT;
01553 
01555     UNumberSignDisplay sign = UNUM_SIGN_COUNT;
01556 
01558     bool approximately = false;
01559 
01561     UNumberDecimalSeparatorDisplay decimal = UNUM_DECIMAL_SEPARATOR_COUNT;
01562 
01564     Scale scale;  // = Scale();  (benign value)
01565 
01567     StringProp usage;  // = StringProp();  (no usage)
01568 
01570     StringProp unitDisplayCase;  // = StringProp();  (nominative)
01571 
01573     const AffixPatternProvider* affixProvider = nullptr;  // no ownership
01574 
01576     const PluralRules* rules = nullptr;  // no ownership
01577 
01579     int32_t threshold = kInternalDefaultThreshold;
01580 
01582     Locale locale;
01583 
01584     // NOTE: Uses default copy and move constructors.
01585 
01590     bool copyErrorTo(UErrorCode &status) const {
01591         return notation.copyErrorTo(status) || precision.copyErrorTo(status) ||
01592                padder.copyErrorTo(status) || integerWidth.copyErrorTo(status) ||
01593                symbols.copyErrorTo(status) || scale.copyErrorTo(status) || usage.copyErrorTo(status) ||
01594                unitDisplayCase.copyErrorTo(status);
01595     }
01596 };
01597 
01598 } // namespace impl
01599 
01600 #if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER)
01601 // Ignore MSVC warning 4661. This is generated for NumberFormatterSettings<>::toSkeleton() as this method
01602 // is defined elsewhere (in number_skeletons.cpp). The compiler is warning that the explicit template instantiation
01603 // inside this single translation unit (CPP file) is incomplete, and thus it isn't sure if the template class is
01604 // fully defined. However, since each translation unit explicitly instantiates all the necessary template classes,
01605 // they will all be passed to the linker, and the linker will still find and export all the class members.
01606 #pragma warning(push)
01607 #pragma warning(disable: 4661)
01608 #endif
01609 
01615 template<typename Derived>
01616 class U_I18N_API NumberFormatterSettings {
01617   public:
01646     Derived notation(const Notation &notation) const &;
01647 
01657     Derived notation(const Notation &notation) &&;
01658 
01707     Derived unit(const icu::MeasureUnit &unit) const &;
01708 
01718     Derived unit(const icu::MeasureUnit &unit) &&;
01719 
01733     Derived adoptUnit(icu::MeasureUnit *unit) const &;
01734 
01744     Derived adoptUnit(icu::MeasureUnit *unit) &&;
01745 
01768     Derived perUnit(const icu::MeasureUnit &perUnit) const &;
01769 
01779     Derived perUnit(const icu::MeasureUnit &perUnit) &&;
01780 
01794     Derived adoptPerUnit(icu::MeasureUnit *perUnit) const &;
01795 
01805     Derived adoptPerUnit(icu::MeasureUnit *perUnit) &&;
01806 
01837     Derived precision(const Precision& precision) const &;
01838 
01848     Derived precision(const Precision& precision) &&;
01849 
01868     Derived roundingMode(UNumberFormatRoundingMode roundingMode) const &;
01869 
01878     Derived roundingMode(UNumberFormatRoundingMode roundingMode) &&;
01879 
01907     Derived grouping(UNumberGroupingStrategy strategy) const &;
01908 
01918     Derived grouping(UNumberGroupingStrategy strategy) &&;
01919 
01944     Derived integerWidth(const IntegerWidth &style) const &;
01945 
01955     Derived integerWidth(const IntegerWidth &style) &&;
01956 
01997     Derived symbols(const DecimalFormatSymbols &symbols) const &;
01998 
02008     Derived symbols(const DecimalFormatSymbols &symbols) &&;
02009 
02043     Derived adoptSymbols(NumberingSystem *symbols) const &;
02044 
02054     Derived adoptSymbols(NumberingSystem *symbols) &&;
02055 
02081     Derived unitWidth(UNumberUnitWidth width) const &;
02082 
02092     Derived unitWidth(UNumberUnitWidth width) &&;
02093 
02119     Derived sign(UNumberSignDisplay style) const &;
02120 
02130     Derived sign(UNumberSignDisplay style) &&;
02131 
02157     Derived decimal(UNumberDecimalSeparatorDisplay style) const &;
02158 
02168     Derived decimal(UNumberDecimalSeparatorDisplay style) &&;
02169 
02194     Derived scale(const Scale &scale) const &;
02195 
02205     Derived scale(const Scale &scale) &&;
02206 
02249     Derived usage(StringPiece usage) const &;
02250 
02258     Derived usage(StringPiece usage) &&;
02259 
02260 #ifndef U_HIDE_DRAFT_API
02261 
02269     Derived displayOptions(const DisplayOptions &displayOptions) const &;
02270 
02278     Derived displayOptions(const DisplayOptions &displayOptions) &&;
02279 #endif // U_HIDE_DRAFT_API
02280 
02281 #ifndef U_HIDE_INTERNAL_API
02282 
02292     Derived unitDisplayCase(StringPiece unitDisplayCase) const &;
02293 
02303     Derived unitDisplayCase(StringPiece unitDisplayCase) &&;
02304 #endif // U_HIDE_INTERNAL_API
02305 
02306 #ifndef U_HIDE_INTERNAL_API
02307 
02313     Derived padding(const impl::Padder &padder) const &;
02314 
02316     Derived padding(const impl::Padder &padder) &&;
02317 
02324     Derived threshold(int32_t threshold) const &;
02325 
02327     Derived threshold(int32_t threshold) &&;
02328 
02334     Derived macros(const impl::MacroProps& macros) const &;
02335 
02337     Derived macros(const impl::MacroProps& macros) &&;
02338 
02340     Derived macros(impl::MacroProps&& macros) const &;
02341 
02343     Derived macros(impl::MacroProps&& macros) &&;
02344 
02345 #endif  /* U_HIDE_INTERNAL_API */
02346 
02364     UnicodeString toSkeleton(UErrorCode& status) const;
02365 
02377     LocalPointer<Derived> clone() const &;
02378 
02386     LocalPointer<Derived> clone() &&;
02387 
02394     UBool copyErrorTo(UErrorCode &outErrorCode) const {
02395         if (U_FAILURE(outErrorCode)) {
02396             // Do not overwrite the older error code
02397             return true;
02398         }
02399         fMacros.copyErrorTo(outErrorCode);
02400         return U_FAILURE(outErrorCode);
02401     }
02402 
02403     // NOTE: Uses default copy and move constructors.
02404 
02405   private:
02406     impl::MacroProps fMacros;
02407 
02408     // Don't construct me directly!  Use (Un)LocalizedNumberFormatter.
02409     NumberFormatterSettings() = default;
02410 
02411     friend class LocalizedNumberFormatter;
02412     friend class UnlocalizedNumberFormatter;
02413 
02414     // Give NumberRangeFormatter access to the MacroProps
02415     friend void impl::touchRangeLocales(impl::RangeMacroProps& macros);
02416     friend class impl::NumberRangeFormatterImpl;
02417 };
02418 
02419 // Explicit instantiations in source/i18n/number_fluent.cpp.
02420 // (MSVC treats imports/exports of explicit instantiations differently.)
02421 #ifndef _MSC_VER
02422 extern template class NumberFormatterSettings<UnlocalizedNumberFormatter>;
02423 extern template class NumberFormatterSettings<LocalizedNumberFormatter>;
02424 #endif
02425 
02434 class U_I18N_API UnlocalizedNumberFormatter
02435         : public NumberFormatterSettings<UnlocalizedNumberFormatter>, public UMemory {
02436 
02437   public:
02447     LocalizedNumberFormatter locale(const icu::Locale &locale) const &;
02448 
02458     LocalizedNumberFormatter locale(const icu::Locale &locale) &&;
02459 
02465     UnlocalizedNumberFormatter() = default;
02466 
02471     UnlocalizedNumberFormatter(const UnlocalizedNumberFormatter &other);
02472 
02478     UnlocalizedNumberFormatter(UnlocalizedNumberFormatter&& src) noexcept;
02479 
02484     UnlocalizedNumberFormatter& operator=(const UnlocalizedNumberFormatter& other);
02485 
02491     UnlocalizedNumberFormatter& operator=(UnlocalizedNumberFormatter&& src) noexcept;
02492 
02493   private:
02494     explicit UnlocalizedNumberFormatter(const NumberFormatterSettings<UnlocalizedNumberFormatter>& other);
02495 
02496     explicit UnlocalizedNumberFormatter(
02497             NumberFormatterSettings<UnlocalizedNumberFormatter>&& src) noexcept;
02498 
02499     // To give the fluent setters access to this class's constructor:
02500     friend class NumberFormatterSettings<UnlocalizedNumberFormatter>;
02501 
02502     // To give NumberFormatter::with() access to this class's constructor:
02503     friend class NumberFormatter;
02504 };
02505 
02514 class U_I18N_API LocalizedNumberFormatter
02515         : public NumberFormatterSettings<LocalizedNumberFormatter>, public UMemory {
02516   public:
02528     FormattedNumber formatInt(int64_t value, UErrorCode &status) const;
02529 
02541     FormattedNumber formatDouble(double value, UErrorCode &status) const;
02542 
02557     FormattedNumber formatDecimal(StringPiece value, UErrorCode& status) const;
02558 
02559 #ifndef U_HIDE_INTERNAL_API
02560 
02561             
02565     const DecimalFormatSymbols* getDecimalFormatSymbols() const;
02566     
02570     FormattedNumber formatDecimalQuantity(const impl::DecimalQuantity& dq, UErrorCode& status) const;
02571 
02575     void getAffixImpl(bool isPrefix, bool isNegative, UnicodeString& result, UErrorCode& status) const;
02576 
02581     const impl::NumberFormatterImpl* getCompiled() const;
02582 
02587     int32_t getCallCount() const;
02588 
02589 #endif  /* U_HIDE_INTERNAL_API */
02590 
02604     Format* toFormat(UErrorCode& status) const;
02605 
02611     LocalizedNumberFormatter() = default;
02612 
02617     LocalizedNumberFormatter(const LocalizedNumberFormatter &other);
02618 
02624     LocalizedNumberFormatter(LocalizedNumberFormatter&& src) noexcept;
02625 
02630     LocalizedNumberFormatter& operator=(const LocalizedNumberFormatter& other);
02631 
02637     LocalizedNumberFormatter& operator=(LocalizedNumberFormatter&& src) noexcept;
02638 
02639 #ifndef U_HIDE_INTERNAL_API
02640 
02653     void formatImpl(impl::UFormattedNumberData *results, UErrorCode &status) const;
02654 
02655 #endif  /* U_HIDE_INTERNAL_API */
02656 
02661     ~LocalizedNumberFormatter();
02662 
02663   private:
02664     // Note: fCompiled can't be a LocalPointer because impl::NumberFormatterImpl is defined in an internal
02665     // header, and LocalPointer needs the full class definition in order to delete the instance.
02666     const impl::NumberFormatterImpl* fCompiled {nullptr};
02667     char fUnsafeCallCount[8] {};  // internally cast to u_atomic_int32_t
02668 
02669     // Owned pointer to a DecimalFormatWarehouse, used when copying a LocalizedNumberFormatter
02670     // from a DecimalFormat.
02671     const impl::DecimalFormatWarehouse* fWarehouse {nullptr};
02672 
02673     explicit LocalizedNumberFormatter(const NumberFormatterSettings<LocalizedNumberFormatter>& other);
02674 
02675     explicit LocalizedNumberFormatter(NumberFormatterSettings<LocalizedNumberFormatter>&& src) noexcept;
02676 
02677     LocalizedNumberFormatter(const impl::MacroProps &macros, const Locale &locale);
02678 
02679     LocalizedNumberFormatter(impl::MacroProps &&macros, const Locale &locale);
02680 
02681     void resetCompiled();
02682 
02683     void lnfMoveHelper(LocalizedNumberFormatter&& src);
02684 
02685     void lnfCopyHelper(const LocalizedNumberFormatter& src, UErrorCode& status);
02686 
02690     bool computeCompiled(UErrorCode& status) const;
02691 
02692     // To give the fluent setters access to this class's constructor:
02693     friend class NumberFormatterSettings<UnlocalizedNumberFormatter>;
02694     friend class NumberFormatterSettings<LocalizedNumberFormatter>;
02695 
02696     // To give UnlocalizedNumberFormatter::locale() access to this class's constructor:
02697     friend class UnlocalizedNumberFormatter;
02698 };
02699 
02700 #if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER)
02701 // Warning 4661.
02702 #pragma warning(pop)
02703 #endif
02704 
02710 class U_I18N_API NumberFormatter final {
02711   public:
02719     static UnlocalizedNumberFormatter with();
02720 
02730     static LocalizedNumberFormatter withLocale(const Locale &locale);
02731 
02749     static UnlocalizedNumberFormatter forSkeleton(const UnicodeString& skeleton, UErrorCode& status);
02750 
02771     static UnlocalizedNumberFormatter forSkeleton(const UnicodeString& skeleton,
02772                                                   UParseError& perror, UErrorCode& status);
02773 
02777     NumberFormatter() = delete;
02778 };
02779 
02780 }  // namespace number
02781 U_NAMESPACE_END
02782 
02783 #endif /* #if !UCONFIG_NO_FORMATTING */
02784 
02785 #endif /* U_SHOW_CPLUSPLUS_API */
02786 
02787 #endif // __NUMBERFORMATTER_H__