X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/73c04bcfe1096173b00431f0cdc742894b15eef0..4388f060552cc537e71e957d32f35e9d75a61233:/icuSources/i18n/unicode/decimfmt.h diff --git a/icuSources/i18n/unicode/decimfmt.h b/icuSources/i18n/unicode/decimfmt.h index 296906fb..2d54306f 100644 --- a/icuSources/i18n/unicode/decimfmt.h +++ b/icuSources/i18n/unicode/decimfmt.h @@ -1,6 +1,6 @@ /* ******************************************************************************** -* Copyright (C) 1997-2006, International Business Machines +* Copyright (C) 1997-2012, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************** * @@ -20,26 +20,33 @@ * 07/20/98 stephen Changed documentation ******************************************************************************** */ - + #ifndef DECIMFMT_H #define DECIMFMT_H - + #include "unicode/utypes.h" /** - * \file + * \file * \brief C++ API: Formats decimal numbers. */ - + #if !UCONFIG_NO_FORMATTING #include "unicode/dcfmtsym.h" #include "unicode/numfmt.h" #include "unicode/locid.h" +#include "unicode/fpositer.h" +#include "unicode/stringpiece.h" +#include "unicode/curramt.h" U_NAMESPACE_BEGIN class DigitList; class ChoiceFormat; +class CurrencyPluralInfo; +class Hashtable; +class UnicodeSet; +class FieldPositionHandler; /** * DecimalFormat is a concrete subclass of NumberFormat that formats decimal @@ -47,8 +54,8 @@ class ChoiceFormat; * and format numbers in any locale, including support for Western, Arabic, or * Indic digits. It also supports different flavors of numbers, including * integers ("123"), fixed-point numbers ("123.4"), scientific notation - * ("1.23E4"), percentages ("12%"), and currency amounts ("$123"). All of these - * flavors can be easily localized. + * ("1.23E4"), percentages ("12%"), and currency amounts ("$123", "USD123", + * "123 US dollars"). All of these flavors can be easily localized. * *
To obtain a NumberFormat for a specific locale (including the default * locale) call one of NumberFormat's factory methods such as @@ -62,11 +69,11 @@ class ChoiceFormat; * // Normally we would have a GUI with a menu for this * int32_t locCount; * const Locale* locales = NumberFormat::getAvailableLocales(locCount); - * + * * double myNumber = -1234.56; * UErrorCode success = U_ZERO_ERROR; * NumberFormat* form; - * + * * // Print out a number with the localized number, currency and percent * // format for each locale. * UnicodeString countryName; @@ -95,11 +102,32 @@ class ChoiceFormat; * cout << locales[i].getDisplayName(displayName) << ": " << pattern; * cout << " -> " << form->format(myNumber,str) << endl; * form->parse(form->format(myNumber,str), fmtable, success); - * delete form; + * delete form; * } * } * } * \endcode + *
+ * Another example use createInstance(style) + *
+ *
+ * // Print out a number using the localized number, currency, + * // percent, scientific, integer, iso currency, and plural currency + * // format for each locale + * Locale* locale = new Locale("en", "US"); + * double myNumber = 1234.56; + * UErrorCode success = U_ZERO_ERROR; + * UnicodeString str; + * Formattable fmtable; + * for (int j=NumberFormat::kNumberStyle; + * j<=NumberFormat::kPluralCurrencyStyle; + * ++j) { + * NumberFormat* format = NumberFormat::createInstance(locale, j, success); + * str.remove(); + * cout << "format result " << form->format(myNumber, str) << endl; + * format->parse(form->format(myNumber, str), fmtable, success); + * }+ * * *
Patterns * @@ -110,7 +138,7 @@ class ChoiceFormat; * digits. The symbols are stored in a DecimalFormatSymbols * object. When using the NumberFormat factory methods, the * pattern and symbols are read from ICU's locale data. - * + * *
Special Pattern Characters * *
Many characters in a pattern are taken literally; they are matched during @@ -208,6 +236,8 @@ class ChoiceFormat; *
Not indicated in the BNF syntax above: * *
padSpec
may appear before the prefix,
* after the prefix, before the suffix, after the suffix, or not at all.
*
@@ -322,6 +352,12 @@ class ChoiceFormat;
*
* During parsing, grouping separators are ignored. * + *
For currency parsing, the formatter is able to parse every currency + * style formats no matter which style the formatter is constructed with. + * For example, a formatter instance gotten from + * NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can parse + * formats such as "USD1.00" and "3.00 US dollars". + * *
If parse(UnicodeString&,Formattable&,ParsePosition&) * fails to parse a string, it leaves the parse position unchanged. * The convenience method parse(UnicodeString&,Formattable&,UErrorCode&) @@ -346,10 +382,10 @@ class ChoiceFormat; * is set to 5. * *
In the absense of an explicit rounding increment numbers are + * rounded to their formatted width. + * *
min
, then it is set to min
. This
* value has no effect unless areSignificantDigits() returns true.
- * @param min the fewest significant digits to be shown
+ * @param min the fewest significant digits to be shown
* @stable ICU 3.0
*/
void setMinimumSignificantDigits(int32_t min);
@@ -1571,7 +1774,7 @@ public:
* than max
, then it is set to max
.
* This value has no effect unless areSignificantDigits() returns
* true.
- * @param max the most significant digits to be shown
+ * @param max the most significant digits to be shown
* @stable ICU 3.0
*/
void setMaximumSignificantDigits(int32_t max);
@@ -1651,9 +1854,16 @@ public:
virtual UClassID getDynamicClassID(void) const;
private:
+
DecimalFormat(); // default constructor not implemented
- int32_t precision(UBool isIntegral) const;
+ int32_t precision() const;
+
+ /**
+ * Initialize all fields of a new DecimalFormatter.
+ * Common code for use by constructors.
+ */
+ void init();
/**
* Do real work of constructing a new DecimalFormat.
@@ -1678,7 +1888,7 @@ private:
* Does the real work of applying a pattern.
* @param pattern The pattern to be applied.
* @param localized If true, the pattern is localized; else false.
- * @param parseError Struct to recieve information on position
+ * @param parseError Struct to recieve information on position
* of error if an error is encountered
* @param status Output param set to success/failure code on
* exit. If the pattern is invalid, this will be
@@ -1688,61 +1898,122 @@ private:
UBool localized,
UParseError& parseError,
UErrorCode& status);
+
+ /*
+ * similar to applyPattern, but without re-gen affix for currency
+ */
+ void applyPatternInternally(const UnicodeString& pluralCount,
+ const UnicodeString& pattern,
+ UBool localized,
+ UParseError& parseError,
+ UErrorCode& status);
+
+ /*
+ * only apply pattern without expand affixes
+ */
+ void applyPatternWithoutExpandAffix(const UnicodeString& pattern,
+ UBool localized,
+ UParseError& parseError,
+ UErrorCode& status);
+
+
+ /*
+ * expand affixes (after apply patter) and re-compute fFormatWidth
+ */
+ void expandAffixAdjustWidth(const UnicodeString* pluralCount);
+
+
/**
* Do the work of formatting a number, either a double or a long.
*
* @param appendTo Output parameter to receive result.
* Result is appended to existing contents.
- * @param fieldPosition On input: an alignment field, if desired.
- * On output: the offsets of the alignment field.
+ * @param handler Records information about field positions.
* @param digits the digits to be formatted.
* @param isInteger if TRUE format the digits as Integer.
* @return Reference to 'appendTo' parameter.
*/
UnicodeString& subformat(UnicodeString& appendTo,
- FieldPosition& fieldPosition,
- DigitList& digits,
- UBool isInteger) const;
+ FieldPositionHandler& handler,
+ DigitList& digits,
+ UBool isInteger) const;
+
void parse(const UnicodeString& text,
Formattable& result,
ParsePosition& pos,
- UBool parseCurrency) const;
+ UChar* currency) const;
enum {
fgStatusInfinite,
fgStatusLength // Leave last in list.
} StatusFlags;
- UBool subparse(const UnicodeString& text, ParsePosition& parsePosition,
+ UBool subparse(const UnicodeString& text,
+ const UnicodeString* negPrefix,
+ const UnicodeString* negSuffix,
+ const UnicodeString* posPrefix,
+ const UnicodeString* posSuffix,
+ UBool currencyParsing,
+ int8_t type,
+ ParsePosition& parsePosition,
DigitList& digits, UBool* status,
UChar* currency) const;
+ // Mixed style parsing for currency.
+ // It parses against the current currency pattern
+ // using complex affix comparison
+ // parses against the currency plural patterns using complex affix comparison,
+ // and parses against the current pattern using simple affix comparison.
+ UBool parseForCurrency(const UnicodeString& text,
+ ParsePosition& parsePosition,
+ DigitList& digits,
+ UBool* status,
+ UChar* currency) const;
+
int32_t skipPadding(const UnicodeString& text, int32_t position) const;
int32_t compareAffix(const UnicodeString& input,
int32_t pos,
UBool isNegative,
UBool isPrefix,
+ const UnicodeString* affixPat,
+ UBool currencyParsing,
+ int8_t type,
UChar* currency) const;
-
+
static int32_t compareSimpleAffix(const UnicodeString& affix,
const UnicodeString& input,
- int32_t pos);
-
- static int32_t skipRuleWhiteSpace(const UnicodeString& text, int32_t pos);
-
+ int32_t pos,
+ UBool lenient);
+
+ static int32_t skipPatternWhiteSpace(const UnicodeString& text, int32_t pos);
+
static int32_t skipUWhiteSpace(const UnicodeString& text, int32_t pos);
-
+
int32_t compareComplexAffix(const UnicodeString& affixPat,
const UnicodeString& input,
int32_t pos,
+ int8_t type,
UChar* currency) const;
static int32_t match(const UnicodeString& text, int32_t pos, UChar32 ch);
static int32_t match(const UnicodeString& text, int32_t pos, const UnicodeString& str);
+ static UBool matchSymbol(const UnicodeString &text, int32_t position, int32_t length, const UnicodeString &symbol,
+ UnicodeSet *sset, UChar32 schar);
+
+ static UBool matchDecimal(UChar32 symbolChar,
+ UBool sawDecimal, UChar32 sawDecimalChar,
+ const UnicodeSet *sset, UChar32 schar);
+
+ static UBool matchGrouping(UChar32 groupingChar,
+ UBool sawGrouping, UChar32 sawGroupingChar,
+ const UnicodeSet *sset,
+ UChar32 decimalChar, const UnicodeSet *decimalSet,
+ UChar32 schar);
+
/**
* Get a decimal format symbol.
* Returns a const reference to the symbol string.
@@ -1750,15 +2021,18 @@ private:
*/
inline const UnicodeString &getConstSymbol(DecimalFormatSymbols::ENumberFormatSymbol symbol) const;
- int32_t appendAffix(UnicodeString& buf, double number,
- UBool isNegative, UBool isPrefix) const;
+ int32_t appendAffix(UnicodeString& buf,
+ double number,
+ FieldPositionHandler& handler,
+ UBool isNegative,
+ UBool isPrefix) const;
/**
* Append an affix to the given UnicodeString, using quotes if
* there are special characters. Single quotes themselves must be
* escaped in either case.
*/
- void appendAffixPattern(UnicodeString& appendTo, const UnicodeString& affix,
+ void appendAffixPattern(UnicodeString& appendTo, const UnicodeString& affix,
UBool localized) const;
void appendAffixPattern(UnicodeString& appendTo,
@@ -1768,26 +2042,75 @@ private:
void expandAffix(const UnicodeString& pattern,
UnicodeString& affix,
double number,
- UBool doFormat) const;
+ FieldPositionHandler& handler,
+ UBool doFormat,
+ const UnicodeString* pluralCount) const;
- void expandAffixes();
-
- static double round(double a, ERoundingMode mode, UBool isNegative);
+ void expandAffixes(const UnicodeString* pluralCount);
void addPadding(UnicodeString& appendTo,
- FieldPosition& fieldPosition,
+ FieldPositionHandler& handler,
int32_t prefixLen, int32_t suffixLen) const;
UBool isGroupingPosition(int32_t pos) const;
void setCurrencyForSymbols();
+ // similar to setCurrency without re-compute the affixes for currency.
+ // If currency changes, the affix pattern for currency is not changed,
+ // but the affix will be changed. So, affixes need to be
+ // re-computed in setCurrency(), but not in setCurrencyInternally().
+ virtual void setCurrencyInternally(const UChar* theCurrency, UErrorCode& ec);
+
+ // set up currency affix patterns for mix parsing.
+ // The patterns saved here are the affix patterns of default currency
+ // pattern and the unique affix patterns of the plural currency patterns.
+ // Those patterns are used by parseForCurrency().
+ void setupCurrencyAffixPatterns(UErrorCode& status);
+
+ // set up the currency affixes used in currency plural formatting.
+ // It sets up both fAffixesForCurrency for currency pattern if the current
+ // pattern contains 3 currency signs,
+ // and it sets up fPluralAffixesForCurrency for currency plural patterns.
+ void setupCurrencyAffixes(const UnicodeString& pattern,
+ UBool setupForCurrentPattern,
+ UBool setupForPluralPattern,
+ UErrorCode& status);
+
+ // hashtable operations
+ Hashtable* initHashForAffixPattern(UErrorCode& status);
+ Hashtable* initHashForAffix(UErrorCode& status);
+
+ void deleteHashForAffixPattern();
+ void deleteHashForAffix(Hashtable*& table);
+
+ void copyHashForAffixPattern(const Hashtable* source,
+ Hashtable* target, UErrorCode& status);
+ void copyHashForAffix(const Hashtable* source,
+ Hashtable* target, UErrorCode& status);
+
+ UnicodeString& _format(int64_t number,
+ UnicodeString& appendTo,
+ FieldPositionHandler& handler) const;
+ UnicodeString& _format(double number,
+ UnicodeString& appendTo,
+ FieldPositionHandler& handler) const;
+ UnicodeString& _format(const DigitList &number,
+ UnicodeString& appendTo,
+ FieldPositionHandler& handler,
+ UErrorCode &status) const;
+
+ // currency sign count
+ enum {
+ fgCurrencySignCountZero,
+ fgCurrencySignCountInSymbolFormat,
+ fgCurrencySignCountInISOFormat,
+ fgCurrencySignCountInPluralFormat
+ } CurrencySignCount;
+
/**
* Constants.
*/
- //static const int8_t fgMaxDigit; // The largest digit, in this case 9
-
- /*transient*/ //DigitList* fDigitList;
UnicodeString fPositivePrefix;
UnicodeString fPositiveSuffix;
@@ -1805,11 +2128,10 @@ private:
*/
ChoiceFormat* fCurrencyChoice;
- int32_t fMultiplier;
+ DigitList * fMultiplier; // NULL for multiplier of one
int32_t fGroupingSize;
int32_t fGroupingSize2;
UBool fDecimalSeparatorAlwaysShown;
- /*transient*/ UBool fIsCurrencyFormat;
DecimalFormatSymbols* fSymbols;
UBool fUseSignificantDigits;
@@ -1820,18 +2142,124 @@ private:
int8_t fMinExponentDigits;
UBool fExponentSignAlwaysShown;
- /* If fRoundingIncrement is NULL, there is no rounding. Otherwise, round to
- * fRoundingIncrement.getDouble(). Since this operation may be expensive,
- * we cache the result in fRoundingDouble. All methods that update
- * fRoundingIncrement also update fRoundingDouble. */
- DigitList* fRoundingIncrement;
- /*transient*/ double fRoundingDouble;
+ DigitList* fRoundingIncrement; // NULL if no rounding increment specified.
ERoundingMode fRoundingMode;
UChar32 fPad;
int32_t fFormatWidth;
EPadPosition fPadPosition;
+ /*
+ * Following are used for currency format
+ */
+ // pattern used in this formatter
+ UnicodeString fFormatPattern;
+ // style is only valid when decimal formatter is constructed by
+ // DecimalFormat(pattern, decimalFormatSymbol, style)
+ int fStyle;
+ /*
+ * Represents whether this is a currency format, and which
+ * currency format style.
+ * 0: not currency format type;
+ * 1: currency style -- symbol name, such as "$" for US dollar.
+ * 2: currency style -- ISO name, such as USD for US dollar.
+ * 3: currency style -- plural long name, such as "US Dollar" for
+ * "1.00 US Dollar", or "US Dollars" for
+ * "3.00 US Dollars".
+ */
+ int fCurrencySignCount;
+
+
+ /* For currency parsing purose,
+ * Need to remember all prefix patterns and suffix patterns of
+ * every currency format pattern,
+ * including the pattern of default currecny style
+ * and plural currency style. And the patterns are set through applyPattern.
+ */
+ // TODO: innerclass?
+ /* This is not needed in the class declaration, so it is moved into decimfmp.cpp
+ struct AffixPatternsForCurrency : public UMemory {
+ // negative prefix pattern
+ UnicodeString negPrefixPatternForCurrency;
+ // negative suffix pattern
+ UnicodeString negSuffixPatternForCurrency;
+ // positive prefix pattern
+ UnicodeString posPrefixPatternForCurrency;
+ // positive suffix pattern
+ UnicodeString posSuffixPatternForCurrency;
+ int8_t patternType;
+
+ AffixPatternsForCurrency(const UnicodeString& negPrefix,
+ const UnicodeString& negSuffix,
+ const UnicodeString& posPrefix,
+ const UnicodeString& posSuffix,
+ int8_t type) {
+ negPrefixPatternForCurrency = negPrefix;
+ negSuffixPatternForCurrency = negSuffix;
+ posPrefixPatternForCurrency = posPrefix;
+ posSuffixPatternForCurrency = posSuffix;
+ patternType = type;
+ }
+ };
+ */
+
+ /* affix for currency formatting when the currency sign in the pattern
+ * equals to 3, such as the pattern contains 3 currency sign or
+ * the formatter style is currency plural format style.
+ */
+ /* This is not needed in the class declaration, so it is moved into decimfmp.cpp
+ struct AffixesForCurrency : public UMemory {
+ // negative prefix
+ UnicodeString negPrefixForCurrency;
+ // negative suffix
+ UnicodeString negSuffixForCurrency;
+ // positive prefix
+ UnicodeString posPrefixForCurrency;
+ // positive suffix
+ UnicodeString posSuffixForCurrency;
+
+ int32_t formatWidth;
+
+ AffixesForCurrency(const UnicodeString& negPrefix,
+ const UnicodeString& negSuffix,
+ const UnicodeString& posPrefix,
+ const UnicodeString& posSuffix) {
+ negPrefixForCurrency = negPrefix;
+ negSuffixForCurrency = negSuffix;
+ posPrefixForCurrency = posPrefix;
+ posSuffixForCurrency = posSuffix;
+ }
+ };
+ */
+
+ // Affix pattern set for currency.
+ // It is a set of AffixPatternsForCurrency,
+ // each element of the set saves the negative prefix pattern,
+ // negative suffix pattern, positive prefix pattern,
+ // and positive suffix pattern of a pattern.
+ // It is used for currency mixed style parsing.
+ // It is actually is a set.
+ // The set contains the default currency pattern from the locale,
+ // and the currency plural patterns.
+ // Since it is a set, it does not contain duplicated items.
+ // For example, if 2 currency plural patterns are the same, only one pattern
+ // is included in the set. When parsing, we do not check whether the plural
+ // count match or not.
+ Hashtable* fAffixPatternsForCurrency;
+
+ // Following 2 are affixes for currency.
+ // It is a hash map from plural count to AffixesForCurrency.
+ // AffixesForCurrency saves the negative prefix,
+ // negative suffix, positive prefix, and positive suffix of a pattern.
+ // It is used during currency formatting only when the currency sign count
+ // is 3. In which case, the affixes are getting from here, not
+ // from the fNegativePrefix etc.
+ Hashtable* fAffixesForCurrency; // for current pattern
+ Hashtable* fPluralAffixesForCurrency; // for plural pattern
+
+ // Information needed for DecimalFormat to format/parse currency plural.
+ CurrencyPluralInfo* fCurrencyPluralInfo;
+
protected:
/**
@@ -1844,13 +2272,13 @@ protected:
*/
virtual void getEffectiveCurrency(UChar* result, UErrorCode& ec) const;
- /** number of integer digits
+ /** number of integer digits
* @stable ICU 2.4
- */
+ */
static const int32_t kDoubleIntegerDigits;
- /** number of fraction digits
+ /** number of fraction digits
* @stable ICU 2.4
- */
+ */
static const int32_t kDoubleFractionDigits;
/**
@@ -1889,10 +2317,12 @@ DecimalFormat::format(int32_t number,
return format((int64_t)number, appendTo, pos);
}
+#ifndef U_HIDE_INTERNAL_API
inline const UnicodeString &
DecimalFormat::getConstSymbol(DecimalFormatSymbols::ENumberFormatSymbol symbol) const {
return fSymbols->getConstSymbol(symbol);
}
+#endif
U_NAMESPACE_END