/* ******************************************************************************** * Copyright (C) 2015, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************** * * File decimfmtimpl.h ******************************************************************************** */ #ifndef DECIMFMTIMPL_H #define DECIMFMTIMPL_H #include "unicode/decimfmt.h" #include "unicode/uobject.h" #include "unicode/utypes.h" #include "affixpatternparser.h" #include "digitaffixesandpadding.h" #include "digitformatter.h" #include "digitgrouping.h" #include "precision.h" U_NAMESPACE_BEGIN class UnicodeString; class FieldPosition; class ValueFormatter; class FieldPositionHandler; class FixedDecimal; class DecimalFormatImpl : public UObject { public: DecimalFormatImpl( NumberFormat *super, const Locale &locale, const UnicodeString &pattern, UErrorCode &status); DecimalFormatImpl( NumberFormat *super, const UnicodeString &pattern, DecimalFormatSymbols *symbolsToAdopt, UParseError &parseError, UErrorCode &status); DecimalFormatImpl( NumberFormat *super, const DecimalFormatImpl &other, UErrorCode &status); DecimalFormatImpl &assign( const DecimalFormatImpl &other, UErrorCode &status); virtual ~DecimalFormatImpl(); void adoptDecimalFormatSymbols(DecimalFormatSymbols *symbolsToAdopt); const DecimalFormatSymbols &getDecimalFormatSymbols() const { return *fSymbols; } UnicodeString &format( int32_t number, UnicodeString &appendTo, FieldPosition &pos, UErrorCode &status) const; UnicodeString &format( int32_t number, UnicodeString &appendTo, FieldPositionIterator *posIter, UErrorCode &status) const; UnicodeString &format( int64_t number, UnicodeString &appendTo, FieldPosition &pos, UErrorCode &status) const; UnicodeString &format( double number, UnicodeString &appendTo, FieldPosition &pos, UErrorCode &status) const; UnicodeString &format( const DigitList &number, UnicodeString &appendTo, FieldPosition &pos, UErrorCode &status) const; UnicodeString &format( int64_t number, UnicodeString &appendTo, FieldPositionIterator *posIter, UErrorCode &status) const; UnicodeString &format( double number, UnicodeString &appendTo, FieldPositionIterator *posIter, UErrorCode &status) const; UnicodeString &format( const DigitList &number, UnicodeString &appendTo, FieldPositionIterator *posIter, UErrorCode &status) const; UnicodeString &format( const StringPiece &number, UnicodeString &appendTo, FieldPositionIterator *posIter, UErrorCode &status) const; UnicodeString &format( const VisibleDigitsWithExponent &digits, UnicodeString &appendTo, FieldPosition &pos, UErrorCode &status) const; UnicodeString &format( const VisibleDigitsWithExponent &digits, UnicodeString &appendTo, FieldPositionIterator *posIter, UErrorCode &status) const; UBool operator==(const DecimalFormatImpl &) const; UBool operator!=(const DecimalFormatImpl &other) const { return !(*this == other); } void setRoundingMode(DecimalFormat::ERoundingMode mode) { fRoundingMode = mode; fEffPrecision.fMantissa.fExactOnly = (fRoundingMode == DecimalFormat::kRoundUnnecessary); fEffPrecision.fMantissa.fRoundingMode = mode; } DecimalFormat::ERoundingMode getRoundingMode() const { return fRoundingMode; } void setFailIfMoreThanMaxDigits(UBool b) { fEffPrecision.fMantissa.fFailIfOverMax = b; } UBool isFailIfMoreThanMaxDigits() const { return fEffPrecision.fMantissa.fFailIfOverMax; } void setMinimumSignificantDigits(int32_t newValue); void setMaximumSignificantDigits(int32_t newValue); void setMinMaxSignificantDigits(int32_t min, int32_t max); void setScientificNotation(UBool newValue); void setSignificantDigitsUsed(UBool newValue); int32_t getMinimumSignificantDigits() const { return fMinSigDigits; } int32_t getMaximumSignificantDigits() const { return fMaxSigDigits; } UBool isScientificNotation() const { return fUseScientific; } UBool areSignificantDigitsUsed() const { return fUseSigDigits; } void setGroupingSize(int32_t newValue); void setSecondaryGroupingSize(int32_t newValue); void setMinimumGroupingDigits(int32_t newValue); int32_t getGroupingSize() const { return fGrouping.fGrouping; } int32_t getSecondaryGroupingSize() const { return fGrouping.fGrouping2; } int32_t getMinimumGroupingDigits() const { return fGrouping.fMinGrouping; } void applyPattern(const UnicodeString &pattern, UErrorCode &status); void applyPatternFavorCurrencyPrecision( const UnicodeString &pattern, UErrorCode &status); void applyPattern( const UnicodeString &pattern, UParseError &perror, UErrorCode &status); void applyLocalizedPattern(const UnicodeString &pattern, UErrorCode &status); void applyLocalizedPattern( const UnicodeString &pattern, UParseError &perror, UErrorCode &status); void setCurrencyUsage(UCurrencyUsage usage, UErrorCode &status); UCurrencyUsage getCurrencyUsage() const { return fCurrencyUsage; } void setRoundingIncrement(double d); double getRoundingIncrement() const; int32_t getMultiplier() const; void setMultiplier(int32_t m); UChar32 getPadCharacter() const { return fAffixes.fPadChar; } void setPadCharacter(UChar32 c) { fAffixes.fPadChar = c; } int32_t getFormatWidth() const { return fAffixes.fWidth; } void setFormatWidth(int32_t x) { fAffixes.fWidth = x; } DigitAffixesAndPadding::EPadPosition getPadPosition() const { return fAffixes.fPadPosition; } void setPadPosition(DigitAffixesAndPadding::EPadPosition x) { fAffixes.fPadPosition = x; } int32_t getMinimumExponentDigits() const { return fEffPrecision.fMinExponentDigits; } void setMinimumExponentDigits(int32_t x) { fEffPrecision.fMinExponentDigits = x; } UBool isExponentSignAlwaysShown() const { return fOptions.fExponent.fAlwaysShowSign; } void setExponentSignAlwaysShown(UBool x) { fOptions.fExponent.fAlwaysShowSign = x; } UBool isDecimalSeparatorAlwaysShown() const { return fOptions.fMantissa.fAlwaysShowDecimal; } void setDecimalSeparatorAlwaysShown(UBool x) { fOptions.fMantissa.fAlwaysShowDecimal = x; } UnicodeString &getPositivePrefix(UnicodeString &result) const; UnicodeString &getPositiveSuffix(UnicodeString &result) const; UnicodeString &getNegativePrefix(UnicodeString &result) const; UnicodeString &getNegativeSuffix(UnicodeString &result) const; void setPositivePrefix(const UnicodeString &str); void setPositiveSuffix(const UnicodeString &str); void setNegativePrefix(const UnicodeString &str); void setNegativeSuffix(const UnicodeString &str); UnicodeString &toPattern(UnicodeString& result) const; FixedDecimal &getFixedDecimal(double value, FixedDecimal &result, UErrorCode &status) const; FixedDecimal &getFixedDecimal(DigitList &number, FixedDecimal &result, UErrorCode &status) const; DigitList &round(DigitList &number, UErrorCode &status) const; VisibleDigitsWithExponent & initVisibleDigitsWithExponent( int64_t number, VisibleDigitsWithExponent &digits, UErrorCode &status) const; VisibleDigitsWithExponent & initVisibleDigitsWithExponent( double number, VisibleDigitsWithExponent &digits, UErrorCode &status) const; VisibleDigitsWithExponent & initVisibleDigitsWithExponent( DigitList &number, VisibleDigitsWithExponent &digits, UErrorCode &status) const; void updatePrecision(); void updateGrouping(); void updateCurrency(UErrorCode &status); private: // Disallow copy and assign DecimalFormatImpl(const DecimalFormatImpl &other); DecimalFormatImpl &operator=(const DecimalFormatImpl &other); NumberFormat *fSuper; DigitList fMultiplier; int32_t fScale; DecimalFormat::ERoundingMode fRoundingMode; // These fields include what the user can see and set. // When the user updates these fields, it triggers automatic updates of // other fields that may be invisible to user // Updating any of the following fields triggers an update to // fEffPrecision.fMantissa.fMin, // fEffPrecision.fMantissa.fMax, // fEffPrecision.fMantissa.fSignificant fields // We have this two phase update because of backward compatibility. // DecimalFormat has to remember all settings even if those settings are // invalid or disabled. int32_t fMinSigDigits; int32_t fMaxSigDigits; UBool fUseScientific; UBool fUseSigDigits; // In addition to these listed above, changes to min/max int digits and // min/max frac digits from fSuper also trigger an update. // Updating any of the following fields triggers an update to // fEffGrouping field Again we do it this way because original // grouping settings have to be retained if grouping is turned off. DigitGrouping fGrouping; // In addition to these listed above, changes to isGroupingUsed in // fSuper also triggers an update to fEffGrouping. // Updating any of the following fields triggers updates on the following: // fMonetary, fRules, fAffixParser, fCurrencyAffixInfo, // fFormatter, fAffixes.fPositivePrefiix, fAffixes.fPositiveSuffix, // fAffixes.fNegativePrefiix, fAffixes.fNegativeSuffix // We do this two phase update because localizing the affix patterns // and formatters can be expensive. Better to do it once with the setters // than each time within format. AffixPattern fPositivePrefixPattern; AffixPattern fNegativePrefixPattern; AffixPattern fPositiveSuffixPattern; AffixPattern fNegativeSuffixPattern; DecimalFormatSymbols *fSymbols; UCurrencyUsage fCurrencyUsage; // In addition to these listed above, changes to getCurrency() in // fSuper also triggers an update. // Optional may be NULL PluralRules *fRules; // These fields are totally hidden from user and are used to derive the affixes // in fAffixes below from the four affix patterns above. UBool fMonetary; AffixPatternParser fAffixParser; CurrencyAffixInfo fCurrencyAffixInfo; // The actual precision used when formatting ScientificPrecision fEffPrecision; // The actual grouping used when formatting DigitGrouping fEffGrouping; SciFormatterOptions fOptions; // Encapsulates fixed precision options DigitFormatter fFormatter; DigitAffixesAndPadding fAffixes; UnicodeString &formatInt32( int32_t number, UnicodeString &appendTo, FieldPositionHandler &handler, UErrorCode &status) const; UnicodeString &formatInt64( int64_t number, UnicodeString &appendTo, FieldPositionHandler &handler, UErrorCode &status) const; UnicodeString &formatDouble( double number, UnicodeString &appendTo, FieldPositionHandler &handler, UErrorCode &status) const; // Scales for precent or permille symbols UnicodeString &formatDigitList( DigitList &number, UnicodeString &appendTo, FieldPositionHandler &handler, UErrorCode &status) const; // Does not scale for precent or permille symbols UnicodeString &formatAdjustedDigitList( DigitList &number, UnicodeString &appendTo, FieldPositionHandler &handler, UErrorCode &status) const; UnicodeString &formatVisibleDigitsWithExponent( const VisibleDigitsWithExponent &number, UnicodeString &appendTo, FieldPositionHandler &handler, UErrorCode &status) const; VisibleDigitsWithExponent & initVisibleDigitsFromAdjusted( DigitList &number, VisibleDigitsWithExponent &digits, UErrorCode &status) const; template UBool maybeFormatWithDigitList( T number, UnicodeString &appendTo, FieldPositionHandler &handler, UErrorCode &status) const; template UBool maybeInitVisibleDigitsFromDigitList( T number, VisibleDigitsWithExponent &digits, UErrorCode &status) const; DigitList &adjustDigitList(DigitList &number, UErrorCode &status) const; void applyPattern( const UnicodeString &pattern, UBool localized, UParseError &perror, UErrorCode &status); ValueFormatter &prepareValueFormatter(ValueFormatter &vf) const; void setMultiplierScale(int32_t s); int32_t getPatternScale() const; void setScale(int32_t s) { fScale = s; } int32_t getScale() const { return fScale; } // Updates everything void updateAll(UErrorCode &status); void updateAll( int32_t formattingFlags, UBool updatePrecisionBasedOnCurrency, UErrorCode &status); // Updates from formatting pattern changes void updateForApplyPattern(UErrorCode &status); void updateForApplyPatternFavorCurrencyPrecision(UErrorCode &status); // Updates from changes to third group of attributes void updateFormatting(int32_t changedFormattingFields, UErrorCode &status); void updateFormatting( int32_t changedFormattingFields, UBool updatePrecisionBasedOnCurrency, UErrorCode &status); // Helper functions for updatePrecision void updatePrecisionForScientific(); void updatePrecisionForFixed(); void extractMinMaxDigits(DigitInterval &min, DigitInterval &max) const; void extractSigDigits(SignificantDigitInterval &sig) const; // Helper functions for updateFormatting void updateFormattingUsesCurrency(int32_t &changedFormattingFields); void updateFormattingPluralRules( int32_t &changedFormattingFields, UErrorCode &status); void updateFormattingAffixParser(int32_t &changedFormattingFields); void updateFormattingCurrencyAffixInfo( int32_t &changedFormattingFields, UBool updatePrecisionBasedOnCurrency, UErrorCode &status); void updateFormattingFixedPointFormatter( int32_t &changedFormattingFields); void updateFormattingLocalizedPositivePrefix( int32_t &changedFormattingFields, UErrorCode &status); void updateFormattingLocalizedPositiveSuffix( int32_t &changedFormattingFields, UErrorCode &status); void updateFormattingLocalizedNegativePrefix( int32_t &changedFormattingFields, UErrorCode &status); void updateFormattingLocalizedNegativeSuffix( int32_t &changedFormattingFields, UErrorCode &status); int32_t computeExponentPatternLength() const; int32_t countFractionDigitAndDecimalPatternLength(int32_t fracDigitCount) const; UnicodeString &toNumberPattern( UBool hasPadding, int32_t minimumLength, UnicodeString& result) const; int32_t getOldFormatWidth() const; const UnicodeString &getConstSymbol( DecimalFormatSymbols::ENumberFormatSymbol symbol) const; UBool isParseFastpath() const; friend class DecimalFormat; }; U_NAMESPACE_END #endif // DECIMFMTIMPL_H //eof