00001
00002
00003
00004 #include "unicode/utypes.h"
00005
00006 #if !UCONFIG_NO_FORMATTING
00007 #ifndef __NUMBERFORMATTER_H__
00008 #define __NUMBERFORMATTER_H__
00009
00010 #include "unicode/appendable.h"
00011 #include "unicode/dcfmtsym.h"
00012 #include "unicode/currunit.h"
00013 #include "unicode/fieldpos.h"
00014 #include "unicode/fpositer.h"
00015 #include "unicode/measunit.h"
00016 #include "unicode/nounit.h"
00017 #include "unicode/plurrule.h"
00018 #include "unicode/ucurr.h"
00019 #include "unicode/unum.h"
00020
00021 #ifndef U_HIDE_DRAFT_API
00022
00099 typedef enum UNumberUnitWidth {
00111 UNUM_UNIT_WIDTH_NARROW,
00112
00127 UNUM_UNIT_WIDTH_SHORT,
00128
00138 UNUM_UNIT_WIDTH_FULL_NAME,
00139
00149 UNUM_UNIT_WIDTH_ISO_CODE,
00150
00158 UNUM_UNIT_WIDTH_HIDDEN,
00159
00165 UNUM_UNIT_WIDTH_COUNT
00166 } UNumberUnitWidth;
00167
00186 typedef enum UNumberSignDisplay {
00193 UNUM_SIGN_AUTO,
00194
00200 UNUM_SIGN_ALWAYS,
00201
00207 UNUM_SIGN_NEVER,
00208
00223 UNUM_SIGN_ACCOUNTING,
00224
00231 UNUM_SIGN_ACCOUNTING_ALWAYS,
00232
00238 UNUM_SIGN_COUNT
00239 } UNumberSignDisplay;
00240
00250 typedef enum UNumberDecimalSeparatorDisplay {
00257 UNUM_DECIMAL_SEPARATOR_AUTO,
00258
00264 UNUM_DECIMAL_SEPARATOR_ALWAYS,
00265
00271 UNUM_DECIMAL_SEPARATOR_COUNT
00272 } UNumberDecimalMarkDisplay;
00273
00274 U_NAMESPACE_BEGIN namespace number {
00275
00276
00277 class UnlocalizedNumberFormatter;
00278 class LocalizedNumberFormatter;
00279 class FormattedNumber;
00280 class Notation;
00281 class ScientificNotation;
00282 class Rounder;
00283 class FractionRounder;
00284 class CurrencyRounder;
00285 class IncrementRounder;
00286 class Grouper;
00287 class IntegerWidth;
00288
00289 namespace impl {
00290
00291
00292 class Padder;
00293 struct MacroProps;
00294 struct MicroProps;
00295 class DecimalQuantity;
00296 struct NumberFormatterResults;
00297 class NumberFormatterImpl;
00298 struct ParsedPatternInfo;
00299 class ScientificModifier;
00300 class MultiplierProducer;
00301 class MutablePatternModifier;
00302 class LongNameHandler;
00303 class ScientificHandler;
00304 class CompactHandler;
00305 class Modifier;
00306 class NumberStringBuilder;
00307
00308 }
00309
00310
00311 typedef Notation CompactNotation;
00312 typedef Notation SimpleNotation;
00313
00319 class U_I18N_API Notation : public UMemory {
00320 public:
00345 static ScientificNotation scientific();
00346
00369 static ScientificNotation engineering();
00370
00412 static CompactNotation compactShort();
00413
00436 static CompactNotation compactLong();
00437
00462 static SimpleNotation simple();
00463
00464 private:
00465 enum NotationType {
00466 NTN_SCIENTIFIC, NTN_COMPACT, NTN_SIMPLE, NTN_ERROR
00467 } fType;
00468
00469 union NotationUnion {
00470
00471 struct ScientificSettings {
00472 int8_t fEngineeringInterval;
00473 bool fRequireMinInt;
00474 int8_t fMinExponentDigits;
00475 UNumberSignDisplay fExponentSignDisplay;
00476 } scientific;
00477
00478
00479 UNumberCompactStyle compactStyle;
00480
00481
00482 UErrorCode errorCode;
00483 } fUnion;
00484
00485 typedef NotationUnion::ScientificSettings ScientificSettings;
00486
00487 Notation(const NotationType &type, const NotationUnion &union_) : fType(type), fUnion(union_) {}
00488
00489 Notation(UErrorCode errorCode) : fType(NTN_ERROR) {
00490 fUnion.errorCode = errorCode;
00491 }
00492
00493 Notation() : fType(NTN_SIMPLE), fUnion() {}
00494
00495 UBool copyErrorTo(UErrorCode &status) const {
00496 if (fType == NTN_ERROR) {
00497 status = fUnion.errorCode;
00498 return TRUE;
00499 }
00500 return FALSE;
00501 }
00502
00503
00504 friend struct impl::MacroProps;
00505 friend class ScientificNotation;
00506
00507
00508 friend class impl::NumberFormatterImpl;
00509 friend class impl::ScientificModifier;
00510 friend class impl::ScientificHandler;
00511 };
00512
00521 class U_I18N_API ScientificNotation : public Notation {
00522 public:
00536 ScientificNotation withMinExponentDigits(int32_t minExponentDigits) const;
00537
00551 ScientificNotation withExponentSignDisplay(UNumberSignDisplay exponentSignDisplay) const;
00552
00553 private:
00554
00555 using Notation::Notation;
00556
00557 friend class Notation;
00558 };
00559
00560
00561 typedef Rounder DigitRounder;
00562
00571 class U_I18N_API Rounder : public UMemory {
00572
00573 public:
00590 static Rounder unlimited();
00591
00598 static FractionRounder integer();
00599
00627 static FractionRounder fixedFraction(int32_t minMaxFractionPlaces);
00628
00642 static FractionRounder minFraction(int32_t minFractionPlaces);
00643
00654 static FractionRounder maxFraction(int32_t maxFractionPlaces);
00655
00669 static FractionRounder minMaxFraction(int32_t minFractionPlaces, int32_t maxFractionPlaces);
00670
00684 static DigitRounder fixedDigits(int32_t minMaxSignificantDigits);
00685
00698 static DigitRounder minDigits(int32_t minSignificantDigits);
00699
00708 static DigitRounder maxDigits(int32_t maxSignificantDigits);
00709
00721 static DigitRounder minMaxDigits(int32_t minSignificantDigits, int32_t maxSignificantDigits);
00722
00742 static IncrementRounder increment(double roundingIncrement);
00743
00760 static CurrencyRounder currency(UCurrencyUsage currencyUsage);
00761
00771 Rounder withMode(UNumberFormatRoundingMode roundingMode) const;
00772
00773 private:
00774 enum RounderType {
00775 RND_BOGUS,
00776 RND_NONE,
00777 RND_FRACTION,
00778 RND_SIGNIFICANT,
00779 RND_FRACTION_SIGNIFICANT,
00780 RND_INCREMENT,
00781 RND_CURRENCY,
00782 RND_PASS_THROUGH,
00783 RND_ERROR
00784 } fType;
00785
00786 union RounderUnion {
00787 struct FractionSignificantSettings {
00788
00789 int8_t fMinFrac;
00790 int8_t fMaxFrac;
00791 int8_t fMinSig;
00792 int8_t fMaxSig;
00793 } fracSig;
00794 struct IncrementSettings {
00795 double fIncrement;
00796 int32_t fMinFrac;
00797 } increment;
00798 UCurrencyUsage currencyUsage;
00799 UErrorCode errorCode;
00800 } fUnion;
00801
00802 typedef RounderUnion::FractionSignificantSettings FractionSignificantSettings;
00803 typedef RounderUnion::IncrementSettings IncrementSettings;
00804
00805 UNumberFormatRoundingMode fRoundingMode;
00806
00807 Rounder(const RounderType &type, const RounderUnion &union_, UNumberFormatRoundingMode roundingMode)
00808 : fType(type), fUnion(union_), fRoundingMode(roundingMode) {}
00809
00810 Rounder(UErrorCode errorCode) : fType(RND_ERROR) {
00811 fUnion.errorCode = errorCode;
00812 }
00813
00814 Rounder() : fType(RND_BOGUS) {}
00815
00816 bool isBogus() const {
00817 return fType == RND_BOGUS;
00818 }
00819
00820 UBool copyErrorTo(UErrorCode &status) const {
00821 if (fType == RND_ERROR) {
00822 status = fUnion.errorCode;
00823 return TRUE;
00824 }
00825 return FALSE;
00826 }
00827
00828
00829 Rounder withCurrency(const CurrencyUnit ¤cy, UErrorCode &status) const;
00830
00832 void setLocaleData(const CurrencyUnit ¤cy, UErrorCode &status);
00833
00834 void apply(impl::DecimalQuantity &value, UErrorCode &status) const;
00835
00837 void apply(impl::DecimalQuantity &value, int32_t minInt, UErrorCode status);
00838
00839 int32_t
00840 chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::MultiplierProducer &producer,
00841 UErrorCode &status);
00842
00843 static FractionRounder constructFraction(int32_t minFrac, int32_t maxFrac);
00844
00845 static Rounder constructSignificant(int32_t minSig, int32_t maxSig);
00846
00847 static Rounder
00848 constructFractionSignificant(const FractionRounder &base, int32_t minSig, int32_t maxSig);
00849
00850 static IncrementRounder constructIncrement(double increment, int32_t minFrac);
00851
00852 static CurrencyRounder constructCurrency(UCurrencyUsage usage);
00853
00854 static Rounder constructPassThrough();
00855
00856
00857 friend struct impl::MacroProps;
00858 friend struct impl::MicroProps;
00859
00860
00861 friend class impl::NumberFormatterImpl;
00862
00863
00864 friend class impl::MutablePatternModifier;
00865 friend class impl::LongNameHandler;
00866 friend class impl::ScientificHandler;
00867 friend class impl::CompactHandler;
00868
00869
00870 friend class FractionRounder;
00871 friend class CurrencyRounder;
00872 friend class IncrementRounder;
00873 };
00874
00884 class U_I18N_API FractionRounder : public Rounder {
00885 public:
00902 Rounder withMinDigits(int32_t minSignificantDigits) const;
00903
00921 Rounder withMaxDigits(int32_t maxSignificantDigits) const;
00922
00923 private:
00924
00925 using Rounder::Rounder;
00926
00927
00928 friend class Rounder;
00929 };
00930
00940 class U_I18N_API CurrencyRounder : public Rounder {
00941 public:
00959 Rounder withCurrency(const CurrencyUnit ¤cy) const;
00960
00961 private:
00962
00963 using Rounder::Rounder;
00964
00965
00966 friend class Rounder;
00967 };
00968
00978 class U_I18N_API IncrementRounder : public Rounder {
00979 public:
00995 Rounder withMinFraction(int32_t minFrac) const;
00996
00997 private:
00998
00999 using Rounder::Rounder;
01000
01001
01002 friend class Rounder;
01003 };
01004
01008 class U_I18N_API Grouper : public UMemory {
01009 public:
01013 static Grouper defaults();
01014
01018 static Grouper minTwoDigits();
01019
01023 static Grouper none();
01024
01025 private:
01026 int8_t fGrouping1;
01027 int8_t fGrouping2;
01028 bool fMin2;
01029
01030 Grouper(int8_t grouping1, int8_t grouping2, bool min2)
01031 : fGrouping1(grouping1), fGrouping2(grouping2), fMin2(min2) {}
01032
01033 Grouper() : fGrouping1(-3) {};
01034
01035 bool isBogus() const {
01036 return fGrouping1 == -3;
01037 }
01038
01040 void setLocaleData(const impl::ParsedPatternInfo &patternInfo);
01041
01042 bool groupAtPosition(int32_t position, const impl::DecimalQuantity &value) const;
01043
01044
01045 friend struct impl::MacroProps;
01046 friend struct impl::MicroProps;
01047
01048
01049 friend class impl::NumberFormatterImpl;
01050 };
01051
01061 class U_I18N_API IntegerWidth : public UMemory {
01062 public:
01075 static IntegerWidth zeroFillTo(int32_t minInt);
01076
01088 IntegerWidth truncateAt(int32_t maxInt);
01089
01090 private:
01091 union {
01092 struct {
01093 int8_t fMinInt;
01094 int8_t fMaxInt;
01095 } minMaxInt;
01096 UErrorCode errorCode;
01097 } fUnion;
01098 bool fHasError = false;
01099
01100 IntegerWidth(int8_t minInt, int8_t maxInt);
01101
01102 IntegerWidth(UErrorCode errorCode) {
01103 fUnion.errorCode = errorCode;
01104 fHasError = true;
01105 }
01106
01107 IntegerWidth() {
01108 fUnion.minMaxInt.fMinInt = -1;
01109 }
01110
01111 bool isBogus() const {
01112 return !fHasError && fUnion.minMaxInt.fMinInt == -1;
01113 }
01114
01115 UBool copyErrorTo(UErrorCode &status) const {
01116 if (fHasError) {
01117 status = fUnion.errorCode;
01118 return TRUE;
01119 }
01120 return FALSE;
01121 }
01122
01123 void apply(impl::DecimalQuantity &quantity, UErrorCode &status) const;
01124
01125
01126 friend struct impl::MacroProps;
01127 friend struct impl::MicroProps;
01128
01129
01130 friend class impl::NumberFormatterImpl;
01131 };
01132
01133 namespace impl {
01134
01141 static constexpr int32_t DEFAULT_THRESHOLD = 3;
01142
01144 class U_I18N_API SymbolsWrapper : public UMemory {
01145 public:
01147 SymbolsWrapper() : fType(SYMPTR_NONE), fPtr{nullptr} {}
01148
01150 SymbolsWrapper(const SymbolsWrapper &other);
01151
01153 ~SymbolsWrapper();
01154
01156 SymbolsWrapper &operator=(const SymbolsWrapper &other);
01157
01162 void setTo(const DecimalFormatSymbols &dfs);
01163
01168 void setTo(const NumberingSystem *ns);
01169
01174 bool isDecimalFormatSymbols() const;
01175
01180 bool isNumberingSystem() const;
01181
01186 const DecimalFormatSymbols *getDecimalFormatSymbols() const;
01187
01192 const NumberingSystem *getNumberingSystem() const;
01193
01195 UBool copyErrorTo(UErrorCode &status) const {
01196 if (fType == SYMPTR_DFS && fPtr.dfs == nullptr) {
01197 status = U_MEMORY_ALLOCATION_ERROR;
01198 return TRUE;
01199 } else if (fType == SYMPTR_NS && fPtr.ns == nullptr) {
01200 status = U_MEMORY_ALLOCATION_ERROR;
01201 return TRUE;
01202 }
01203 return FALSE;
01204 }
01205
01206 private:
01207 enum SymbolsPointerType {
01208 SYMPTR_NONE, SYMPTR_DFS, SYMPTR_NS
01209 } fType;
01210
01211 union {
01212 const DecimalFormatSymbols *dfs;
01213 const NumberingSystem *ns;
01214 } fPtr;
01215
01216 void doCopyFrom(const SymbolsWrapper &other);
01217
01218 void doCleanup();
01219 };
01220
01222 class U_I18N_API Padder : public UMemory {
01223 public:
01225 static Padder none();
01226
01228 static Padder codePoints(UChar32 cp, int32_t targetWidth, UNumberFormatPadPosition position);
01229
01230 private:
01231 UChar32 fWidth;
01232 union {
01233 struct {
01234 int32_t fCp;
01235 UNumberFormatPadPosition fPosition;
01236 } padding;
01237 UErrorCode errorCode;
01238 } fUnion;
01239
01240 Padder(UChar32 cp, int32_t width, UNumberFormatPadPosition position);
01241
01242 Padder(int32_t width);
01243
01244 Padder(UErrorCode errorCode) : fWidth(-3) {
01245 fUnion.errorCode = errorCode;
01246 }
01247
01248 Padder() : fWidth(-2) {}
01249
01250 bool isBogus() const {
01251 return fWidth == -2;
01252 }
01253
01254 UBool copyErrorTo(UErrorCode &status) const {
01255 if (fWidth == -3) {
01256 status = fUnion.errorCode;
01257 return TRUE;
01258 }
01259 return FALSE;
01260 }
01261
01262 bool isValid() const {
01263 return fWidth > 0;
01264 }
01265
01266 int32_t padAndApply(const impl::Modifier &mod1, const impl::Modifier &mod2,
01267 impl::NumberStringBuilder &string, int32_t leftIndex, int32_t rightIndex,
01268 UErrorCode &status) const;
01269
01270
01271 friend struct MacroProps;
01272 friend struct MicroProps;
01273
01274
01275 friend class impl::NumberFormatterImpl;
01276 };
01277
01279 struct U_I18N_API MacroProps : public UMemory {
01281 Notation notation;
01282
01284 MeasureUnit unit;
01285
01287 Rounder rounder;
01288
01290 Grouper grouper;
01291
01293 Padder padder;
01294
01296 IntegerWidth integerWidth;
01297
01299 SymbolsWrapper symbols;
01300
01301
01302
01304 UNumberUnitWidth unitWidth = UNUM_UNIT_WIDTH_COUNT;
01305
01307 UNumberSignDisplay sign = UNUM_SIGN_COUNT;
01308
01310 UNumberDecimalSeparatorDisplay decimal = UNUM_DECIMAL_SEPARATOR_COUNT;
01311
01313 PluralRules *rules = nullptr;
01314
01316 int32_t threshold = DEFAULT_THRESHOLD;
01317 Locale locale;
01318
01323 bool copyErrorTo(UErrorCode &status) const {
01324 return notation.copyErrorTo(status) || rounder.copyErrorTo(status) ||
01325 padder.copyErrorTo(status) || integerWidth.copyErrorTo(status) ||
01326 symbols.copyErrorTo(status);
01327 }
01328 };
01329
01330 }
01331
01336 template<typename Derived>
01337 class U_I18N_API NumberFormatterSettings {
01338 public:
01367 Derived notation(const Notation ¬ation) const;
01368
01411 Derived unit(const icu::MeasureUnit &unit) const;
01412
01424 Derived adoptUnit(const icu::MeasureUnit *unit) const;
01425
01457 Derived rounding(const Rounder &rounder) const;
01458
01459 #ifndef U_HIDE_INTERNAL_API
01460
01490 Derived grouping(const Grouper &grouper) const;
01491
01492 #endif
01493
01518 Derived integerWidth(const IntegerWidth &style) const;
01519
01560 Derived symbols(const DecimalFormatSymbols &symbols) const;
01561
01595 Derived adoptSymbols(const NumberingSystem *symbols) const;
01596
01622 Derived unitWidth(const UNumberUnitWidth &width) const;
01623
01650 Derived sign(const UNumberSignDisplay &width) const;
01651
01678 Derived decimal(const UNumberDecimalSeparatorDisplay &width) const;
01679
01680 #ifndef U_HIDE_INTERNAL_API
01681
01687 Derived padding(const impl::Padder &padder) const;
01688
01695 Derived threshold(int32_t threshold) const;
01696
01697 #endif
01698
01705 UBool copyErrorTo(UErrorCode &outErrorCode) const {
01706 if (U_FAILURE(outErrorCode)) {
01707
01708 return TRUE;
01709 }
01710 fMacros.copyErrorTo(outErrorCode);
01711 return U_FAILURE(outErrorCode);
01712 }
01713
01714 protected:
01715 impl::MacroProps fMacros;
01716
01717 private:
01718
01719 NumberFormatterSettings() = default;
01720
01721 friend class LocalizedNumberFormatter;
01722 friend class UnlocalizedNumberFormatter;
01723 };
01724
01731 class U_I18N_API UnlocalizedNumberFormatter
01732 : public NumberFormatterSettings<UnlocalizedNumberFormatter>, public UMemory {
01733
01734 public:
01751 LocalizedNumberFormatter locale(const icu::Locale &locale) const;
01752
01753
01758 UnlocalizedNumberFormatter(const UnlocalizedNumberFormatter &other) : UnlocalizedNumberFormatter(
01759 static_cast<const NumberFormatterSettings<UnlocalizedNumberFormatter> &>(other)) {}
01760
01761 private:
01762 UnlocalizedNumberFormatter() = default;
01763
01764 explicit UnlocalizedNumberFormatter(
01765 const NumberFormatterSettings<UnlocalizedNumberFormatter> &other);
01766
01767
01768 friend class NumberFormatterSettings<UnlocalizedNumberFormatter>;
01769
01770
01771 friend class NumberFormatter;
01772 };
01773
01780 class U_I18N_API LocalizedNumberFormatter
01781 : public NumberFormatterSettings<LocalizedNumberFormatter>, public UMemory {
01782 public:
01794 FormattedNumber formatInt(int64_t value, UErrorCode &status) const;
01795
01807 FormattedNumber formatDouble(double value, UErrorCode &status) const;
01808
01823 FormattedNumber formatDecimal(StringPiece value, UErrorCode &status) const;
01824
01825
01830 LocalizedNumberFormatter(const LocalizedNumberFormatter &other) : LocalizedNumberFormatter(
01831 static_cast<const NumberFormatterSettings<LocalizedNumberFormatter> &>(other)) {}
01832
01837 ~LocalizedNumberFormatter();
01838
01839 private:
01840 const impl::NumberFormatterImpl* fCompiled {nullptr};
01841 char fUnsafeCallCount[8] {};
01842
01843 LocalizedNumberFormatter() = default;
01844
01845 explicit LocalizedNumberFormatter(const NumberFormatterSettings<LocalizedNumberFormatter> &other);
01846
01847 LocalizedNumberFormatter(const impl::MacroProps ¯os, const Locale &locale);
01848
01860 FormattedNumber formatImpl(impl::NumberFormatterResults *results, UErrorCode &status) const;
01861
01862
01863 friend class NumberFormatterSettings<UnlocalizedNumberFormatter>;
01864 friend class NumberFormatterSettings<LocalizedNumberFormatter>;
01865
01866
01867 friend class UnlocalizedNumberFormatter;
01868 };
01869
01876 class U_I18N_API FormattedNumber : public UMemory {
01877 public:
01884 UnicodeString toString() const;
01885
01895 Appendable &appendTo(Appendable &appendable);
01896
01916 void populateFieldPosition(FieldPosition &fieldPosition, UErrorCode &status);
01917
01932 void populateFieldPositionIterator(FieldPositionIterator &iterator, UErrorCode &status);
01933
01938 ~FormattedNumber();
01939
01940 private:
01941
01942 const impl::NumberFormatterResults *fResults;
01943
01944
01945 UErrorCode fErrorCode;
01946
01947 explicit FormattedNumber(impl::NumberFormatterResults *results)
01948 : fResults(results), fErrorCode(U_ZERO_ERROR) {};
01949
01950 explicit FormattedNumber(UErrorCode errorCode)
01951 : fResults(nullptr), fErrorCode(errorCode) {};
01952
01953
01954 friend class LocalizedNumberFormatter;
01955 };
01956
01962 class U_I18N_API NumberFormatter final {
01963 public:
01971 static UnlocalizedNumberFormatter with();
01972
01982 static LocalizedNumberFormatter withLocale(const Locale &locale);
01983
01988 NumberFormatter() = delete;
01989 };
01990
01991 }
01992 U_NAMESPACE_END
01993
01994 #endif // U_HIDE_DRAFT_API
01995
01996 #endif // __NUMBERFORMATTER_H__
01997
01998 #endif