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