1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ********************************************************************************
5 *   Copyright (C) 1997-2016, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 ********************************************************************************
8 *
9 * File DCFMTSYM.H
10 *
11 * Modification History:
12 *
13 *   Date        Name        Description
14 *   02/19/97    aliu        Converted from java.
15 *   03/18/97    clhuang     Updated per C++ implementation.
16 *   03/27/97    helena      Updated to pass the simple test after code review.
17 *   08/26/97    aliu        Added currency/intl currency symbol support.
18 *   07/22/98    stephen     Changed to match C++ style
19 *                            currencySymbol -> fCurrencySymbol
20 *                            Constants changed from CAPS to kCaps
21 *   06/24/99    helena      Integrated Alan's NF enhancements and Java2 bug fixes
22 *   09/22/00    grhoten     Marked deprecation tags with a pointer to replacement
23 *                            functions.
24 ********************************************************************************
25 */
26 
27 #ifndef DCFMTSYM_H
28 #define DCFMTSYM_H
29 
30 #include "unicode/utypes.h"
31 #include "unicode/uchar.h"
32 
33 #if !UCONFIG_NO_FORMATTING
34 
35 #include "unicode/uobject.h"
36 #include "unicode/locid.h"
37 #include "unicode/numsys.h"
38 #include "unicode/unum.h"
39 #include "unicode/unistr.h"
40 
41 /**
42  * \file
43  * \brief C++ API: Symbols for formatting numbers.
44  */
45 
46 
47 U_NAMESPACE_BEGIN
48 
49 /**
50  * This class represents the set of symbols needed by DecimalFormat
51  * to format numbers. DecimalFormat creates for itself an instance of
52  * DecimalFormatSymbols from its locale data.  If you need to change any
53  * of these symbols, you can get the DecimalFormatSymbols object from
54  * your DecimalFormat and modify it.
55  * <P>
56  * Here are the special characters used in the parts of the
57  * subpattern, with notes on their usage.
58  * <pre>
59  * \code
60  *        Symbol   Meaning
61  *          0      a digit
62  *          #      a digit, zero shows as absent
63  *          .      placeholder for decimal separator
64  *          ,      placeholder for grouping separator.
65  *          ;      separates formats.
66  *          -      default negative prefix.
67  *          %      divide by 100 and show as percentage
68  *          X      any other characters can be used in the prefix or suffix
69  *          '      used to quote special characters in a prefix or suffix.
70  * \endcode
71  *  </pre>
72  * [Notes]
73  * <P>
74  * If there is no explicit negative subpattern, - is prefixed to the
75  * positive form. That is, "0.00" alone is equivalent to "0.00;-0.00".
76  * <P>
77  * The grouping separator is commonly used for thousands, but in some
78  * countries for ten-thousands. The interval is a constant number of
79  * digits between the grouping characters, such as 100,000,000 or 1,0000,0000.
80  * If you supply a pattern with multiple grouping characters, the interval
81  * between the last one and the end of the integer is the one that is
82  * used. So "#,##,###,####" == "######,####" == "##,####,####".
83  * <P>
84  * This class only handles localized digits where the 10 digits are
85  * contiguous in Unicode, from 0 to 9. Other digits sets (such as
86  * superscripts) would need a different subclass.
87  */
88 class U_I18N_API DecimalFormatSymbols : public UObject {
89 public:
90     /**
91      * Constants for specifying a number format symbol.
92      * @stable ICU 2.0
93      */
94     enum ENumberFormatSymbol {
95         /** The decimal separator */
96         kDecimalSeparatorSymbol,
97         /** The grouping separator */
98         kGroupingSeparatorSymbol,
99         /** The pattern separator */
100         kPatternSeparatorSymbol,
101         /** The percent sign */
102         kPercentSymbol,
103         /** Zero*/
104         kZeroDigitSymbol,
105         /** Character representing a digit in the pattern */
106         kDigitSymbol,
107         /** The minus sign */
108         kMinusSignSymbol,
109         /** The plus sign */
110         kPlusSignSymbol,
111         /** The currency symbol */
112         kCurrencySymbol,
113         /** The international currency symbol */
114         kIntlCurrencySymbol,
115         /** The monetary separator */
116         kMonetarySeparatorSymbol,
117         /** The exponential symbol */
118         kExponentialSymbol,
119         /** Per mill symbol - replaces kPermillSymbol */
120         kPerMillSymbol,
121         /** Escape padding character */
122         kPadEscapeSymbol,
123         /** Infinity symbol */
124         kInfinitySymbol,
125         /** Nan symbol */
126         kNaNSymbol,
127         /** Significant digit symbol
128          * @stable ICU 3.0 */
129         kSignificantDigitSymbol,
130         /** The monetary grouping separator
131          * @stable ICU 3.6
132          */
133         kMonetaryGroupingSeparatorSymbol,
134         /** One
135          * @stable ICU 4.6
136          */
137         kOneDigitSymbol,
138         /** Two
139          * @stable ICU 4.6
140          */
141         kTwoDigitSymbol,
142         /** Three
143          * @stable ICU 4.6
144          */
145         kThreeDigitSymbol,
146         /** Four
147          * @stable ICU 4.6
148          */
149         kFourDigitSymbol,
150         /** Five
151          * @stable ICU 4.6
152          */
153         kFiveDigitSymbol,
154         /** Six
155          * @stable ICU 4.6
156          */
157         kSixDigitSymbol,
158         /** Seven
159          * @stable ICU 4.6
160          */
161         kSevenDigitSymbol,
162         /** Eight
163          * @stable ICU 4.6
164          */
165         kEightDigitSymbol,
166         /** Nine
167          * @stable ICU 4.6
168          */
169         kNineDigitSymbol,
170         /** Multiplication sign.
171          * @stable ICU 54
172          */
173         kExponentMultiplicationSymbol,
174         /** count symbol constants */
175         kFormatSymbolCount = kNineDigitSymbol + 2
176     };
177 
178     /**
179      * Create a DecimalFormatSymbols object for the given locale.
180      *
181      * @param locale    The locale to get symbols for.
182      * @param status    Input/output parameter, set to success or
183      *                  failure code upon return.
184      * @stable ICU 2.0
185      */
186     DecimalFormatSymbols(const Locale& locale, UErrorCode& status);
187 
188 #ifndef U_HIDE_DRAFT_API
189     /**
190      * Creates a DecimalFormatSymbols instance for the given locale with digits and symbols
191      * corresponding to the given NumberingSystem.
192      *
193      * This constructor behaves equivalently to the normal constructor called with a locale having a
194      * "numbers=xxxx" keyword specifying the numbering system by name.
195      *
196      * In this constructor, the NumberingSystem argument will be used even if the locale has its own
197      * "numbers=xxxx" keyword.
198      *
199      * @param locale    The locale to get symbols for.
200      * @param ns        The numbering system.
201      * @param status    Input/output parameter, set to success or
202      *                  failure code upon return.
203      * @draft ICU 60
204      */
205     DecimalFormatSymbols(const Locale& locale, const NumberingSystem& ns, UErrorCode& status);
206 #endif  /* U_HIDE_DRAFT_API */
207 
208     /**
209      * Create a DecimalFormatSymbols object for the default locale.
210      * This constructor will not fail.  If the resource file data is
211      * not available, it will use hard-coded last-resort data and
212      * set status to U_USING_FALLBACK_ERROR.
213      *
214      * @param status    Input/output parameter, set to success or
215      *                  failure code upon return.
216      * @stable ICU 2.0
217      */
218     DecimalFormatSymbols(UErrorCode& status);
219 
220     /**
221      * Creates a DecimalFormatSymbols object with last-resort data.
222      * Intended for callers who cache the symbols data and
223      * set all symbols on the resulting object.
224      *
225      * The last-resort symbols are similar to those for the root data,
226      * except that the grouping separators are empty,
227      * the NaN symbol is U+FFFD rather than "NaN",
228      * and the CurrencySpacing patterns are empty.
229      *
230      * @param status    Input/output parameter, set to success or
231      *                  failure code upon return.
232      * @return last-resort symbols
233      * @stable ICU 52
234      */
235     static DecimalFormatSymbols* createWithLastResortData(UErrorCode& status);
236 
237     /**
238      * Copy constructor.
239      * @stable ICU 2.0
240      */
241     DecimalFormatSymbols(const DecimalFormatSymbols&);
242 
243     /**
244      * Assignment operator.
245      * @stable ICU 2.0
246      */
247     DecimalFormatSymbols& operator=(const DecimalFormatSymbols&);
248 
249     /**
250      * Destructor.
251      * @stable ICU 2.0
252      */
253     virtual ~DecimalFormatSymbols();
254 
255     /**
256      * Return true if another object is semantically equal to this one.
257      *
258      * @param other    the object to be compared with.
259      * @return         true if another object is semantically equal to this one.
260      * @stable ICU 2.0
261      */
262     UBool operator==(const DecimalFormatSymbols& other) const;
263 
264     /**
265      * Return true if another object is semantically unequal to this one.
266      *
267      * @param other    the object to be compared with.
268      * @return         true if another object is semantically unequal to this one.
269      * @stable ICU 2.0
270      */
271     UBool operator!=(const DecimalFormatSymbols& other) const { return !operator==(other); }
272 
273     /**
274      * Get one of the format symbols by its enum constant.
275      * Each symbol is stored as a string so that graphemes
276      * (characters with modifier letters) can be used.
277      *
278      * @param symbol    Constant to indicate a number format symbol.
279      * @return    the format symbols by the param 'symbol'
280      * @stable ICU 2.0
281      */
282     inline UnicodeString getSymbol(ENumberFormatSymbol symbol) const;
283 
284     /**
285      * Set one of the format symbols by its enum constant.
286      * Each symbol is stored as a string so that graphemes
287      * (characters with modifier letters) can be used.
288      *
289      * @param symbol    Constant to indicate a number format symbol.
290      * @param value     value of the format symbol
291      * @param propogateDigits If false, setting the zero digit will not automatically set 1-9.
292      *     The default behavior is to automatically set 1-9 if zero is being set and the value
293      *     it is being set to corresponds to a known Unicode zero digit.
294      * @stable ICU 2.0
295      */
296     void setSymbol(ENumberFormatSymbol symbol, const UnicodeString &value, const UBool propogateDigits);
297 
298     /**
299      * Returns the locale for which this object was constructed.
300      * @stable ICU 2.6
301      */
302     inline Locale getLocale() const;
303 
304     /**
305      * Returns the locale for this object. Two flavors are available:
306      * valid and actual locale.
307      * @stable ICU 2.8
308      */
309     Locale getLocale(ULocDataLocaleType type, UErrorCode& status) const;
310 
311     /**
312       * Get pattern string for 'CurrencySpacing' that can be applied to
313       * currency format.
314       * This API gets the CurrencySpacing data from ResourceBundle. The pattern can
315       * be empty if there is no data from current locale and its parent locales.
316       *
317       * @param type :  UNUM_CURRENCY_MATCH, UNUM_CURRENCY_SURROUNDING_MATCH or UNUM_CURRENCY_INSERT.
318       * @param beforeCurrency : true if the pattern is for before currency symbol.
319       *                         false if the pattern is for after currency symbol.
320       * @param status: Input/output parameter, set to success or
321       *                  failure code upon return.
322       * @return pattern string for currencyMatch, surroundingMatch or spaceInsert.
323       *     Return empty string if there is no data for this locale and its parent
324       *     locales.
325       * @stable ICU 4.8
326       */
327      const UnicodeString& getPatternForCurrencySpacing(UCurrencySpacing type,
328                                                  UBool beforeCurrency,
329                                                  UErrorCode& status) const;
330      /**
331        * Set pattern string for 'CurrencySpacing' that can be applied to
332        * currency format.
333        *
334        * @param type : UNUM_CURRENCY_MATCH, UNUM_CURRENCY_SURROUNDING_MATCH or UNUM_CURRENCY_INSERT.
335        * @param beforeCurrency : true if the pattern is for before currency symbol.
336        *                         false if the pattern is for after currency symbol.
337        * @param pattern : pattern string to override current setting.
338        * @stable ICU 4.8
339        */
340      void setPatternForCurrencySpacing(UCurrencySpacing type,
341                                        UBool beforeCurrency,
342                                        const UnicodeString& pattern);
343 
344     /**
345      * ICU "poor man's RTTI", returns a UClassID for the actual class.
346      *
347      * @stable ICU 2.2
348      */
349     virtual UClassID getDynamicClassID() const;
350 
351     /**
352      * ICU "poor man's RTTI", returns a UClassID for this class.
353      *
354      * @stable ICU 2.2
355      */
356     static UClassID U_EXPORT2 getStaticClassID();
357 
358 private:
359     DecimalFormatSymbols();
360 
361     /**
362      * Initializes the symbols from the LocaleElements resource bundle.
363      * Note: The organization of LocaleElements badly needs to be
364      * cleaned up.
365      *
366      * @param locale               The locale to get symbols for.
367      * @param success              Input/output parameter, set to success or
368      *                             failure code upon return.
369      * @param useLastResortData    determine if use last resort data
370      * @param ns                   The NumberingSystem to use; otherwise, fall
371      *                             back to the locale.
372      */
373     void initialize(const Locale& locale, UErrorCode& success,
374         UBool useLastResortData = FALSE, const NumberingSystem* ns = nullptr);
375 
376     /**
377      * Initialize the symbols with default values.
378      */
379     void initialize();
380 
381     void setCurrencyForSymbols();
382 
383 public:
384 
385 #ifndef U_HIDE_INTERNAL_API
386     /**
387      * @internal For ICU use only
388      */
isCustomCurrencySymbol()389     inline UBool isCustomCurrencySymbol() const {
390         return fIsCustomCurrencySymbol;
391     }
392 
393     /**
394      * @internal For ICU use only
395      */
isCustomIntlCurrencySymbol()396     inline UBool isCustomIntlCurrencySymbol() const {
397         return fIsCustomIntlCurrencySymbol;
398     }
399 #endif  /* U_HIDE_INTERNAL_API */
400 
401     /**
402      * _Internal_ function - more efficient version of getSymbol,
403      * returning a const reference to one of the symbol strings.
404      * The returned reference becomes invalid when the symbol is changed
405      * or when the DecimalFormatSymbols are destroyed.
406      * ### TODO markus 2002oct11: Consider proposing getConstSymbol() to be really public.
407      * Note: moved #ifndef U_HIDE_INTERNAL_API after this, since this is needed for inline in DecimalFormat
408      *
409      * @param symbol Constant to indicate a number format symbol.
410      * @return the format symbol by the param 'symbol'
411      * @internal
412      */
413     inline const UnicodeString &getConstSymbol(ENumberFormatSymbol symbol) const;
414 
415 #ifndef U_HIDE_INTERNAL_API
416     /**
417      * Returns that pattern stored in currecy info. Internal API for use by NumberFormat API.
418      * @internal
419      */
420     inline const char16_t* getCurrencyPattern(void) const;
421 #endif  /* U_HIDE_INTERNAL_API */
422 
423 private:
424     /**
425      * Private symbol strings.
426      * They are either loaded from a resource bundle or otherwise owned.
427      * setSymbol() clones the symbol string.
428      * Readonly aliases can only come from a resource bundle, so that we can always
429      * use fastCopyFrom() with them.
430      *
431      * If DecimalFormatSymbols becomes subclassable and the status of fSymbols changes
432      * from private to protected,
433      * or when fSymbols can be set any other way that allows them to be readonly aliases
434      * to non-resource bundle strings,
435      * then regular UnicodeString copies must be used instead of fastCopyFrom().
436      *
437      * @internal
438      */
439     UnicodeString fSymbols[kFormatSymbolCount];
440 
441     /**
442      * Non-symbol variable for getConstSymbol(). Always empty.
443      * @internal
444      */
445     UnicodeString fNoSymbol;
446 
447     Locale locale;
448 
449     char actualLocale[ULOC_FULLNAME_CAPACITY];
450     char validLocale[ULOC_FULLNAME_CAPACITY];
451     const char16_t* currPattern;
452 
453     UnicodeString currencySpcBeforeSym[UNUM_CURRENCY_SPACING_COUNT];
454     UnicodeString currencySpcAfterSym[UNUM_CURRENCY_SPACING_COUNT];
455     UBool fIsCustomCurrencySymbol;
456     UBool fIsCustomIntlCurrencySymbol;
457 };
458 
459 // -------------------------------------
460 
461 inline UnicodeString
getSymbol(ENumberFormatSymbol symbol)462 DecimalFormatSymbols::getSymbol(ENumberFormatSymbol symbol) const {
463     const UnicodeString *strPtr;
464     if(symbol < kFormatSymbolCount) {
465         strPtr = &fSymbols[symbol];
466     } else {
467         strPtr = &fNoSymbol;
468     }
469     return *strPtr;
470 }
471 
472 // See comments above for this function. Not hidden with #ifndef U_HIDE_INTERNAL_API
473 inline const UnicodeString &
getConstSymbol(ENumberFormatSymbol symbol)474 DecimalFormatSymbols::getConstSymbol(ENumberFormatSymbol symbol) const {
475     const UnicodeString *strPtr;
476     if(symbol < kFormatSymbolCount) {
477         strPtr = &fSymbols[symbol];
478     } else {
479         strPtr = &fNoSymbol;
480     }
481     return *strPtr;
482 }
483 
484 // -------------------------------------
485 
486 inline void
487 DecimalFormatSymbols::setSymbol(ENumberFormatSymbol symbol, const UnicodeString &value, const UBool propogateDigits = TRUE) {
488     if (symbol == kCurrencySymbol) {
489         fIsCustomCurrencySymbol = TRUE;
490     }
491     else if (symbol == kIntlCurrencySymbol) {
492         fIsCustomIntlCurrencySymbol = TRUE;
493     }
494     if(symbol<kFormatSymbolCount) {
495         fSymbols[symbol]=value;
496     }
497 
498     // If the zero digit is being set to a known zero digit according to Unicode,
499     // then we automatically set the corresponding 1-9 digits
500     if ( propogateDigits && symbol == kZeroDigitSymbol && value.countChar32() == 1 ) {
501         UChar32 sym = value.char32At(0);
502         if ( u_charDigitValue(sym) == 0 ) {
503             for ( int8_t i = 1 ; i<= 9 ; i++ ) {
504                 sym++;
505                 fSymbols[(int)kOneDigitSymbol+i-1] = UnicodeString(sym);
506             }
507         }
508     }
509 }
510 
511 // -------------------------------------
512 
513 inline Locale
getLocale()514 DecimalFormatSymbols::getLocale() const {
515     return locale;
516 }
517 
518 #ifndef U_HIDE_INTERNAL_API
519 inline const char16_t*
getCurrencyPattern()520 DecimalFormatSymbols::getCurrencyPattern() const {
521     return currPattern;
522 }
523 #endif /* U_HIDE_INTERNAL_API */
524 
525 U_NAMESPACE_END
526 
527 #endif /* #if !UCONFIG_NO_FORMATTING */
528 
529 #endif // _DCFMTSYM
530 //eof
531