1*0e209d39SAndroid Build Coastguard Worker // © 2016 and later: Unicode, Inc. and others.
2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html
3*0e209d39SAndroid Build Coastguard Worker /*
4*0e209d39SAndroid Build Coastguard Worker *******************************************************************************
5*0e209d39SAndroid Build Coastguard Worker * Copyright (C) 1997-2015, International Business Machines Corporation and
6*0e209d39SAndroid Build Coastguard Worker * others. All Rights Reserved.
7*0e209d39SAndroid Build Coastguard Worker *******************************************************************************
8*0e209d39SAndroid Build Coastguard Worker *
9*0e209d39SAndroid Build Coastguard Worker * File NUMFMT.CPP
10*0e209d39SAndroid Build Coastguard Worker *
11*0e209d39SAndroid Build Coastguard Worker * Modification History:
12*0e209d39SAndroid Build Coastguard Worker *
13*0e209d39SAndroid Build Coastguard Worker * Date Name Description
14*0e209d39SAndroid Build Coastguard Worker * 02/19/97 aliu Converted from java.
15*0e209d39SAndroid Build Coastguard Worker * 03/18/97 clhuang Implemented with C++ APIs.
16*0e209d39SAndroid Build Coastguard Worker * 04/17/97 aliu Enlarged MAX_INTEGER_DIGITS to fully accommodate the
17*0e209d39SAndroid Build Coastguard Worker * largest double, by default.
18*0e209d39SAndroid Build Coastguard Worker * Changed DigitCount to int per code review.
19*0e209d39SAndroid Build Coastguard Worker * 07/20/98 stephen Changed operator== to check for grouping
20*0e209d39SAndroid Build Coastguard Worker * Changed setMaxIntegerDigits per Java implementation.
21*0e209d39SAndroid Build Coastguard Worker * Changed setMinIntegerDigits per Java implementation.
22*0e209d39SAndroid Build Coastguard Worker * Changed setMinFractionDigits per Java implementation.
23*0e209d39SAndroid Build Coastguard Worker * Changed setMaxFractionDigits per Java implementation.
24*0e209d39SAndroid Build Coastguard Worker ********************************************************************************
25*0e209d39SAndroid Build Coastguard Worker */
26*0e209d39SAndroid Build Coastguard Worker
27*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h"
28*0e209d39SAndroid Build Coastguard Worker
29*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_FORMATTING
30*0e209d39SAndroid Build Coastguard Worker
31*0e209d39SAndroid Build Coastguard Worker #include "unicode/numfmt.h"
32*0e209d39SAndroid Build Coastguard Worker #include "unicode/locid.h"
33*0e209d39SAndroid Build Coastguard Worker #include "unicode/dcfmtsym.h"
34*0e209d39SAndroid Build Coastguard Worker #include "unicode/decimfmt.h"
35*0e209d39SAndroid Build Coastguard Worker #include "unicode/ustring.h"
36*0e209d39SAndroid Build Coastguard Worker #include "unicode/ucurr.h"
37*0e209d39SAndroid Build Coastguard Worker #include "unicode/curramt.h"
38*0e209d39SAndroid Build Coastguard Worker #include "unicode/numsys.h"
39*0e209d39SAndroid Build Coastguard Worker #include "unicode/rbnf.h"
40*0e209d39SAndroid Build Coastguard Worker #include "unicode/localpointer.h"
41*0e209d39SAndroid Build Coastguard Worker #include "unicode/udisplaycontext.h"
42*0e209d39SAndroid Build Coastguard Worker #include "charstr.h"
43*0e209d39SAndroid Build Coastguard Worker #include "winnmfmt.h"
44*0e209d39SAndroid Build Coastguard Worker #include "uresimp.h"
45*0e209d39SAndroid Build Coastguard Worker #include "uhash.h"
46*0e209d39SAndroid Build Coastguard Worker #include "cmemory.h"
47*0e209d39SAndroid Build Coastguard Worker #include "servloc.h"
48*0e209d39SAndroid Build Coastguard Worker #include "ucln_in.h"
49*0e209d39SAndroid Build Coastguard Worker #include "cstring.h"
50*0e209d39SAndroid Build Coastguard Worker #include "putilimp.h"
51*0e209d39SAndroid Build Coastguard Worker #include "uassert.h"
52*0e209d39SAndroid Build Coastguard Worker #include "umutex.h"
53*0e209d39SAndroid Build Coastguard Worker #include "mutex.h"
54*0e209d39SAndroid Build Coastguard Worker #include <float.h>
55*0e209d39SAndroid Build Coastguard Worker #include "sharednumberformat.h"
56*0e209d39SAndroid Build Coastguard Worker #include "unifiedcache.h"
57*0e209d39SAndroid Build Coastguard Worker #include "number_decimalquantity.h"
58*0e209d39SAndroid Build Coastguard Worker #include "number_utils.h"
59*0e209d39SAndroid Build Coastguard Worker
60*0e209d39SAndroid Build Coastguard Worker //#define FMT_DEBUG
61*0e209d39SAndroid Build Coastguard Worker
62*0e209d39SAndroid Build Coastguard Worker #ifdef FMT_DEBUG
63*0e209d39SAndroid Build Coastguard Worker #include <stdio.h>
debugout(UnicodeString s)64*0e209d39SAndroid Build Coastguard Worker static inline void debugout(UnicodeString s) {
65*0e209d39SAndroid Build Coastguard Worker char buf[2000];
66*0e209d39SAndroid Build Coastguard Worker s.extract((int32_t) 0, s.length(), buf);
67*0e209d39SAndroid Build Coastguard Worker printf("%s", buf);
68*0e209d39SAndroid Build Coastguard Worker }
69*0e209d39SAndroid Build Coastguard Worker #define debug(x) printf("%s", x);
70*0e209d39SAndroid Build Coastguard Worker #else
71*0e209d39SAndroid Build Coastguard Worker #define debugout(x)
72*0e209d39SAndroid Build Coastguard Worker #define debug(x)
73*0e209d39SAndroid Build Coastguard Worker #endif
74*0e209d39SAndroid Build Coastguard Worker
75*0e209d39SAndroid Build Coastguard Worker // If no number pattern can be located for a locale, this is the last
76*0e209d39SAndroid Build Coastguard Worker // resort. The patterns are same as the ones in root locale.
77*0e209d39SAndroid Build Coastguard Worker static const char16_t gLastResortDecimalPat[] = {
78*0e209d39SAndroid Build Coastguard Worker 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#,##0.###" */
79*0e209d39SAndroid Build Coastguard Worker };
80*0e209d39SAndroid Build Coastguard Worker static const char16_t gLastResortCurrencyPat[] = {
81*0e209d39SAndroid Build Coastguard Worker 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */
82*0e209d39SAndroid Build Coastguard Worker };
83*0e209d39SAndroid Build Coastguard Worker static const char16_t gLastResortPercentPat[] = {
84*0e209d39SAndroid Build Coastguard Worker 0x23, 0x2C, 0x23, 0x23, 0x30, 0x25, 0 /* "#,##0%" */
85*0e209d39SAndroid Build Coastguard Worker };
86*0e209d39SAndroid Build Coastguard Worker static const char16_t gLastResortScientificPat[] = {
87*0e209d39SAndroid Build Coastguard Worker 0x23, 0x45, 0x30, 0 /* "#E0" */
88*0e209d39SAndroid Build Coastguard Worker };
89*0e209d39SAndroid Build Coastguard Worker static const char16_t gLastResortIsoCurrencyPat[] = {
90*0e209d39SAndroid Build Coastguard Worker 0xA4, 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A4\u00A0#,##0.00" */
91*0e209d39SAndroid Build Coastguard Worker };
92*0e209d39SAndroid Build Coastguard Worker static const char16_t gLastResortPluralCurrencyPat[] = {
93*0e209d39SAndroid Build Coastguard Worker 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x20, 0xA4, 0xA4, 0xA4, 0 /* "#,##0.### \u00A4\u00A4\u00A4*/
94*0e209d39SAndroid Build Coastguard Worker };
95*0e209d39SAndroid Build Coastguard Worker static const char16_t gLastResortAccountingCurrencyPat[] = {
96*0e209d39SAndroid Build Coastguard Worker 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */
97*0e209d39SAndroid Build Coastguard Worker };
98*0e209d39SAndroid Build Coastguard Worker
99*0e209d39SAndroid Build Coastguard Worker static const char16_t gSingleCurrencySign[] = {0xA4, 0};
100*0e209d39SAndroid Build Coastguard Worker static const char16_t gDoubleCurrencySign[] = {0xA4, 0xA4, 0};
101*0e209d39SAndroid Build Coastguard Worker
102*0e209d39SAndroid Build Coastguard Worker static const char16_t gSlash = 0x2f;
103*0e209d39SAndroid Build Coastguard Worker
104*0e209d39SAndroid Build Coastguard Worker // If the maximum base 10 exponent were 4, then the largest number would
105*0e209d39SAndroid Build Coastguard Worker // be 99,999 which has 5 digits.
106*0e209d39SAndroid Build Coastguard Worker // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
107*0e209d39SAndroid Build Coastguard Worker // With big decimal, the max exponent is 999,999,999 and the max number of digits is the same, 999,999,999
108*0e209d39SAndroid Build Coastguard Worker const int32_t icu::NumberFormat::gDefaultMaxIntegerDigits = 2000000000;
109*0e209d39SAndroid Build Coastguard Worker const int32_t icu::NumberFormat::gDefaultMinIntegerDigits = 127;
110*0e209d39SAndroid Build Coastguard Worker
111*0e209d39SAndroid Build Coastguard Worker static const char16_t * const gLastResortNumberPatterns[UNUM_FORMAT_STYLE_COUNT] = {
112*0e209d39SAndroid Build Coastguard Worker nullptr, // UNUM_PATTERN_DECIMAL
113*0e209d39SAndroid Build Coastguard Worker gLastResortDecimalPat, // UNUM_DECIMAL
114*0e209d39SAndroid Build Coastguard Worker gLastResortCurrencyPat, // UNUM_CURRENCY
115*0e209d39SAndroid Build Coastguard Worker gLastResortPercentPat, // UNUM_PERCENT
116*0e209d39SAndroid Build Coastguard Worker gLastResortScientificPat, // UNUM_SCIENTIFIC
117*0e209d39SAndroid Build Coastguard Worker nullptr, // UNUM_SPELLOUT
118*0e209d39SAndroid Build Coastguard Worker nullptr, // UNUM_ORDINAL
119*0e209d39SAndroid Build Coastguard Worker nullptr, // UNUM_DURATION
120*0e209d39SAndroid Build Coastguard Worker gLastResortDecimalPat, // UNUM_NUMBERING_SYSTEM
121*0e209d39SAndroid Build Coastguard Worker nullptr, // UNUM_PATTERN_RULEBASED
122*0e209d39SAndroid Build Coastguard Worker gLastResortIsoCurrencyPat, // UNUM_CURRENCY_ISO
123*0e209d39SAndroid Build Coastguard Worker gLastResortPluralCurrencyPat, // UNUM_CURRENCY_PLURAL
124*0e209d39SAndroid Build Coastguard Worker gLastResortAccountingCurrencyPat, // UNUM_CURRENCY_ACCOUNTING
125*0e209d39SAndroid Build Coastguard Worker gLastResortCurrencyPat, // UNUM_CASH_CURRENCY
126*0e209d39SAndroid Build Coastguard Worker nullptr, // UNUM_DECIMAL_COMPACT_SHORT
127*0e209d39SAndroid Build Coastguard Worker nullptr, // UNUM_DECIMAL_COMPACT_LONG
128*0e209d39SAndroid Build Coastguard Worker gLastResortCurrencyPat, // UNUM_CURRENCY_STANDARD
129*0e209d39SAndroid Build Coastguard Worker };
130*0e209d39SAndroid Build Coastguard Worker
131*0e209d39SAndroid Build Coastguard Worker // Keys used for accessing resource bundles
132*0e209d39SAndroid Build Coastguard Worker
133*0e209d39SAndroid Build Coastguard Worker static const icu::number::impl::CldrPatternStyle gFormatCldrStyles[UNUM_FORMAT_STYLE_COUNT] = {
134*0e209d39SAndroid Build Coastguard Worker /* nullptr */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_PATTERN_DECIMAL
135*0e209d39SAndroid Build Coastguard Worker icu::number::impl::CLDR_PATTERN_STYLE_DECIMAL, // UNUM_DECIMAL
136*0e209d39SAndroid Build Coastguard Worker icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY, // UNUM_CURRENCY
137*0e209d39SAndroid Build Coastguard Worker icu::number::impl::CLDR_PATTERN_STYLE_PERCENT, // UNUM_PERCENT
138*0e209d39SAndroid Build Coastguard Worker icu::number::impl::CLDR_PATTERN_STYLE_SCIENTIFIC, // UNUM_SCIENTIFIC
139*0e209d39SAndroid Build Coastguard Worker /* nullptr */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_SPELLOUT
140*0e209d39SAndroid Build Coastguard Worker /* nullptr */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_ORDINAL
141*0e209d39SAndroid Build Coastguard Worker /* nullptr */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_DURATION
142*0e209d39SAndroid Build Coastguard Worker /* nullptr */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_NUMBERING_SYSTEM
143*0e209d39SAndroid Build Coastguard Worker /* nullptr */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_PATTERN_RULEBASED
144*0e209d39SAndroid Build Coastguard Worker // For UNUM_CURRENCY_ISO and UNUM_CURRENCY_PLURAL,
145*0e209d39SAndroid Build Coastguard Worker // the pattern is the same as the pattern of UNUM_CURRENCY
146*0e209d39SAndroid Build Coastguard Worker // except for replacing the single currency sign with
147*0e209d39SAndroid Build Coastguard Worker // double currency sign or triple currency sign.
148*0e209d39SAndroid Build Coastguard Worker icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY, // UNUM_CURRENCY_ISO
149*0e209d39SAndroid Build Coastguard Worker icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY, // UNUM_CURRENCY_PLURAL
150*0e209d39SAndroid Build Coastguard Worker icu::number::impl::CLDR_PATTERN_STYLE_ACCOUNTING, // UNUM_CURRENCY_ACCOUNTING
151*0e209d39SAndroid Build Coastguard Worker icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY, // UNUM_CASH_CURRENCY
152*0e209d39SAndroid Build Coastguard Worker /* nullptr */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_DECIMAL_COMPACT_SHORT
153*0e209d39SAndroid Build Coastguard Worker /* nullptr */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_DECIMAL_COMPACT_LONG
154*0e209d39SAndroid Build Coastguard Worker icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY, // UNUM_CURRENCY_STANDARD
155*0e209d39SAndroid Build Coastguard Worker };
156*0e209d39SAndroid Build Coastguard Worker
157*0e209d39SAndroid Build Coastguard Worker // Static hashtable cache of NumberingSystem objects used by NumberFormat
158*0e209d39SAndroid Build Coastguard Worker static UHashtable * NumberingSystem_cache = nullptr;
159*0e209d39SAndroid Build Coastguard Worker static icu::UInitOnce gNSCacheInitOnce {};
160*0e209d39SAndroid Build Coastguard Worker
161*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_SERVICE
162*0e209d39SAndroid Build Coastguard Worker static icu::ICULocaleService* gService = nullptr;
163*0e209d39SAndroid Build Coastguard Worker static icu::UInitOnce gServiceInitOnce {};
164*0e209d39SAndroid Build Coastguard Worker #endif
165*0e209d39SAndroid Build Coastguard Worker
166*0e209d39SAndroid Build Coastguard Worker /**
167*0e209d39SAndroid Build Coastguard Worker * Release all static memory held by Number Format.
168*0e209d39SAndroid Build Coastguard Worker */
169*0e209d39SAndroid Build Coastguard Worker U_CDECL_BEGIN
170*0e209d39SAndroid Build Coastguard Worker static void U_CALLCONV
deleteNumberingSystem(void * obj)171*0e209d39SAndroid Build Coastguard Worker deleteNumberingSystem(void *obj) {
172*0e209d39SAndroid Build Coastguard Worker delete (icu::NumberingSystem *)obj;
173*0e209d39SAndroid Build Coastguard Worker }
174*0e209d39SAndroid Build Coastguard Worker
numfmt_cleanup()175*0e209d39SAndroid Build Coastguard Worker static UBool U_CALLCONV numfmt_cleanup() {
176*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_SERVICE
177*0e209d39SAndroid Build Coastguard Worker gServiceInitOnce.reset();
178*0e209d39SAndroid Build Coastguard Worker if (gService) {
179*0e209d39SAndroid Build Coastguard Worker delete gService;
180*0e209d39SAndroid Build Coastguard Worker gService = nullptr;
181*0e209d39SAndroid Build Coastguard Worker }
182*0e209d39SAndroid Build Coastguard Worker #endif
183*0e209d39SAndroid Build Coastguard Worker gNSCacheInitOnce.reset();
184*0e209d39SAndroid Build Coastguard Worker if (NumberingSystem_cache) {
185*0e209d39SAndroid Build Coastguard Worker // delete NumberingSystem_cache;
186*0e209d39SAndroid Build Coastguard Worker uhash_close(NumberingSystem_cache);
187*0e209d39SAndroid Build Coastguard Worker NumberingSystem_cache = nullptr;
188*0e209d39SAndroid Build Coastguard Worker }
189*0e209d39SAndroid Build Coastguard Worker return true;
190*0e209d39SAndroid Build Coastguard Worker }
191*0e209d39SAndroid Build Coastguard Worker U_CDECL_END
192*0e209d39SAndroid Build Coastguard Worker
193*0e209d39SAndroid Build Coastguard Worker // *****************************************************************************
194*0e209d39SAndroid Build Coastguard Worker // class NumberFormat
195*0e209d39SAndroid Build Coastguard Worker // *****************************************************************************
196*0e209d39SAndroid Build Coastguard Worker
197*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_BEGIN
198*0e209d39SAndroid Build Coastguard Worker
UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat)199*0e209d39SAndroid Build Coastguard Worker UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat)
200*0e209d39SAndroid Build Coastguard Worker
201*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_SERVICE
202*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
203*0e209d39SAndroid Build Coastguard Worker // SimpleNumberFormatFactory implementation
204*0e209d39SAndroid Build Coastguard Worker NumberFormatFactory::~NumberFormatFactory() {}
SimpleNumberFormatFactory(const Locale & locale,UBool visible)205*0e209d39SAndroid Build Coastguard Worker SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale& locale, UBool visible)
206*0e209d39SAndroid Build Coastguard Worker : _visible(visible)
207*0e209d39SAndroid Build Coastguard Worker {
208*0e209d39SAndroid Build Coastguard Worker LocaleUtility::initNameFromLocale(locale, _id);
209*0e209d39SAndroid Build Coastguard Worker }
210*0e209d39SAndroid Build Coastguard Worker
~SimpleNumberFormatFactory()211*0e209d39SAndroid Build Coastguard Worker SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
212*0e209d39SAndroid Build Coastguard Worker
visible() const213*0e209d39SAndroid Build Coastguard Worker UBool SimpleNumberFormatFactory::visible() const {
214*0e209d39SAndroid Build Coastguard Worker return _visible;
215*0e209d39SAndroid Build Coastguard Worker }
216*0e209d39SAndroid Build Coastguard Worker
217*0e209d39SAndroid Build Coastguard Worker const UnicodeString *
getSupportedIDs(int32_t & count,UErrorCode & status) const218*0e209d39SAndroid Build Coastguard Worker SimpleNumberFormatFactory::getSupportedIDs(int32_t &count, UErrorCode& status) const
219*0e209d39SAndroid Build Coastguard Worker {
220*0e209d39SAndroid Build Coastguard Worker if (U_SUCCESS(status)) {
221*0e209d39SAndroid Build Coastguard Worker count = 1;
222*0e209d39SAndroid Build Coastguard Worker return &_id;
223*0e209d39SAndroid Build Coastguard Worker }
224*0e209d39SAndroid Build Coastguard Worker count = 0;
225*0e209d39SAndroid Build Coastguard Worker return nullptr;
226*0e209d39SAndroid Build Coastguard Worker }
227*0e209d39SAndroid Build Coastguard Worker #endif /* #if !UCONFIG_NO_SERVICE */
228*0e209d39SAndroid Build Coastguard Worker
229*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
230*0e209d39SAndroid Build Coastguard Worker // default constructor
NumberFormat()231*0e209d39SAndroid Build Coastguard Worker NumberFormat::NumberFormat()
232*0e209d39SAndroid Build Coastguard Worker : fGroupingUsed(true),
233*0e209d39SAndroid Build Coastguard Worker fMaxIntegerDigits(gDefaultMaxIntegerDigits),
234*0e209d39SAndroid Build Coastguard Worker fMinIntegerDigits(1),
235*0e209d39SAndroid Build Coastguard Worker fMaxFractionDigits(3), // invariant, >= minFractionDigits
236*0e209d39SAndroid Build Coastguard Worker fMinFractionDigits(0),
237*0e209d39SAndroid Build Coastguard Worker fParseIntegerOnly(false),
238*0e209d39SAndroid Build Coastguard Worker fLenient(false),
239*0e209d39SAndroid Build Coastguard Worker fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
240*0e209d39SAndroid Build Coastguard Worker {
241*0e209d39SAndroid Build Coastguard Worker fCurrency[0] = 0;
242*0e209d39SAndroid Build Coastguard Worker }
243*0e209d39SAndroid Build Coastguard Worker
244*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
245*0e209d39SAndroid Build Coastguard Worker
~NumberFormat()246*0e209d39SAndroid Build Coastguard Worker NumberFormat::~NumberFormat()
247*0e209d39SAndroid Build Coastguard Worker {
248*0e209d39SAndroid Build Coastguard Worker }
249*0e209d39SAndroid Build Coastguard Worker
~SharedNumberFormat()250*0e209d39SAndroid Build Coastguard Worker SharedNumberFormat::~SharedNumberFormat() {
251*0e209d39SAndroid Build Coastguard Worker delete ptr;
252*0e209d39SAndroid Build Coastguard Worker }
253*0e209d39SAndroid Build Coastguard Worker
254*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
255*0e209d39SAndroid Build Coastguard Worker // copy constructor
256*0e209d39SAndroid Build Coastguard Worker
NumberFormat(const NumberFormat & source)257*0e209d39SAndroid Build Coastguard Worker NumberFormat::NumberFormat(const NumberFormat &source)
258*0e209d39SAndroid Build Coastguard Worker : Format(source)
259*0e209d39SAndroid Build Coastguard Worker {
260*0e209d39SAndroid Build Coastguard Worker *this = source;
261*0e209d39SAndroid Build Coastguard Worker }
262*0e209d39SAndroid Build Coastguard Worker
263*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
264*0e209d39SAndroid Build Coastguard Worker // assignment operator
265*0e209d39SAndroid Build Coastguard Worker
266*0e209d39SAndroid Build Coastguard Worker NumberFormat&
operator =(const NumberFormat & rhs)267*0e209d39SAndroid Build Coastguard Worker NumberFormat::operator=(const NumberFormat& rhs)
268*0e209d39SAndroid Build Coastguard Worker {
269*0e209d39SAndroid Build Coastguard Worker if (this != &rhs)
270*0e209d39SAndroid Build Coastguard Worker {
271*0e209d39SAndroid Build Coastguard Worker Format::operator=(rhs);
272*0e209d39SAndroid Build Coastguard Worker fGroupingUsed = rhs.fGroupingUsed;
273*0e209d39SAndroid Build Coastguard Worker fMaxIntegerDigits = rhs.fMaxIntegerDigits;
274*0e209d39SAndroid Build Coastguard Worker fMinIntegerDigits = rhs.fMinIntegerDigits;
275*0e209d39SAndroid Build Coastguard Worker fMaxFractionDigits = rhs.fMaxFractionDigits;
276*0e209d39SAndroid Build Coastguard Worker fMinFractionDigits = rhs.fMinFractionDigits;
277*0e209d39SAndroid Build Coastguard Worker fParseIntegerOnly = rhs.fParseIntegerOnly;
278*0e209d39SAndroid Build Coastguard Worker u_strncpy(fCurrency, rhs.fCurrency, 3);
279*0e209d39SAndroid Build Coastguard Worker fCurrency[3] = 0;
280*0e209d39SAndroid Build Coastguard Worker fLenient = rhs.fLenient;
281*0e209d39SAndroid Build Coastguard Worker fCapitalizationContext = rhs.fCapitalizationContext;
282*0e209d39SAndroid Build Coastguard Worker }
283*0e209d39SAndroid Build Coastguard Worker return *this;
284*0e209d39SAndroid Build Coastguard Worker }
285*0e209d39SAndroid Build Coastguard Worker
286*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
287*0e209d39SAndroid Build Coastguard Worker
288*0e209d39SAndroid Build Coastguard Worker bool
operator ==(const Format & that) const289*0e209d39SAndroid Build Coastguard Worker NumberFormat::operator==(const Format& that) const
290*0e209d39SAndroid Build Coastguard Worker {
291*0e209d39SAndroid Build Coastguard Worker // Format::operator== guarantees this cast is safe
292*0e209d39SAndroid Build Coastguard Worker NumberFormat* other = (NumberFormat*)&that;
293*0e209d39SAndroid Build Coastguard Worker
294*0e209d39SAndroid Build Coastguard Worker #ifdef FMT_DEBUG
295*0e209d39SAndroid Build Coastguard Worker // This code makes it easy to determine why two format objects that should
296*0e209d39SAndroid Build Coastguard Worker // be equal aren't.
297*0e209d39SAndroid Build Coastguard Worker UBool first = true;
298*0e209d39SAndroid Build Coastguard Worker if (!Format::operator==(that)) {
299*0e209d39SAndroid Build Coastguard Worker if (first) { printf("[ "); first = false; } else { printf(", "); }
300*0e209d39SAndroid Build Coastguard Worker debug("Format::!=");
301*0e209d39SAndroid Build Coastguard Worker }
302*0e209d39SAndroid Build Coastguard Worker if (!(fMaxIntegerDigits == other->fMaxIntegerDigits &&
303*0e209d39SAndroid Build Coastguard Worker fMinIntegerDigits == other->fMinIntegerDigits)) {
304*0e209d39SAndroid Build Coastguard Worker if (first) { printf("[ "); first = false; } else { printf(", "); }
305*0e209d39SAndroid Build Coastguard Worker debug("Integer digits !=");
306*0e209d39SAndroid Build Coastguard Worker }
307*0e209d39SAndroid Build Coastguard Worker if (!(fMaxFractionDigits == other->fMaxFractionDigits &&
308*0e209d39SAndroid Build Coastguard Worker fMinFractionDigits == other->fMinFractionDigits)) {
309*0e209d39SAndroid Build Coastguard Worker if (first) { printf("[ "); first = false; } else { printf(", "); }
310*0e209d39SAndroid Build Coastguard Worker debug("Fraction digits !=");
311*0e209d39SAndroid Build Coastguard Worker }
312*0e209d39SAndroid Build Coastguard Worker if (!(fGroupingUsed == other->fGroupingUsed)) {
313*0e209d39SAndroid Build Coastguard Worker if (first) { printf("[ "); first = false; } else { printf(", "); }
314*0e209d39SAndroid Build Coastguard Worker debug("fGroupingUsed != ");
315*0e209d39SAndroid Build Coastguard Worker }
316*0e209d39SAndroid Build Coastguard Worker if (!(fParseIntegerOnly == other->fParseIntegerOnly)) {
317*0e209d39SAndroid Build Coastguard Worker if (first) { printf("[ "); first = false; } else { printf(", "); }
318*0e209d39SAndroid Build Coastguard Worker debug("fParseIntegerOnly != ");
319*0e209d39SAndroid Build Coastguard Worker }
320*0e209d39SAndroid Build Coastguard Worker if (!(u_strcmp(fCurrency, other->fCurrency) == 0)) {
321*0e209d39SAndroid Build Coastguard Worker if (first) { printf("[ "); first = false; } else { printf(", "); }
322*0e209d39SAndroid Build Coastguard Worker debug("fCurrency !=");
323*0e209d39SAndroid Build Coastguard Worker }
324*0e209d39SAndroid Build Coastguard Worker if (!(fLenient == other->fLenient)) {
325*0e209d39SAndroid Build Coastguard Worker if (first) { printf("[ "); first = false; } else { printf(", "); }
326*0e209d39SAndroid Build Coastguard Worker debug("fLenient != ");
327*0e209d39SAndroid Build Coastguard Worker }
328*0e209d39SAndroid Build Coastguard Worker if (!(fCapitalizationContext == other->fCapitalizationContext)) {
329*0e209d39SAndroid Build Coastguard Worker if (first) { printf("[ "); first = false; } else { printf(", "); }
330*0e209d39SAndroid Build Coastguard Worker debug("fCapitalizationContext != ");
331*0e209d39SAndroid Build Coastguard Worker }
332*0e209d39SAndroid Build Coastguard Worker if (!first) { printf(" ]"); }
333*0e209d39SAndroid Build Coastguard Worker #endif
334*0e209d39SAndroid Build Coastguard Worker
335*0e209d39SAndroid Build Coastguard Worker return ((this == &that) ||
336*0e209d39SAndroid Build Coastguard Worker ((Format::operator==(that) &&
337*0e209d39SAndroid Build Coastguard Worker fMaxIntegerDigits == other->fMaxIntegerDigits &&
338*0e209d39SAndroid Build Coastguard Worker fMinIntegerDigits == other->fMinIntegerDigits &&
339*0e209d39SAndroid Build Coastguard Worker fMaxFractionDigits == other->fMaxFractionDigits &&
340*0e209d39SAndroid Build Coastguard Worker fMinFractionDigits == other->fMinFractionDigits &&
341*0e209d39SAndroid Build Coastguard Worker fGroupingUsed == other->fGroupingUsed &&
342*0e209d39SAndroid Build Coastguard Worker fParseIntegerOnly == other->fParseIntegerOnly &&
343*0e209d39SAndroid Build Coastguard Worker u_strcmp(fCurrency, other->fCurrency) == 0 &&
344*0e209d39SAndroid Build Coastguard Worker fLenient == other->fLenient &&
345*0e209d39SAndroid Build Coastguard Worker fCapitalizationContext == other->fCapitalizationContext)));
346*0e209d39SAndroid Build Coastguard Worker }
347*0e209d39SAndroid Build Coastguard Worker
348*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
349*0e209d39SAndroid Build Coastguard Worker // Default implementation sets unsupported error; subclasses should
350*0e209d39SAndroid Build Coastguard Worker // override.
351*0e209d39SAndroid Build Coastguard Worker
352*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(double,UnicodeString & toAppendTo,FieldPositionIterator *,UErrorCode & status) const353*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(double /* unused number */,
354*0e209d39SAndroid Build Coastguard Worker UnicodeString& toAppendTo,
355*0e209d39SAndroid Build Coastguard Worker FieldPositionIterator* /* unused posIter */,
356*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) const
357*0e209d39SAndroid Build Coastguard Worker {
358*0e209d39SAndroid Build Coastguard Worker if (!U_FAILURE(status)) {
359*0e209d39SAndroid Build Coastguard Worker status = U_UNSUPPORTED_ERROR;
360*0e209d39SAndroid Build Coastguard Worker }
361*0e209d39SAndroid Build Coastguard Worker return toAppendTo;
362*0e209d39SAndroid Build Coastguard Worker }
363*0e209d39SAndroid Build Coastguard Worker
364*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
365*0e209d39SAndroid Build Coastguard Worker // Default implementation sets unsupported error; subclasses should
366*0e209d39SAndroid Build Coastguard Worker // override.
367*0e209d39SAndroid Build Coastguard Worker
368*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(int32_t,UnicodeString & toAppendTo,FieldPositionIterator *,UErrorCode & status) const369*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(int32_t /* unused number */,
370*0e209d39SAndroid Build Coastguard Worker UnicodeString& toAppendTo,
371*0e209d39SAndroid Build Coastguard Worker FieldPositionIterator* /* unused posIter */,
372*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) const
373*0e209d39SAndroid Build Coastguard Worker {
374*0e209d39SAndroid Build Coastguard Worker if (!U_FAILURE(status)) {
375*0e209d39SAndroid Build Coastguard Worker status = U_UNSUPPORTED_ERROR;
376*0e209d39SAndroid Build Coastguard Worker }
377*0e209d39SAndroid Build Coastguard Worker return toAppendTo;
378*0e209d39SAndroid Build Coastguard Worker }
379*0e209d39SAndroid Build Coastguard Worker
380*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
381*0e209d39SAndroid Build Coastguard Worker // Default implementation sets unsupported error; subclasses should
382*0e209d39SAndroid Build Coastguard Worker // override.
383*0e209d39SAndroid Build Coastguard Worker
384*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(int64_t,UnicodeString & toAppendTo,FieldPositionIterator *,UErrorCode & status) const385*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(int64_t /* unused number */,
386*0e209d39SAndroid Build Coastguard Worker UnicodeString& toAppendTo,
387*0e209d39SAndroid Build Coastguard Worker FieldPositionIterator* /* unused posIter */,
388*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) const
389*0e209d39SAndroid Build Coastguard Worker {
390*0e209d39SAndroid Build Coastguard Worker if (!U_FAILURE(status)) {
391*0e209d39SAndroid Build Coastguard Worker status = U_UNSUPPORTED_ERROR;
392*0e209d39SAndroid Build Coastguard Worker }
393*0e209d39SAndroid Build Coastguard Worker return toAppendTo;
394*0e209d39SAndroid Build Coastguard Worker }
395*0e209d39SAndroid Build Coastguard Worker
396*0e209d39SAndroid Build Coastguard Worker // ------------------------------------------
397*0e209d39SAndroid Build Coastguard Worker // These functions add the status code, just fall back to the non-status versions
398*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(double number,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const399*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(double number,
400*0e209d39SAndroid Build Coastguard Worker UnicodeString& appendTo,
401*0e209d39SAndroid Build Coastguard Worker FieldPosition& pos,
402*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const {
403*0e209d39SAndroid Build Coastguard Worker if(U_SUCCESS(status)) {
404*0e209d39SAndroid Build Coastguard Worker return format(number,appendTo,pos);
405*0e209d39SAndroid Build Coastguard Worker } else {
406*0e209d39SAndroid Build Coastguard Worker return appendTo;
407*0e209d39SAndroid Build Coastguard Worker }
408*0e209d39SAndroid Build Coastguard Worker }
409*0e209d39SAndroid Build Coastguard Worker
410*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(int32_t number,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const411*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(int32_t number,
412*0e209d39SAndroid Build Coastguard Worker UnicodeString& appendTo,
413*0e209d39SAndroid Build Coastguard Worker FieldPosition& pos,
414*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const {
415*0e209d39SAndroid Build Coastguard Worker if(U_SUCCESS(status)) {
416*0e209d39SAndroid Build Coastguard Worker return format(number,appendTo,pos);
417*0e209d39SAndroid Build Coastguard Worker } else {
418*0e209d39SAndroid Build Coastguard Worker return appendTo;
419*0e209d39SAndroid Build Coastguard Worker }
420*0e209d39SAndroid Build Coastguard Worker }
421*0e209d39SAndroid Build Coastguard Worker
422*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(int64_t number,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const423*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(int64_t number,
424*0e209d39SAndroid Build Coastguard Worker UnicodeString& appendTo,
425*0e209d39SAndroid Build Coastguard Worker FieldPosition& pos,
426*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const {
427*0e209d39SAndroid Build Coastguard Worker if(U_SUCCESS(status)) {
428*0e209d39SAndroid Build Coastguard Worker return format(number,appendTo,pos);
429*0e209d39SAndroid Build Coastguard Worker } else {
430*0e209d39SAndroid Build Coastguard Worker return appendTo;
431*0e209d39SAndroid Build Coastguard Worker }
432*0e209d39SAndroid Build Coastguard Worker }
433*0e209d39SAndroid Build Coastguard Worker
434*0e209d39SAndroid Build Coastguard Worker
435*0e209d39SAndroid Build Coastguard Worker
436*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
437*0e209d39SAndroid Build Coastguard Worker // Decimal Number format() default implementation
438*0e209d39SAndroid Build Coastguard Worker // Subclasses do not normally override this function, but rather the DigitList
439*0e209d39SAndroid Build Coastguard Worker // formatting functions..
440*0e209d39SAndroid Build Coastguard Worker // The expected call chain from here is
441*0e209d39SAndroid Build Coastguard Worker // this function ->
442*0e209d39SAndroid Build Coastguard Worker // NumberFormat::format(Formattable ->
443*0e209d39SAndroid Build Coastguard Worker // DecimalFormat::format(DigitList
444*0e209d39SAndroid Build Coastguard Worker //
445*0e209d39SAndroid Build Coastguard Worker // Or, for subclasses of Formattable that do not know about DigitList,
446*0e209d39SAndroid Build Coastguard Worker // this Function ->
447*0e209d39SAndroid Build Coastguard Worker // NumberFormat::format(Formattable ->
448*0e209d39SAndroid Build Coastguard Worker // NumberFormat::format(DigitList ->
449*0e209d39SAndroid Build Coastguard Worker // XXXFormat::format(double
450*0e209d39SAndroid Build Coastguard Worker
451*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(StringPiece decimalNum,UnicodeString & toAppendTo,FieldPositionIterator * fpi,UErrorCode & status) const452*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(StringPiece decimalNum,
453*0e209d39SAndroid Build Coastguard Worker UnicodeString& toAppendTo,
454*0e209d39SAndroid Build Coastguard Worker FieldPositionIterator* fpi,
455*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) const
456*0e209d39SAndroid Build Coastguard Worker {
457*0e209d39SAndroid Build Coastguard Worker Formattable f;
458*0e209d39SAndroid Build Coastguard Worker f.setDecimalNumber(decimalNum, status);
459*0e209d39SAndroid Build Coastguard Worker format(f, toAppendTo, fpi, status);
460*0e209d39SAndroid Build Coastguard Worker return toAppendTo;
461*0e209d39SAndroid Build Coastguard Worker }
462*0e209d39SAndroid Build Coastguard Worker
463*0e209d39SAndroid Build Coastguard Worker /**
464*0e209d39SAndroid Build Coastguard Worker *
465*0e209d39SAndroid Build Coastguard Worker // Formats the number object and save the format
466*0e209d39SAndroid Build Coastguard Worker // result in the toAppendTo string buffer.
467*0e209d39SAndroid Build Coastguard Worker
468*0e209d39SAndroid Build Coastguard Worker // utility to save/restore state, used in two overloads
469*0e209d39SAndroid Build Coastguard Worker // of format(const Formattable&...) below.
470*0e209d39SAndroid Build Coastguard Worker *
471*0e209d39SAndroid Build Coastguard Worker * Old purpose of ArgExtractor was to avoid const. Not thread safe!
472*0e209d39SAndroid Build Coastguard Worker *
473*0e209d39SAndroid Build Coastguard Worker * keeping it around as a shim.
474*0e209d39SAndroid Build Coastguard Worker */
475*0e209d39SAndroid Build Coastguard Worker class ArgExtractor {
476*0e209d39SAndroid Build Coastguard Worker const Formattable* num;
477*0e209d39SAndroid Build Coastguard Worker char16_t save[4];
478*0e209d39SAndroid Build Coastguard Worker UBool fWasCurrency;
479*0e209d39SAndroid Build Coastguard Worker
480*0e209d39SAndroid Build Coastguard Worker public:
481*0e209d39SAndroid Build Coastguard Worker ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status);
482*0e209d39SAndroid Build Coastguard Worker ~ArgExtractor();
483*0e209d39SAndroid Build Coastguard Worker
484*0e209d39SAndroid Build Coastguard Worker const Formattable* number() const;
485*0e209d39SAndroid Build Coastguard Worker const char16_t *iso() const;
486*0e209d39SAndroid Build Coastguard Worker UBool wasCurrency() const;
487*0e209d39SAndroid Build Coastguard Worker };
488*0e209d39SAndroid Build Coastguard Worker
489*0e209d39SAndroid Build Coastguard Worker inline const Formattable*
number() const490*0e209d39SAndroid Build Coastguard Worker ArgExtractor::number() const {
491*0e209d39SAndroid Build Coastguard Worker return num;
492*0e209d39SAndroid Build Coastguard Worker }
493*0e209d39SAndroid Build Coastguard Worker
494*0e209d39SAndroid Build Coastguard Worker inline UBool
wasCurrency() const495*0e209d39SAndroid Build Coastguard Worker ArgExtractor::wasCurrency() const {
496*0e209d39SAndroid Build Coastguard Worker return fWasCurrency;
497*0e209d39SAndroid Build Coastguard Worker }
498*0e209d39SAndroid Build Coastguard Worker
499*0e209d39SAndroid Build Coastguard Worker inline const char16_t *
iso() const500*0e209d39SAndroid Build Coastguard Worker ArgExtractor::iso() const {
501*0e209d39SAndroid Build Coastguard Worker return save;
502*0e209d39SAndroid Build Coastguard Worker }
503*0e209d39SAndroid Build Coastguard Worker
ArgExtractor(const NumberFormat &,const Formattable & obj,UErrorCode &)504*0e209d39SAndroid Build Coastguard Worker ArgExtractor::ArgExtractor(const NumberFormat& /*nf*/, const Formattable& obj, UErrorCode& /*status*/)
505*0e209d39SAndroid Build Coastguard Worker : num(&obj), fWasCurrency(false) {
506*0e209d39SAndroid Build Coastguard Worker
507*0e209d39SAndroid Build Coastguard Worker const UObject* o = obj.getObject(); // most commonly o==nullptr
508*0e209d39SAndroid Build Coastguard Worker const CurrencyAmount* amt;
509*0e209d39SAndroid Build Coastguard Worker if (o != nullptr && (amt = dynamic_cast<const CurrencyAmount*>(o)) != nullptr) {
510*0e209d39SAndroid Build Coastguard Worker // getISOCurrency() returns a pointer to internal storage, so we
511*0e209d39SAndroid Build Coastguard Worker // copy it to retain it across the call to setCurrency().
512*0e209d39SAndroid Build Coastguard Worker //const char16_t* curr = amt->getISOCurrency();
513*0e209d39SAndroid Build Coastguard Worker u_strcpy(save, amt->getISOCurrency());
514*0e209d39SAndroid Build Coastguard Worker num = &amt->getNumber();
515*0e209d39SAndroid Build Coastguard Worker fWasCurrency=true;
516*0e209d39SAndroid Build Coastguard Worker } else {
517*0e209d39SAndroid Build Coastguard Worker save[0]=0;
518*0e209d39SAndroid Build Coastguard Worker }
519*0e209d39SAndroid Build Coastguard Worker }
520*0e209d39SAndroid Build Coastguard Worker
~ArgExtractor()521*0e209d39SAndroid Build Coastguard Worker ArgExtractor::~ArgExtractor() {
522*0e209d39SAndroid Build Coastguard Worker }
523*0e209d39SAndroid Build Coastguard Worker
format(const number::impl::DecimalQuantity & number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const524*0e209d39SAndroid Build Coastguard Worker UnicodeString& NumberFormat::format(const number::impl::DecimalQuantity &number,
525*0e209d39SAndroid Build Coastguard Worker UnicodeString& appendTo,
526*0e209d39SAndroid Build Coastguard Worker FieldPositionIterator* posIter,
527*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) const {
528*0e209d39SAndroid Build Coastguard Worker // DecimalFormat overrides this function, and handles DigitList based big decimals.
529*0e209d39SAndroid Build Coastguard Worker // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists,
530*0e209d39SAndroid Build Coastguard Worker // so this default implementation falls back to formatting decimal numbers as doubles.
531*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
532*0e209d39SAndroid Build Coastguard Worker return appendTo;
533*0e209d39SAndroid Build Coastguard Worker }
534*0e209d39SAndroid Build Coastguard Worker double dnum = number.toDouble();
535*0e209d39SAndroid Build Coastguard Worker format(dnum, appendTo, posIter, status);
536*0e209d39SAndroid Build Coastguard Worker return appendTo;
537*0e209d39SAndroid Build Coastguard Worker }
538*0e209d39SAndroid Build Coastguard Worker
539*0e209d39SAndroid Build Coastguard Worker
540*0e209d39SAndroid Build Coastguard Worker
541*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(const number::impl::DecimalQuantity & number,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const542*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(const number::impl::DecimalQuantity &number,
543*0e209d39SAndroid Build Coastguard Worker UnicodeString& appendTo,
544*0e209d39SAndroid Build Coastguard Worker FieldPosition& pos,
545*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const {
546*0e209d39SAndroid Build Coastguard Worker // DecimalFormat overrides this function, and handles DigitList based big decimals.
547*0e209d39SAndroid Build Coastguard Worker // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists,
548*0e209d39SAndroid Build Coastguard Worker // so this default implementation falls back to formatting decimal numbers as doubles.
549*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
550*0e209d39SAndroid Build Coastguard Worker return appendTo;
551*0e209d39SAndroid Build Coastguard Worker }
552*0e209d39SAndroid Build Coastguard Worker double dnum = number.toDouble();
553*0e209d39SAndroid Build Coastguard Worker format(dnum, appendTo, pos, status);
554*0e209d39SAndroid Build Coastguard Worker return appendTo;
555*0e209d39SAndroid Build Coastguard Worker }
556*0e209d39SAndroid Build Coastguard Worker
557*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(const Formattable & obj,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const558*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(const Formattable& obj,
559*0e209d39SAndroid Build Coastguard Worker UnicodeString& appendTo,
560*0e209d39SAndroid Build Coastguard Worker FieldPosition& pos,
561*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) const
562*0e209d39SAndroid Build Coastguard Worker {
563*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) return appendTo;
564*0e209d39SAndroid Build Coastguard Worker
565*0e209d39SAndroid Build Coastguard Worker ArgExtractor arg(*this, obj, status);
566*0e209d39SAndroid Build Coastguard Worker const Formattable *n = arg.number();
567*0e209d39SAndroid Build Coastguard Worker const char16_t *iso = arg.iso();
568*0e209d39SAndroid Build Coastguard Worker
569*0e209d39SAndroid Build Coastguard Worker if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) {
570*0e209d39SAndroid Build Coastguard Worker // trying to format a different currency.
571*0e209d39SAndroid Build Coastguard Worker // Right now, we clone.
572*0e209d39SAndroid Build Coastguard Worker LocalPointer<NumberFormat> cloneFmt(this->clone());
573*0e209d39SAndroid Build Coastguard Worker cloneFmt->setCurrency(iso, status);
574*0e209d39SAndroid Build Coastguard Worker // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount.
575*0e209d39SAndroid Build Coastguard Worker return cloneFmt->format(*n, appendTo, pos, status);
576*0e209d39SAndroid Build Coastguard Worker }
577*0e209d39SAndroid Build Coastguard Worker
578*0e209d39SAndroid Build Coastguard Worker if (n->isNumeric() && n->getDecimalQuantity() != nullptr) {
579*0e209d39SAndroid Build Coastguard Worker // Decimal Number. We will have a DigitList available if the value was
580*0e209d39SAndroid Build Coastguard Worker // set to a decimal number, or if the value originated with a parse.
581*0e209d39SAndroid Build Coastguard Worker //
582*0e209d39SAndroid Build Coastguard Worker // The default implementation for formatting a DigitList converts it
583*0e209d39SAndroid Build Coastguard Worker // to a double, and formats that, allowing formatting classes that don't
584*0e209d39SAndroid Build Coastguard Worker // know about DigitList to continue to operate as they had.
585*0e209d39SAndroid Build Coastguard Worker //
586*0e209d39SAndroid Build Coastguard Worker // DecimalFormat overrides the DigitList formatting functions.
587*0e209d39SAndroid Build Coastguard Worker format(*n->getDecimalQuantity(), appendTo, pos, status);
588*0e209d39SAndroid Build Coastguard Worker } else {
589*0e209d39SAndroid Build Coastguard Worker switch (n->getType()) {
590*0e209d39SAndroid Build Coastguard Worker case Formattable::kDouble:
591*0e209d39SAndroid Build Coastguard Worker format(n->getDouble(), appendTo, pos, status);
592*0e209d39SAndroid Build Coastguard Worker break;
593*0e209d39SAndroid Build Coastguard Worker case Formattable::kLong:
594*0e209d39SAndroid Build Coastguard Worker format(n->getLong(), appendTo, pos, status);
595*0e209d39SAndroid Build Coastguard Worker break;
596*0e209d39SAndroid Build Coastguard Worker case Formattable::kInt64:
597*0e209d39SAndroid Build Coastguard Worker format(n->getInt64(), appendTo, pos, status);
598*0e209d39SAndroid Build Coastguard Worker break;
599*0e209d39SAndroid Build Coastguard Worker default:
600*0e209d39SAndroid Build Coastguard Worker status = U_INVALID_FORMAT_ERROR;
601*0e209d39SAndroid Build Coastguard Worker break;
602*0e209d39SAndroid Build Coastguard Worker }
603*0e209d39SAndroid Build Coastguard Worker }
604*0e209d39SAndroid Build Coastguard Worker
605*0e209d39SAndroid Build Coastguard Worker return appendTo;
606*0e209d39SAndroid Build Coastguard Worker }
607*0e209d39SAndroid Build Coastguard Worker
608*0e209d39SAndroid Build Coastguard Worker // -------------------------------------x
609*0e209d39SAndroid Build Coastguard Worker // Formats the number object and save the format
610*0e209d39SAndroid Build Coastguard Worker // result in the toAppendTo string buffer.
611*0e209d39SAndroid Build Coastguard Worker
612*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(const Formattable & obj,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const613*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(const Formattable& obj,
614*0e209d39SAndroid Build Coastguard Worker UnicodeString& appendTo,
615*0e209d39SAndroid Build Coastguard Worker FieldPositionIterator* posIter,
616*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) const
617*0e209d39SAndroid Build Coastguard Worker {
618*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) return appendTo;
619*0e209d39SAndroid Build Coastguard Worker
620*0e209d39SAndroid Build Coastguard Worker ArgExtractor arg(*this, obj, status);
621*0e209d39SAndroid Build Coastguard Worker const Formattable *n = arg.number();
622*0e209d39SAndroid Build Coastguard Worker const char16_t *iso = arg.iso();
623*0e209d39SAndroid Build Coastguard Worker
624*0e209d39SAndroid Build Coastguard Worker if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) {
625*0e209d39SAndroid Build Coastguard Worker // trying to format a different currency.
626*0e209d39SAndroid Build Coastguard Worker // Right now, we clone.
627*0e209d39SAndroid Build Coastguard Worker LocalPointer<NumberFormat> cloneFmt(this->clone());
628*0e209d39SAndroid Build Coastguard Worker cloneFmt->setCurrency(iso, status);
629*0e209d39SAndroid Build Coastguard Worker // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount.
630*0e209d39SAndroid Build Coastguard Worker return cloneFmt->format(*n, appendTo, posIter, status);
631*0e209d39SAndroid Build Coastguard Worker }
632*0e209d39SAndroid Build Coastguard Worker
633*0e209d39SAndroid Build Coastguard Worker if (n->isNumeric() && n->getDecimalQuantity() != nullptr) {
634*0e209d39SAndroid Build Coastguard Worker // Decimal Number
635*0e209d39SAndroid Build Coastguard Worker format(*n->getDecimalQuantity(), appendTo, posIter, status);
636*0e209d39SAndroid Build Coastguard Worker } else {
637*0e209d39SAndroid Build Coastguard Worker switch (n->getType()) {
638*0e209d39SAndroid Build Coastguard Worker case Formattable::kDouble:
639*0e209d39SAndroid Build Coastguard Worker format(n->getDouble(), appendTo, posIter, status);
640*0e209d39SAndroid Build Coastguard Worker break;
641*0e209d39SAndroid Build Coastguard Worker case Formattable::kLong:
642*0e209d39SAndroid Build Coastguard Worker format(n->getLong(), appendTo, posIter, status);
643*0e209d39SAndroid Build Coastguard Worker break;
644*0e209d39SAndroid Build Coastguard Worker case Formattable::kInt64:
645*0e209d39SAndroid Build Coastguard Worker format(n->getInt64(), appendTo, posIter, status);
646*0e209d39SAndroid Build Coastguard Worker break;
647*0e209d39SAndroid Build Coastguard Worker default:
648*0e209d39SAndroid Build Coastguard Worker status = U_INVALID_FORMAT_ERROR;
649*0e209d39SAndroid Build Coastguard Worker break;
650*0e209d39SAndroid Build Coastguard Worker }
651*0e209d39SAndroid Build Coastguard Worker }
652*0e209d39SAndroid Build Coastguard Worker
653*0e209d39SAndroid Build Coastguard Worker return appendTo;
654*0e209d39SAndroid Build Coastguard Worker }
655*0e209d39SAndroid Build Coastguard Worker
656*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
657*0e209d39SAndroid Build Coastguard Worker
658*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(int64_t number,UnicodeString & appendTo,FieldPosition & pos) const659*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(int64_t number,
660*0e209d39SAndroid Build Coastguard Worker UnicodeString& appendTo,
661*0e209d39SAndroid Build Coastguard Worker FieldPosition& pos) const
662*0e209d39SAndroid Build Coastguard Worker {
663*0e209d39SAndroid Build Coastguard Worker // default so we don't introduce a new abstract method
664*0e209d39SAndroid Build Coastguard Worker return format((int32_t)number, appendTo, pos);
665*0e209d39SAndroid Build Coastguard Worker }
666*0e209d39SAndroid Build Coastguard Worker
667*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
668*0e209d39SAndroid Build Coastguard Worker // Parses the string and save the result object as well
669*0e209d39SAndroid Build Coastguard Worker // as the final parsed position.
670*0e209d39SAndroid Build Coastguard Worker
671*0e209d39SAndroid Build Coastguard Worker void
parseObject(const UnicodeString & source,Formattable & result,ParsePosition & parse_pos) const672*0e209d39SAndroid Build Coastguard Worker NumberFormat::parseObject(const UnicodeString& source,
673*0e209d39SAndroid Build Coastguard Worker Formattable& result,
674*0e209d39SAndroid Build Coastguard Worker ParsePosition& parse_pos) const
675*0e209d39SAndroid Build Coastguard Worker {
676*0e209d39SAndroid Build Coastguard Worker parse(source, result, parse_pos);
677*0e209d39SAndroid Build Coastguard Worker }
678*0e209d39SAndroid Build Coastguard Worker
679*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
680*0e209d39SAndroid Build Coastguard Worker // Formats a double number and save the result in a string.
681*0e209d39SAndroid Build Coastguard Worker
682*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(double number,UnicodeString & appendTo) const683*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(double number, UnicodeString& appendTo) const
684*0e209d39SAndroid Build Coastguard Worker {
685*0e209d39SAndroid Build Coastguard Worker FieldPosition pos(FieldPosition::DONT_CARE);
686*0e209d39SAndroid Build Coastguard Worker return format(number, appendTo, pos);
687*0e209d39SAndroid Build Coastguard Worker }
688*0e209d39SAndroid Build Coastguard Worker
689*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
690*0e209d39SAndroid Build Coastguard Worker // Formats a long number and save the result in a string.
691*0e209d39SAndroid Build Coastguard Worker
692*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(int32_t number,UnicodeString & appendTo) const693*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(int32_t number, UnicodeString& appendTo) const
694*0e209d39SAndroid Build Coastguard Worker {
695*0e209d39SAndroid Build Coastguard Worker FieldPosition pos(FieldPosition::DONT_CARE);
696*0e209d39SAndroid Build Coastguard Worker return format(number, appendTo, pos);
697*0e209d39SAndroid Build Coastguard Worker }
698*0e209d39SAndroid Build Coastguard Worker
699*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
700*0e209d39SAndroid Build Coastguard Worker // Formats a long number and save the result in a string.
701*0e209d39SAndroid Build Coastguard Worker
702*0e209d39SAndroid Build Coastguard Worker UnicodeString&
format(int64_t number,UnicodeString & appendTo) const703*0e209d39SAndroid Build Coastguard Worker NumberFormat::format(int64_t number, UnicodeString& appendTo) const
704*0e209d39SAndroid Build Coastguard Worker {
705*0e209d39SAndroid Build Coastguard Worker FieldPosition pos(FieldPosition::DONT_CARE);
706*0e209d39SAndroid Build Coastguard Worker return format(number, appendTo, pos);
707*0e209d39SAndroid Build Coastguard Worker }
708*0e209d39SAndroid Build Coastguard Worker
709*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
710*0e209d39SAndroid Build Coastguard Worker // Parses the text and save the result object. If the returned
711*0e209d39SAndroid Build Coastguard Worker // parse position is 0, that means the parsing failed, the status
712*0e209d39SAndroid Build Coastguard Worker // code needs to be set to failure. Ignores the returned parse
713*0e209d39SAndroid Build Coastguard Worker // position, otherwise.
714*0e209d39SAndroid Build Coastguard Worker
715*0e209d39SAndroid Build Coastguard Worker void
parse(const UnicodeString & text,Formattable & result,UErrorCode & status) const716*0e209d39SAndroid Build Coastguard Worker NumberFormat::parse(const UnicodeString& text,
717*0e209d39SAndroid Build Coastguard Worker Formattable& result,
718*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) const
719*0e209d39SAndroid Build Coastguard Worker {
720*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) return;
721*0e209d39SAndroid Build Coastguard Worker
722*0e209d39SAndroid Build Coastguard Worker ParsePosition parsePosition(0);
723*0e209d39SAndroid Build Coastguard Worker parse(text, result, parsePosition);
724*0e209d39SAndroid Build Coastguard Worker if (parsePosition.getIndex() == 0) {
725*0e209d39SAndroid Build Coastguard Worker status = U_INVALID_FORMAT_ERROR;
726*0e209d39SAndroid Build Coastguard Worker }
727*0e209d39SAndroid Build Coastguard Worker }
728*0e209d39SAndroid Build Coastguard Worker
parseCurrency(const UnicodeString & text,ParsePosition & pos) const729*0e209d39SAndroid Build Coastguard Worker CurrencyAmount* NumberFormat::parseCurrency(const UnicodeString& text,
730*0e209d39SAndroid Build Coastguard Worker ParsePosition& pos) const {
731*0e209d39SAndroid Build Coastguard Worker // Default implementation only -- subclasses should override
732*0e209d39SAndroid Build Coastguard Worker Formattable parseResult;
733*0e209d39SAndroid Build Coastguard Worker int32_t start = pos.getIndex();
734*0e209d39SAndroid Build Coastguard Worker parse(text, parseResult, pos);
735*0e209d39SAndroid Build Coastguard Worker if (pos.getIndex() != start) {
736*0e209d39SAndroid Build Coastguard Worker char16_t curr[4];
737*0e209d39SAndroid Build Coastguard Worker UErrorCode ec = U_ZERO_ERROR;
738*0e209d39SAndroid Build Coastguard Worker getEffectiveCurrency(curr, ec);
739*0e209d39SAndroid Build Coastguard Worker if (U_SUCCESS(ec)) {
740*0e209d39SAndroid Build Coastguard Worker LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curr, ec), ec);
741*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(ec)) {
742*0e209d39SAndroid Build Coastguard Worker pos.setIndex(start); // indicate failure
743*0e209d39SAndroid Build Coastguard Worker } else {
744*0e209d39SAndroid Build Coastguard Worker return currAmt.orphan();
745*0e209d39SAndroid Build Coastguard Worker }
746*0e209d39SAndroid Build Coastguard Worker }
747*0e209d39SAndroid Build Coastguard Worker }
748*0e209d39SAndroid Build Coastguard Worker return nullptr;
749*0e209d39SAndroid Build Coastguard Worker }
750*0e209d39SAndroid Build Coastguard Worker
751*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
752*0e209d39SAndroid Build Coastguard Worker // Sets to only parse integers.
753*0e209d39SAndroid Build Coastguard Worker
754*0e209d39SAndroid Build Coastguard Worker void
setParseIntegerOnly(UBool value)755*0e209d39SAndroid Build Coastguard Worker NumberFormat::setParseIntegerOnly(UBool value)
756*0e209d39SAndroid Build Coastguard Worker {
757*0e209d39SAndroid Build Coastguard Worker fParseIntegerOnly = value;
758*0e209d39SAndroid Build Coastguard Worker }
759*0e209d39SAndroid Build Coastguard Worker
760*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
761*0e209d39SAndroid Build Coastguard Worker // Sets whether lenient parse is enabled.
762*0e209d39SAndroid Build Coastguard Worker
763*0e209d39SAndroid Build Coastguard Worker void
setLenient(UBool enable)764*0e209d39SAndroid Build Coastguard Worker NumberFormat::setLenient(UBool enable)
765*0e209d39SAndroid Build Coastguard Worker {
766*0e209d39SAndroid Build Coastguard Worker fLenient = enable;
767*0e209d39SAndroid Build Coastguard Worker }
768*0e209d39SAndroid Build Coastguard Worker
769*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
770*0e209d39SAndroid Build Coastguard Worker // Create a number style NumberFormat instance with the default locale.
771*0e209d39SAndroid Build Coastguard Worker
772*0e209d39SAndroid Build Coastguard Worker NumberFormat* U_EXPORT2
createInstance(UErrorCode & status)773*0e209d39SAndroid Build Coastguard Worker NumberFormat::createInstance(UErrorCode& status)
774*0e209d39SAndroid Build Coastguard Worker {
775*0e209d39SAndroid Build Coastguard Worker return createInstance(Locale::getDefault(), UNUM_DECIMAL, status);
776*0e209d39SAndroid Build Coastguard Worker }
777*0e209d39SAndroid Build Coastguard Worker
778*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
779*0e209d39SAndroid Build Coastguard Worker // Create a number style NumberFormat instance with the inLocale locale.
780*0e209d39SAndroid Build Coastguard Worker
781*0e209d39SAndroid Build Coastguard Worker NumberFormat* U_EXPORT2
createInstance(const Locale & inLocale,UErrorCode & status)782*0e209d39SAndroid Build Coastguard Worker NumberFormat::createInstance(const Locale& inLocale, UErrorCode& status)
783*0e209d39SAndroid Build Coastguard Worker {
784*0e209d39SAndroid Build Coastguard Worker return createInstance(inLocale, UNUM_DECIMAL, status);
785*0e209d39SAndroid Build Coastguard Worker }
786*0e209d39SAndroid Build Coastguard Worker
787*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
788*0e209d39SAndroid Build Coastguard Worker // Create a currency style NumberFormat instance with the default locale.
789*0e209d39SAndroid Build Coastguard Worker
790*0e209d39SAndroid Build Coastguard Worker NumberFormat* U_EXPORT2
createCurrencyInstance(UErrorCode & status)791*0e209d39SAndroid Build Coastguard Worker NumberFormat::createCurrencyInstance(UErrorCode& status)
792*0e209d39SAndroid Build Coastguard Worker {
793*0e209d39SAndroid Build Coastguard Worker return createCurrencyInstance(Locale::getDefault(), status);
794*0e209d39SAndroid Build Coastguard Worker }
795*0e209d39SAndroid Build Coastguard Worker
796*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
797*0e209d39SAndroid Build Coastguard Worker // Create a currency style NumberFormat instance with the inLocale locale.
798*0e209d39SAndroid Build Coastguard Worker
799*0e209d39SAndroid Build Coastguard Worker NumberFormat* U_EXPORT2
createCurrencyInstance(const Locale & inLocale,UErrorCode & status)800*0e209d39SAndroid Build Coastguard Worker NumberFormat::createCurrencyInstance(const Locale& inLocale, UErrorCode& status)
801*0e209d39SAndroid Build Coastguard Worker {
802*0e209d39SAndroid Build Coastguard Worker return createInstance(inLocale, UNUM_CURRENCY, status);
803*0e209d39SAndroid Build Coastguard Worker }
804*0e209d39SAndroid Build Coastguard Worker
805*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
806*0e209d39SAndroid Build Coastguard Worker // Create a percent style NumberFormat instance with the default locale.
807*0e209d39SAndroid Build Coastguard Worker
808*0e209d39SAndroid Build Coastguard Worker NumberFormat* U_EXPORT2
createPercentInstance(UErrorCode & status)809*0e209d39SAndroid Build Coastguard Worker NumberFormat::createPercentInstance(UErrorCode& status)
810*0e209d39SAndroid Build Coastguard Worker {
811*0e209d39SAndroid Build Coastguard Worker return createInstance(Locale::getDefault(), UNUM_PERCENT, status);
812*0e209d39SAndroid Build Coastguard Worker }
813*0e209d39SAndroid Build Coastguard Worker
814*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
815*0e209d39SAndroid Build Coastguard Worker // Create a percent style NumberFormat instance with the inLocale locale.
816*0e209d39SAndroid Build Coastguard Worker
817*0e209d39SAndroid Build Coastguard Worker NumberFormat* U_EXPORT2
createPercentInstance(const Locale & inLocale,UErrorCode & status)818*0e209d39SAndroid Build Coastguard Worker NumberFormat::createPercentInstance(const Locale& inLocale, UErrorCode& status)
819*0e209d39SAndroid Build Coastguard Worker {
820*0e209d39SAndroid Build Coastguard Worker return createInstance(inLocale, UNUM_PERCENT, status);
821*0e209d39SAndroid Build Coastguard Worker }
822*0e209d39SAndroid Build Coastguard Worker
823*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
824*0e209d39SAndroid Build Coastguard Worker // Create a scientific style NumberFormat instance with the default locale.
825*0e209d39SAndroid Build Coastguard Worker
826*0e209d39SAndroid Build Coastguard Worker NumberFormat* U_EXPORT2
createScientificInstance(UErrorCode & status)827*0e209d39SAndroid Build Coastguard Worker NumberFormat::createScientificInstance(UErrorCode& status)
828*0e209d39SAndroid Build Coastguard Worker {
829*0e209d39SAndroid Build Coastguard Worker return createInstance(Locale::getDefault(), UNUM_SCIENTIFIC, status);
830*0e209d39SAndroid Build Coastguard Worker }
831*0e209d39SAndroid Build Coastguard Worker
832*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
833*0e209d39SAndroid Build Coastguard Worker // Create a scientific style NumberFormat instance with the inLocale locale.
834*0e209d39SAndroid Build Coastguard Worker
835*0e209d39SAndroid Build Coastguard Worker NumberFormat* U_EXPORT2
createScientificInstance(const Locale & inLocale,UErrorCode & status)836*0e209d39SAndroid Build Coastguard Worker NumberFormat::createScientificInstance(const Locale& inLocale, UErrorCode& status)
837*0e209d39SAndroid Build Coastguard Worker {
838*0e209d39SAndroid Build Coastguard Worker return createInstance(inLocale, UNUM_SCIENTIFIC, status);
839*0e209d39SAndroid Build Coastguard Worker }
840*0e209d39SAndroid Build Coastguard Worker
841*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
842*0e209d39SAndroid Build Coastguard Worker
843*0e209d39SAndroid Build Coastguard Worker const Locale* U_EXPORT2
getAvailableLocales(int32_t & count)844*0e209d39SAndroid Build Coastguard Worker NumberFormat::getAvailableLocales(int32_t& count)
845*0e209d39SAndroid Build Coastguard Worker {
846*0e209d39SAndroid Build Coastguard Worker return Locale::getAvailableLocales(count);
847*0e209d39SAndroid Build Coastguard Worker }
848*0e209d39SAndroid Build Coastguard Worker
849*0e209d39SAndroid Build Coastguard Worker // ------------------------------------------
850*0e209d39SAndroid Build Coastguard Worker //
851*0e209d39SAndroid Build Coastguard Worker // Registration
852*0e209d39SAndroid Build Coastguard Worker //
853*0e209d39SAndroid Build Coastguard Worker //-------------------------------------------
854*0e209d39SAndroid Build Coastguard Worker
855*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_SERVICE
856*0e209d39SAndroid Build Coastguard Worker
857*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
858*0e209d39SAndroid Build Coastguard Worker
859*0e209d39SAndroid Build Coastguard Worker class ICUNumberFormatFactory : public ICUResourceBundleFactory {
860*0e209d39SAndroid Build Coastguard Worker public:
861*0e209d39SAndroid Build Coastguard Worker virtual ~ICUNumberFormatFactory();
862*0e209d39SAndroid Build Coastguard Worker protected:
handleCreate(const Locale & loc,int32_t kind,const ICUService *,UErrorCode & status) const863*0e209d39SAndroid Build Coastguard Worker virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* /* service */, UErrorCode& status) const override {
864*0e209d39SAndroid Build Coastguard Worker return NumberFormat::makeInstance(loc, (UNumberFormatStyle)kind, status);
865*0e209d39SAndroid Build Coastguard Worker }
866*0e209d39SAndroid Build Coastguard Worker };
867*0e209d39SAndroid Build Coastguard Worker
~ICUNumberFormatFactory()868*0e209d39SAndroid Build Coastguard Worker ICUNumberFormatFactory::~ICUNumberFormatFactory() {}
869*0e209d39SAndroid Build Coastguard Worker
870*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
871*0e209d39SAndroid Build Coastguard Worker
872*0e209d39SAndroid Build Coastguard Worker class NFFactory : public LocaleKeyFactory {
873*0e209d39SAndroid Build Coastguard Worker private:
874*0e209d39SAndroid Build Coastguard Worker NumberFormatFactory* _delegate;
875*0e209d39SAndroid Build Coastguard Worker Hashtable* _ids;
876*0e209d39SAndroid Build Coastguard Worker
877*0e209d39SAndroid Build Coastguard Worker public:
NFFactory(NumberFormatFactory * delegate)878*0e209d39SAndroid Build Coastguard Worker NFFactory(NumberFormatFactory* delegate)
879*0e209d39SAndroid Build Coastguard Worker : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE)
880*0e209d39SAndroid Build Coastguard Worker , _delegate(delegate)
881*0e209d39SAndroid Build Coastguard Worker , _ids(nullptr)
882*0e209d39SAndroid Build Coastguard Worker {
883*0e209d39SAndroid Build Coastguard Worker }
884*0e209d39SAndroid Build Coastguard Worker
885*0e209d39SAndroid Build Coastguard Worker virtual ~NFFactory();
886*0e209d39SAndroid Build Coastguard Worker
create(const ICUServiceKey & key,const ICUService * service,UErrorCode & status) const887*0e209d39SAndroid Build Coastguard Worker virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const override
888*0e209d39SAndroid Build Coastguard Worker {
889*0e209d39SAndroid Build Coastguard Worker if (handlesKey(key, status)) {
890*0e209d39SAndroid Build Coastguard Worker const LocaleKey* lkey = dynamic_cast<const LocaleKey*>(&key);
891*0e209d39SAndroid Build Coastguard Worker U_ASSERT(lkey != nullptr);
892*0e209d39SAndroid Build Coastguard Worker Locale loc;
893*0e209d39SAndroid Build Coastguard Worker lkey->canonicalLocale(loc);
894*0e209d39SAndroid Build Coastguard Worker int32_t kind = lkey->kind();
895*0e209d39SAndroid Build Coastguard Worker
896*0e209d39SAndroid Build Coastguard Worker UObject* result = _delegate->createFormat(loc, (UNumberFormatStyle)kind);
897*0e209d39SAndroid Build Coastguard Worker if (result == nullptr) {
898*0e209d39SAndroid Build Coastguard Worker result = service->getKey(const_cast<ICUServiceKey&>(key) /* cast away const */, nullptr, this, status);
899*0e209d39SAndroid Build Coastguard Worker }
900*0e209d39SAndroid Build Coastguard Worker return result;
901*0e209d39SAndroid Build Coastguard Worker }
902*0e209d39SAndroid Build Coastguard Worker return nullptr;
903*0e209d39SAndroid Build Coastguard Worker }
904*0e209d39SAndroid Build Coastguard Worker
905*0e209d39SAndroid Build Coastguard Worker protected:
906*0e209d39SAndroid Build Coastguard Worker /**
907*0e209d39SAndroid Build Coastguard Worker * Return the set of ids that this factory supports (visible or
908*0e209d39SAndroid Build Coastguard Worker * otherwise). This can be called often and might need to be
909*0e209d39SAndroid Build Coastguard Worker * cached if it is expensive to create.
910*0e209d39SAndroid Build Coastguard Worker */
getSupportedIDs(UErrorCode & status) const911*0e209d39SAndroid Build Coastguard Worker virtual const Hashtable* getSupportedIDs(UErrorCode& status) const override
912*0e209d39SAndroid Build Coastguard Worker {
913*0e209d39SAndroid Build Coastguard Worker if (U_SUCCESS(status)) {
914*0e209d39SAndroid Build Coastguard Worker if (!_ids) {
915*0e209d39SAndroid Build Coastguard Worker int32_t count = 0;
916*0e209d39SAndroid Build Coastguard Worker const UnicodeString * const idlist = _delegate->getSupportedIDs(count, status);
917*0e209d39SAndroid Build Coastguard Worker ((NFFactory*)this)->_ids = new Hashtable(status); /* cast away const */
918*0e209d39SAndroid Build Coastguard Worker if (_ids) {
919*0e209d39SAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
920*0e209d39SAndroid Build Coastguard Worker _ids->put(idlist[i], (void*)this, status);
921*0e209d39SAndroid Build Coastguard Worker }
922*0e209d39SAndroid Build Coastguard Worker }
923*0e209d39SAndroid Build Coastguard Worker }
924*0e209d39SAndroid Build Coastguard Worker return _ids;
925*0e209d39SAndroid Build Coastguard Worker }
926*0e209d39SAndroid Build Coastguard Worker return nullptr;
927*0e209d39SAndroid Build Coastguard Worker }
928*0e209d39SAndroid Build Coastguard Worker };
929*0e209d39SAndroid Build Coastguard Worker
~NFFactory()930*0e209d39SAndroid Build Coastguard Worker NFFactory::~NFFactory()
931*0e209d39SAndroid Build Coastguard Worker {
932*0e209d39SAndroid Build Coastguard Worker delete _delegate;
933*0e209d39SAndroid Build Coastguard Worker delete _ids;
934*0e209d39SAndroid Build Coastguard Worker }
935*0e209d39SAndroid Build Coastguard Worker
936*0e209d39SAndroid Build Coastguard Worker class ICUNumberFormatService : public ICULocaleService {
937*0e209d39SAndroid Build Coastguard Worker public:
ICUNumberFormatService()938*0e209d39SAndroid Build Coastguard Worker ICUNumberFormatService()
939*0e209d39SAndroid Build Coastguard Worker : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
940*0e209d39SAndroid Build Coastguard Worker {
941*0e209d39SAndroid Build Coastguard Worker UErrorCode status = U_ZERO_ERROR;
942*0e209d39SAndroid Build Coastguard Worker registerFactory(new ICUNumberFormatFactory(), status);
943*0e209d39SAndroid Build Coastguard Worker }
944*0e209d39SAndroid Build Coastguard Worker
945*0e209d39SAndroid Build Coastguard Worker virtual ~ICUNumberFormatService();
946*0e209d39SAndroid Build Coastguard Worker
cloneInstance(UObject * instance) const947*0e209d39SAndroid Build Coastguard Worker virtual UObject* cloneInstance(UObject* instance) const override {
948*0e209d39SAndroid Build Coastguard Worker return ((NumberFormat*)instance)->clone();
949*0e209d39SAndroid Build Coastguard Worker }
950*0e209d39SAndroid Build Coastguard Worker
handleDefault(const ICUServiceKey & key,UnicodeString *,UErrorCode & status) const951*0e209d39SAndroid Build Coastguard Worker virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* /* actualID */, UErrorCode& status) const override {
952*0e209d39SAndroid Build Coastguard Worker const LocaleKey* lkey = dynamic_cast<const LocaleKey*>(&key);
953*0e209d39SAndroid Build Coastguard Worker U_ASSERT(lkey != nullptr);
954*0e209d39SAndroid Build Coastguard Worker int32_t kind = lkey->kind();
955*0e209d39SAndroid Build Coastguard Worker Locale loc;
956*0e209d39SAndroid Build Coastguard Worker lkey->currentLocale(loc);
957*0e209d39SAndroid Build Coastguard Worker return NumberFormat::makeInstance(loc, (UNumberFormatStyle)kind, status);
958*0e209d39SAndroid Build Coastguard Worker }
959*0e209d39SAndroid Build Coastguard Worker
isDefault() const960*0e209d39SAndroid Build Coastguard Worker virtual UBool isDefault() const override {
961*0e209d39SAndroid Build Coastguard Worker return countFactories() == 1;
962*0e209d39SAndroid Build Coastguard Worker }
963*0e209d39SAndroid Build Coastguard Worker };
964*0e209d39SAndroid Build Coastguard Worker
~ICUNumberFormatService()965*0e209d39SAndroid Build Coastguard Worker ICUNumberFormatService::~ICUNumberFormatService() {}
966*0e209d39SAndroid Build Coastguard Worker
967*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
968*0e209d39SAndroid Build Coastguard Worker
initNumberFormatService()969*0e209d39SAndroid Build Coastguard Worker static void U_CALLCONV initNumberFormatService() {
970*0e209d39SAndroid Build Coastguard Worker U_ASSERT(gService == nullptr);
971*0e209d39SAndroid Build Coastguard Worker ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
972*0e209d39SAndroid Build Coastguard Worker gService = new ICUNumberFormatService();
973*0e209d39SAndroid Build Coastguard Worker }
974*0e209d39SAndroid Build Coastguard Worker
975*0e209d39SAndroid Build Coastguard Worker static ICULocaleService*
getNumberFormatService()976*0e209d39SAndroid Build Coastguard Worker getNumberFormatService()
977*0e209d39SAndroid Build Coastguard Worker {
978*0e209d39SAndroid Build Coastguard Worker umtx_initOnce(gServiceInitOnce, &initNumberFormatService);
979*0e209d39SAndroid Build Coastguard Worker return gService;
980*0e209d39SAndroid Build Coastguard Worker }
981*0e209d39SAndroid Build Coastguard Worker
haveService()982*0e209d39SAndroid Build Coastguard Worker static UBool haveService() {
983*0e209d39SAndroid Build Coastguard Worker return !gServiceInitOnce.isReset() && (getNumberFormatService() != nullptr);
984*0e209d39SAndroid Build Coastguard Worker }
985*0e209d39SAndroid Build Coastguard Worker
986*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
987*0e209d39SAndroid Build Coastguard Worker
988*0e209d39SAndroid Build Coastguard Worker URegistryKey U_EXPORT2
registerFactory(NumberFormatFactory * toAdopt,UErrorCode & status)989*0e209d39SAndroid Build Coastguard Worker NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status)
990*0e209d39SAndroid Build Coastguard Worker {
991*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
992*0e209d39SAndroid Build Coastguard Worker delete toAdopt;
993*0e209d39SAndroid Build Coastguard Worker return nullptr;
994*0e209d39SAndroid Build Coastguard Worker }
995*0e209d39SAndroid Build Coastguard Worker ICULocaleService *service = getNumberFormatService();
996*0e209d39SAndroid Build Coastguard Worker if (service) {
997*0e209d39SAndroid Build Coastguard Worker NFFactory *tempnnf = new NFFactory(toAdopt);
998*0e209d39SAndroid Build Coastguard Worker if (tempnnf != nullptr) {
999*0e209d39SAndroid Build Coastguard Worker return service->registerFactory(tempnnf, status);
1000*0e209d39SAndroid Build Coastguard Worker }
1001*0e209d39SAndroid Build Coastguard Worker }
1002*0e209d39SAndroid Build Coastguard Worker status = U_MEMORY_ALLOCATION_ERROR;
1003*0e209d39SAndroid Build Coastguard Worker return nullptr;
1004*0e209d39SAndroid Build Coastguard Worker }
1005*0e209d39SAndroid Build Coastguard Worker
1006*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1007*0e209d39SAndroid Build Coastguard Worker
1008*0e209d39SAndroid Build Coastguard Worker UBool U_EXPORT2
unregister(URegistryKey key,UErrorCode & status)1009*0e209d39SAndroid Build Coastguard Worker NumberFormat::unregister(URegistryKey key, UErrorCode& status)
1010*0e209d39SAndroid Build Coastguard Worker {
1011*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1012*0e209d39SAndroid Build Coastguard Worker return false;
1013*0e209d39SAndroid Build Coastguard Worker }
1014*0e209d39SAndroid Build Coastguard Worker if (haveService()) {
1015*0e209d39SAndroid Build Coastguard Worker return gService->unregister(key, status);
1016*0e209d39SAndroid Build Coastguard Worker } else {
1017*0e209d39SAndroid Build Coastguard Worker status = U_ILLEGAL_ARGUMENT_ERROR;
1018*0e209d39SAndroid Build Coastguard Worker return false;
1019*0e209d39SAndroid Build Coastguard Worker }
1020*0e209d39SAndroid Build Coastguard Worker }
1021*0e209d39SAndroid Build Coastguard Worker
1022*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1023*0e209d39SAndroid Build Coastguard Worker StringEnumeration* U_EXPORT2
getAvailableLocales()1024*0e209d39SAndroid Build Coastguard Worker NumberFormat::getAvailableLocales()
1025*0e209d39SAndroid Build Coastguard Worker {
1026*0e209d39SAndroid Build Coastguard Worker ICULocaleService *service = getNumberFormatService();
1027*0e209d39SAndroid Build Coastguard Worker if (service) {
1028*0e209d39SAndroid Build Coastguard Worker return service->getAvailableLocales();
1029*0e209d39SAndroid Build Coastguard Worker }
1030*0e209d39SAndroid Build Coastguard Worker return nullptr; // no way to return error condition
1031*0e209d39SAndroid Build Coastguard Worker }
1032*0e209d39SAndroid Build Coastguard Worker #endif /* UCONFIG_NO_SERVICE */
1033*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1034*0e209d39SAndroid Build Coastguard Worker
1035*0e209d39SAndroid Build Coastguard Worker enum { kKeyValueLenMax = 32 };
1036*0e209d39SAndroid Build Coastguard Worker
1037*0e209d39SAndroid Build Coastguard Worker NumberFormat*
internalCreateInstance(const Locale & loc,UNumberFormatStyle kind,UErrorCode & status)1038*0e209d39SAndroid Build Coastguard Worker NumberFormat::internalCreateInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) {
1039*0e209d39SAndroid Build Coastguard Worker if (kind == UNUM_CURRENCY) {
1040*0e209d39SAndroid Build Coastguard Worker char cfKeyValue[kKeyValueLenMax] = {0};
1041*0e209d39SAndroid Build Coastguard Worker UErrorCode kvStatus = U_ZERO_ERROR;
1042*0e209d39SAndroid Build Coastguard Worker int32_t kLen = loc.getKeywordValue("cf", cfKeyValue, kKeyValueLenMax, kvStatus);
1043*0e209d39SAndroid Build Coastguard Worker if (U_SUCCESS(kvStatus) && kLen > 0 && uprv_strcmp(cfKeyValue,"account")==0) {
1044*0e209d39SAndroid Build Coastguard Worker kind = UNUM_CURRENCY_ACCOUNTING;
1045*0e209d39SAndroid Build Coastguard Worker }
1046*0e209d39SAndroid Build Coastguard Worker }
1047*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_SERVICE
1048*0e209d39SAndroid Build Coastguard Worker if (haveService()) {
1049*0e209d39SAndroid Build Coastguard Worker return (NumberFormat*)gService->get(loc, kind, status);
1050*0e209d39SAndroid Build Coastguard Worker }
1051*0e209d39SAndroid Build Coastguard Worker #endif
1052*0e209d39SAndroid Build Coastguard Worker return makeInstance(loc, kind, status);
1053*0e209d39SAndroid Build Coastguard Worker }
1054*0e209d39SAndroid Build Coastguard Worker
1055*0e209d39SAndroid Build Coastguard Worker NumberFormat* U_EXPORT2
createInstance(const Locale & loc,UNumberFormatStyle kind,UErrorCode & status)1056*0e209d39SAndroid Build Coastguard Worker NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) {
1057*0e209d39SAndroid Build Coastguard Worker if (kind != UNUM_DECIMAL) {
1058*0e209d39SAndroid Build Coastguard Worker return internalCreateInstance(loc, kind, status);
1059*0e209d39SAndroid Build Coastguard Worker }
1060*0e209d39SAndroid Build Coastguard Worker const SharedNumberFormat *shared = createSharedInstance(loc, kind, status);
1061*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1062*0e209d39SAndroid Build Coastguard Worker return nullptr;
1063*0e209d39SAndroid Build Coastguard Worker }
1064*0e209d39SAndroid Build Coastguard Worker NumberFormat *result = (*shared)->clone();
1065*0e209d39SAndroid Build Coastguard Worker shared->removeRef();
1066*0e209d39SAndroid Build Coastguard Worker if (result == nullptr) {
1067*0e209d39SAndroid Build Coastguard Worker status = U_MEMORY_ALLOCATION_ERROR;
1068*0e209d39SAndroid Build Coastguard Worker }
1069*0e209d39SAndroid Build Coastguard Worker return result;
1070*0e209d39SAndroid Build Coastguard Worker }
1071*0e209d39SAndroid Build Coastguard Worker
1072*0e209d39SAndroid Build Coastguard Worker
1073*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1074*0e209d39SAndroid Build Coastguard Worker // Checks if the thousand/10 thousand grouping is used in the
1075*0e209d39SAndroid Build Coastguard Worker // NumberFormat instance.
1076*0e209d39SAndroid Build Coastguard Worker
1077*0e209d39SAndroid Build Coastguard Worker UBool
isGroupingUsed() const1078*0e209d39SAndroid Build Coastguard Worker NumberFormat::isGroupingUsed() const
1079*0e209d39SAndroid Build Coastguard Worker {
1080*0e209d39SAndroid Build Coastguard Worker return fGroupingUsed;
1081*0e209d39SAndroid Build Coastguard Worker }
1082*0e209d39SAndroid Build Coastguard Worker
1083*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1084*0e209d39SAndroid Build Coastguard Worker // Sets to use the thousand/10 thousand grouping in the
1085*0e209d39SAndroid Build Coastguard Worker // NumberFormat instance.
1086*0e209d39SAndroid Build Coastguard Worker
1087*0e209d39SAndroid Build Coastguard Worker void
setGroupingUsed(UBool newValue)1088*0e209d39SAndroid Build Coastguard Worker NumberFormat::setGroupingUsed(UBool newValue)
1089*0e209d39SAndroid Build Coastguard Worker {
1090*0e209d39SAndroid Build Coastguard Worker fGroupingUsed = newValue;
1091*0e209d39SAndroid Build Coastguard Worker }
1092*0e209d39SAndroid Build Coastguard Worker
1093*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1094*0e209d39SAndroid Build Coastguard Worker // Gets the maximum number of digits for the integral part for
1095*0e209d39SAndroid Build Coastguard Worker // this NumberFormat instance.
1096*0e209d39SAndroid Build Coastguard Worker
getMaximumIntegerDigits() const1097*0e209d39SAndroid Build Coastguard Worker int32_t NumberFormat::getMaximumIntegerDigits() const
1098*0e209d39SAndroid Build Coastguard Worker {
1099*0e209d39SAndroid Build Coastguard Worker return fMaxIntegerDigits;
1100*0e209d39SAndroid Build Coastguard Worker }
1101*0e209d39SAndroid Build Coastguard Worker
1102*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1103*0e209d39SAndroid Build Coastguard Worker // Sets the maximum number of digits for the integral part for
1104*0e209d39SAndroid Build Coastguard Worker // this NumberFormat instance.
1105*0e209d39SAndroid Build Coastguard Worker
1106*0e209d39SAndroid Build Coastguard Worker void
setMaximumIntegerDigits(int32_t newValue)1107*0e209d39SAndroid Build Coastguard Worker NumberFormat::setMaximumIntegerDigits(int32_t newValue)
1108*0e209d39SAndroid Build Coastguard Worker {
1109*0e209d39SAndroid Build Coastguard Worker fMaxIntegerDigits = uprv_max(0, uprv_min(newValue, gDefaultMaxIntegerDigits));
1110*0e209d39SAndroid Build Coastguard Worker if(fMinIntegerDigits > fMaxIntegerDigits)
1111*0e209d39SAndroid Build Coastguard Worker fMinIntegerDigits = fMaxIntegerDigits;
1112*0e209d39SAndroid Build Coastguard Worker }
1113*0e209d39SAndroid Build Coastguard Worker
1114*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1115*0e209d39SAndroid Build Coastguard Worker // Gets the minimum number of digits for the integral part for
1116*0e209d39SAndroid Build Coastguard Worker // this NumberFormat instance.
1117*0e209d39SAndroid Build Coastguard Worker
1118*0e209d39SAndroid Build Coastguard Worker int32_t
getMinimumIntegerDigits() const1119*0e209d39SAndroid Build Coastguard Worker NumberFormat::getMinimumIntegerDigits() const
1120*0e209d39SAndroid Build Coastguard Worker {
1121*0e209d39SAndroid Build Coastguard Worker return fMinIntegerDigits;
1122*0e209d39SAndroid Build Coastguard Worker }
1123*0e209d39SAndroid Build Coastguard Worker
1124*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1125*0e209d39SAndroid Build Coastguard Worker // Sets the minimum number of digits for the integral part for
1126*0e209d39SAndroid Build Coastguard Worker // this NumberFormat instance.
1127*0e209d39SAndroid Build Coastguard Worker
1128*0e209d39SAndroid Build Coastguard Worker void
setMinimumIntegerDigits(int32_t newValue)1129*0e209d39SAndroid Build Coastguard Worker NumberFormat::setMinimumIntegerDigits(int32_t newValue)
1130*0e209d39SAndroid Build Coastguard Worker {
1131*0e209d39SAndroid Build Coastguard Worker fMinIntegerDigits = uprv_max(0, uprv_min(newValue, gDefaultMinIntegerDigits));
1132*0e209d39SAndroid Build Coastguard Worker if(fMinIntegerDigits > fMaxIntegerDigits)
1133*0e209d39SAndroid Build Coastguard Worker fMaxIntegerDigits = fMinIntegerDigits;
1134*0e209d39SAndroid Build Coastguard Worker }
1135*0e209d39SAndroid Build Coastguard Worker
1136*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1137*0e209d39SAndroid Build Coastguard Worker // Gets the maximum number of digits for the fractional part for
1138*0e209d39SAndroid Build Coastguard Worker // this NumberFormat instance.
1139*0e209d39SAndroid Build Coastguard Worker
1140*0e209d39SAndroid Build Coastguard Worker int32_t
getMaximumFractionDigits() const1141*0e209d39SAndroid Build Coastguard Worker NumberFormat::getMaximumFractionDigits() const
1142*0e209d39SAndroid Build Coastguard Worker {
1143*0e209d39SAndroid Build Coastguard Worker return fMaxFractionDigits;
1144*0e209d39SAndroid Build Coastguard Worker }
1145*0e209d39SAndroid Build Coastguard Worker
1146*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1147*0e209d39SAndroid Build Coastguard Worker // Sets the maximum number of digits for the fractional part for
1148*0e209d39SAndroid Build Coastguard Worker // this NumberFormat instance.
1149*0e209d39SAndroid Build Coastguard Worker
1150*0e209d39SAndroid Build Coastguard Worker void
setMaximumFractionDigits(int32_t newValue)1151*0e209d39SAndroid Build Coastguard Worker NumberFormat::setMaximumFractionDigits(int32_t newValue)
1152*0e209d39SAndroid Build Coastguard Worker {
1153*0e209d39SAndroid Build Coastguard Worker fMaxFractionDigits = uprv_max(0, uprv_min(newValue, gDefaultMaxIntegerDigits));
1154*0e209d39SAndroid Build Coastguard Worker if(fMaxFractionDigits < fMinFractionDigits)
1155*0e209d39SAndroid Build Coastguard Worker fMinFractionDigits = fMaxFractionDigits;
1156*0e209d39SAndroid Build Coastguard Worker }
1157*0e209d39SAndroid Build Coastguard Worker
1158*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1159*0e209d39SAndroid Build Coastguard Worker // Gets the minimum number of digits for the fractional part for
1160*0e209d39SAndroid Build Coastguard Worker // this NumberFormat instance.
1161*0e209d39SAndroid Build Coastguard Worker
1162*0e209d39SAndroid Build Coastguard Worker int32_t
getMinimumFractionDigits() const1163*0e209d39SAndroid Build Coastguard Worker NumberFormat::getMinimumFractionDigits() const
1164*0e209d39SAndroid Build Coastguard Worker {
1165*0e209d39SAndroid Build Coastguard Worker return fMinFractionDigits;
1166*0e209d39SAndroid Build Coastguard Worker }
1167*0e209d39SAndroid Build Coastguard Worker
1168*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1169*0e209d39SAndroid Build Coastguard Worker // Sets the minimum number of digits for the fractional part for
1170*0e209d39SAndroid Build Coastguard Worker // this NumberFormat instance.
1171*0e209d39SAndroid Build Coastguard Worker
1172*0e209d39SAndroid Build Coastguard Worker void
setMinimumFractionDigits(int32_t newValue)1173*0e209d39SAndroid Build Coastguard Worker NumberFormat::setMinimumFractionDigits(int32_t newValue)
1174*0e209d39SAndroid Build Coastguard Worker {
1175*0e209d39SAndroid Build Coastguard Worker fMinFractionDigits = uprv_max(0, uprv_min(newValue, gDefaultMinIntegerDigits));
1176*0e209d39SAndroid Build Coastguard Worker if (fMaxFractionDigits < fMinFractionDigits)
1177*0e209d39SAndroid Build Coastguard Worker fMaxFractionDigits = fMinFractionDigits;
1178*0e209d39SAndroid Build Coastguard Worker }
1179*0e209d39SAndroid Build Coastguard Worker
1180*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1181*0e209d39SAndroid Build Coastguard Worker
setCurrency(const char16_t * theCurrency,UErrorCode & ec)1182*0e209d39SAndroid Build Coastguard Worker void NumberFormat::setCurrency(const char16_t* theCurrency, UErrorCode& ec) {
1183*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(ec)) {
1184*0e209d39SAndroid Build Coastguard Worker return;
1185*0e209d39SAndroid Build Coastguard Worker }
1186*0e209d39SAndroid Build Coastguard Worker if (theCurrency) {
1187*0e209d39SAndroid Build Coastguard Worker u_strncpy(fCurrency, theCurrency, 3);
1188*0e209d39SAndroid Build Coastguard Worker fCurrency[3] = 0;
1189*0e209d39SAndroid Build Coastguard Worker } else {
1190*0e209d39SAndroid Build Coastguard Worker fCurrency[0] = 0;
1191*0e209d39SAndroid Build Coastguard Worker }
1192*0e209d39SAndroid Build Coastguard Worker }
1193*0e209d39SAndroid Build Coastguard Worker
getCurrency() const1194*0e209d39SAndroid Build Coastguard Worker const char16_t* NumberFormat::getCurrency() const {
1195*0e209d39SAndroid Build Coastguard Worker return fCurrency;
1196*0e209d39SAndroid Build Coastguard Worker }
1197*0e209d39SAndroid Build Coastguard Worker
getEffectiveCurrency(char16_t * result,UErrorCode & ec) const1198*0e209d39SAndroid Build Coastguard Worker void NumberFormat::getEffectiveCurrency(char16_t* result, UErrorCode& ec) const {
1199*0e209d39SAndroid Build Coastguard Worker const char16_t* c = getCurrency();
1200*0e209d39SAndroid Build Coastguard Worker if (*c != 0) {
1201*0e209d39SAndroid Build Coastguard Worker u_strncpy(result, c, 3);
1202*0e209d39SAndroid Build Coastguard Worker result[3] = 0;
1203*0e209d39SAndroid Build Coastguard Worker } else {
1204*0e209d39SAndroid Build Coastguard Worker const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec);
1205*0e209d39SAndroid Build Coastguard Worker if (loc == nullptr) {
1206*0e209d39SAndroid Build Coastguard Worker loc = uloc_getDefault();
1207*0e209d39SAndroid Build Coastguard Worker }
1208*0e209d39SAndroid Build Coastguard Worker ucurr_forLocale(loc, result, 4, &ec);
1209*0e209d39SAndroid Build Coastguard Worker }
1210*0e209d39SAndroid Build Coastguard Worker }
1211*0e209d39SAndroid Build Coastguard Worker
1212*0e209d39SAndroid Build Coastguard Worker //----------------------------------------------------------------------
1213*0e209d39SAndroid Build Coastguard Worker
1214*0e209d39SAndroid Build Coastguard Worker
setContext(UDisplayContext value,UErrorCode & status)1215*0e209d39SAndroid Build Coastguard Worker void NumberFormat::setContext(UDisplayContext value, UErrorCode& status)
1216*0e209d39SAndroid Build Coastguard Worker {
1217*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status))
1218*0e209d39SAndroid Build Coastguard Worker return;
1219*0e209d39SAndroid Build Coastguard Worker if ( (UDisplayContextType)((uint32_t)value >> 8) == UDISPCTX_TYPE_CAPITALIZATION ) {
1220*0e209d39SAndroid Build Coastguard Worker fCapitalizationContext = value;
1221*0e209d39SAndroid Build Coastguard Worker } else {
1222*0e209d39SAndroid Build Coastguard Worker status = U_ILLEGAL_ARGUMENT_ERROR;
1223*0e209d39SAndroid Build Coastguard Worker }
1224*0e209d39SAndroid Build Coastguard Worker }
1225*0e209d39SAndroid Build Coastguard Worker
1226*0e209d39SAndroid Build Coastguard Worker
getContext(UDisplayContextType type,UErrorCode & status) const1227*0e209d39SAndroid Build Coastguard Worker UDisplayContext NumberFormat::getContext(UDisplayContextType type, UErrorCode& status) const
1228*0e209d39SAndroid Build Coastguard Worker {
1229*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status))
1230*0e209d39SAndroid Build Coastguard Worker return (UDisplayContext)0;
1231*0e209d39SAndroid Build Coastguard Worker if (type != UDISPCTX_TYPE_CAPITALIZATION) {
1232*0e209d39SAndroid Build Coastguard Worker status = U_ILLEGAL_ARGUMENT_ERROR;
1233*0e209d39SAndroid Build Coastguard Worker return (UDisplayContext)0;
1234*0e209d39SAndroid Build Coastguard Worker }
1235*0e209d39SAndroid Build Coastguard Worker return fCapitalizationContext;
1236*0e209d39SAndroid Build Coastguard Worker }
1237*0e209d39SAndroid Build Coastguard Worker
1238*0e209d39SAndroid Build Coastguard Worker
1239*0e209d39SAndroid Build Coastguard Worker // -------------------------------------
1240*0e209d39SAndroid Build Coastguard Worker // Creates the NumberFormat instance of the specified style (number, currency,
1241*0e209d39SAndroid Build Coastguard Worker // or percent) for the desired locale.
1242*0e209d39SAndroid Build Coastguard Worker
nscacheInit()1243*0e209d39SAndroid Build Coastguard Worker static void U_CALLCONV nscacheInit() {
1244*0e209d39SAndroid Build Coastguard Worker U_ASSERT(NumberingSystem_cache == nullptr);
1245*0e209d39SAndroid Build Coastguard Worker ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
1246*0e209d39SAndroid Build Coastguard Worker UErrorCode status = U_ZERO_ERROR;
1247*0e209d39SAndroid Build Coastguard Worker NumberingSystem_cache = uhash_open(uhash_hashLong,
1248*0e209d39SAndroid Build Coastguard Worker uhash_compareLong,
1249*0e209d39SAndroid Build Coastguard Worker nullptr,
1250*0e209d39SAndroid Build Coastguard Worker &status);
1251*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1252*0e209d39SAndroid Build Coastguard Worker // Number Format code will run with no cache if creation fails.
1253*0e209d39SAndroid Build Coastguard Worker NumberingSystem_cache = nullptr;
1254*0e209d39SAndroid Build Coastguard Worker return;
1255*0e209d39SAndroid Build Coastguard Worker }
1256*0e209d39SAndroid Build Coastguard Worker uhash_setValueDeleter(NumberingSystem_cache, deleteNumberingSystem);
1257*0e209d39SAndroid Build Coastguard Worker }
1258*0e209d39SAndroid Build Coastguard Worker
1259*0e209d39SAndroid Build Coastguard Worker template<> U_I18N_API
createObject(const void *,UErrorCode & status) const1260*0e209d39SAndroid Build Coastguard Worker const SharedNumberFormat *LocaleCacheKey<SharedNumberFormat>::createObject(
1261*0e209d39SAndroid Build Coastguard Worker const void * /*unused*/, UErrorCode &status) const {
1262*0e209d39SAndroid Build Coastguard Worker const char *localeId = fLoc.getName();
1263*0e209d39SAndroid Build Coastguard Worker NumberFormat *nf = NumberFormat::internalCreateInstance(
1264*0e209d39SAndroid Build Coastguard Worker localeId, UNUM_DECIMAL, status);
1265*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1266*0e209d39SAndroid Build Coastguard Worker return nullptr;
1267*0e209d39SAndroid Build Coastguard Worker }
1268*0e209d39SAndroid Build Coastguard Worker SharedNumberFormat *result = new SharedNumberFormat(nf);
1269*0e209d39SAndroid Build Coastguard Worker if (result == nullptr) {
1270*0e209d39SAndroid Build Coastguard Worker status = U_MEMORY_ALLOCATION_ERROR;
1271*0e209d39SAndroid Build Coastguard Worker delete nf;
1272*0e209d39SAndroid Build Coastguard Worker return nullptr;
1273*0e209d39SAndroid Build Coastguard Worker }
1274*0e209d39SAndroid Build Coastguard Worker result->addRef();
1275*0e209d39SAndroid Build Coastguard Worker return result;
1276*0e209d39SAndroid Build Coastguard Worker }
1277*0e209d39SAndroid Build Coastguard Worker
1278*0e209d39SAndroid Build Coastguard Worker const SharedNumberFormat* U_EXPORT2
createSharedInstance(const Locale & loc,UNumberFormatStyle kind,UErrorCode & status)1279*0e209d39SAndroid Build Coastguard Worker NumberFormat::createSharedInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) {
1280*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1281*0e209d39SAndroid Build Coastguard Worker return nullptr;
1282*0e209d39SAndroid Build Coastguard Worker }
1283*0e209d39SAndroid Build Coastguard Worker if (kind != UNUM_DECIMAL) {
1284*0e209d39SAndroid Build Coastguard Worker status = U_UNSUPPORTED_ERROR;
1285*0e209d39SAndroid Build Coastguard Worker return nullptr;
1286*0e209d39SAndroid Build Coastguard Worker }
1287*0e209d39SAndroid Build Coastguard Worker const SharedNumberFormat *result = nullptr;
1288*0e209d39SAndroid Build Coastguard Worker UnifiedCache::getByLocale(loc, result, status);
1289*0e209d39SAndroid Build Coastguard Worker return result;
1290*0e209d39SAndroid Build Coastguard Worker }
1291*0e209d39SAndroid Build Coastguard Worker
1292*0e209d39SAndroid Build Coastguard Worker UBool
isStyleSupported(UNumberFormatStyle style)1293*0e209d39SAndroid Build Coastguard Worker NumberFormat::isStyleSupported(UNumberFormatStyle style) {
1294*0e209d39SAndroid Build Coastguard Worker return gLastResortNumberPatterns[style] != nullptr;
1295*0e209d39SAndroid Build Coastguard Worker }
1296*0e209d39SAndroid Build Coastguard Worker
1297*0e209d39SAndroid Build Coastguard Worker NumberFormat*
makeInstance(const Locale & desiredLocale,UNumberFormatStyle style,UErrorCode & status)1298*0e209d39SAndroid Build Coastguard Worker NumberFormat::makeInstance(const Locale& desiredLocale,
1299*0e209d39SAndroid Build Coastguard Worker UNumberFormatStyle style,
1300*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) {
1301*0e209d39SAndroid Build Coastguard Worker return makeInstance(desiredLocale, style, false, status);
1302*0e209d39SAndroid Build Coastguard Worker }
1303*0e209d39SAndroid Build Coastguard Worker
1304*0e209d39SAndroid Build Coastguard Worker NumberFormat*
makeInstance(const Locale & desiredLocale,UNumberFormatStyle style,UBool mustBeDecimalFormat,UErrorCode & status)1305*0e209d39SAndroid Build Coastguard Worker NumberFormat::makeInstance(const Locale& desiredLocale,
1306*0e209d39SAndroid Build Coastguard Worker UNumberFormatStyle style,
1307*0e209d39SAndroid Build Coastguard Worker UBool mustBeDecimalFormat,
1308*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) {
1309*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) return nullptr;
1310*0e209d39SAndroid Build Coastguard Worker
1311*0e209d39SAndroid Build Coastguard Worker if (style < 0 || style >= UNUM_FORMAT_STYLE_COUNT) {
1312*0e209d39SAndroid Build Coastguard Worker status = U_ILLEGAL_ARGUMENT_ERROR;
1313*0e209d39SAndroid Build Coastguard Worker return nullptr;
1314*0e209d39SAndroid Build Coastguard Worker }
1315*0e209d39SAndroid Build Coastguard Worker
1316*0e209d39SAndroid Build Coastguard Worker // For the purposes of general number formatting, UNUM_NUMBERING_SYSTEM should behave the same
1317*0e209d39SAndroid Build Coastguard Worker // was as UNUM_DECIMAL. In both cases, you get either a DecimalFormat or a RuleBasedNumberFormat
1318*0e209d39SAndroid Build Coastguard Worker // depending on the locale's numbering system (either the default one for the locale or a specific
1319*0e209d39SAndroid Build Coastguard Worker // one specified by using the "@numbers=" or "-u-nu-" parameter in the locale ID.
1320*0e209d39SAndroid Build Coastguard Worker if (style == UNUM_NUMBERING_SYSTEM) {
1321*0e209d39SAndroid Build Coastguard Worker style = UNUM_DECIMAL;
1322*0e209d39SAndroid Build Coastguard Worker }
1323*0e209d39SAndroid Build Coastguard Worker
1324*0e209d39SAndroid Build Coastguard Worker // Some styles are not supported. This is a result of merging
1325*0e209d39SAndroid Build Coastguard Worker // the @draft ICU 4.2 NumberFormat::EStyles into the long-existing UNumberFormatStyle.
1326*0e209d39SAndroid Build Coastguard Worker // Ticket #8503 is for reviewing/fixing/merging the two relevant implementations:
1327*0e209d39SAndroid Build Coastguard Worker // this one and unum_open().
1328*0e209d39SAndroid Build Coastguard Worker // The UNUM_PATTERN_ styles are not supported here
1329*0e209d39SAndroid Build Coastguard Worker // because this method does not take a pattern string.
1330*0e209d39SAndroid Build Coastguard Worker if (!isStyleSupported(style)) {
1331*0e209d39SAndroid Build Coastguard Worker status = U_UNSUPPORTED_ERROR;
1332*0e209d39SAndroid Build Coastguard Worker return nullptr;
1333*0e209d39SAndroid Build Coastguard Worker }
1334*0e209d39SAndroid Build Coastguard Worker
1335*0e209d39SAndroid Build Coastguard Worker #if U_PLATFORM_USES_ONLY_WIN32_API
1336*0e209d39SAndroid Build Coastguard Worker if (!mustBeDecimalFormat) {
1337*0e209d39SAndroid Build Coastguard Worker char buffer[8];
1338*0e209d39SAndroid Build Coastguard Worker int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status);
1339*0e209d39SAndroid Build Coastguard Worker
1340*0e209d39SAndroid Build Coastguard Worker // if the locale has "@compat=host", create a host-specific NumberFormat
1341*0e209d39SAndroid Build Coastguard Worker if (U_SUCCESS(status) && count > 0 && uprv_strcmp(buffer, "host") == 0) {
1342*0e209d39SAndroid Build Coastguard Worker UBool curr = true;
1343*0e209d39SAndroid Build Coastguard Worker
1344*0e209d39SAndroid Build Coastguard Worker switch (style) {
1345*0e209d39SAndroid Build Coastguard Worker case UNUM_DECIMAL:
1346*0e209d39SAndroid Build Coastguard Worker curr = false;
1347*0e209d39SAndroid Build Coastguard Worker // fall-through
1348*0e209d39SAndroid Build Coastguard Worker U_FALLTHROUGH;
1349*0e209d39SAndroid Build Coastguard Worker
1350*0e209d39SAndroid Build Coastguard Worker case UNUM_CURRENCY:
1351*0e209d39SAndroid Build Coastguard Worker case UNUM_CURRENCY_ISO: // do not support plural formatting here
1352*0e209d39SAndroid Build Coastguard Worker case UNUM_CURRENCY_PLURAL:
1353*0e209d39SAndroid Build Coastguard Worker case UNUM_CURRENCY_ACCOUNTING:
1354*0e209d39SAndroid Build Coastguard Worker case UNUM_CASH_CURRENCY:
1355*0e209d39SAndroid Build Coastguard Worker case UNUM_CURRENCY_STANDARD:
1356*0e209d39SAndroid Build Coastguard Worker {
1357*0e209d39SAndroid Build Coastguard Worker LocalPointer<Win32NumberFormat> f(new Win32NumberFormat(desiredLocale, curr, status), status);
1358*0e209d39SAndroid Build Coastguard Worker if (U_SUCCESS(status)) {
1359*0e209d39SAndroid Build Coastguard Worker return f.orphan();
1360*0e209d39SAndroid Build Coastguard Worker }
1361*0e209d39SAndroid Build Coastguard Worker }
1362*0e209d39SAndroid Build Coastguard Worker break;
1363*0e209d39SAndroid Build Coastguard Worker default:
1364*0e209d39SAndroid Build Coastguard Worker break;
1365*0e209d39SAndroid Build Coastguard Worker }
1366*0e209d39SAndroid Build Coastguard Worker }
1367*0e209d39SAndroid Build Coastguard Worker }
1368*0e209d39SAndroid Build Coastguard Worker #endif
1369*0e209d39SAndroid Build Coastguard Worker // Use numbering system cache hashtable
1370*0e209d39SAndroid Build Coastguard Worker umtx_initOnce(gNSCacheInitOnce, &nscacheInit);
1371*0e209d39SAndroid Build Coastguard Worker
1372*0e209d39SAndroid Build Coastguard Worker // Get cached numbering system
1373*0e209d39SAndroid Build Coastguard Worker LocalPointer<NumberingSystem> ownedNs;
1374*0e209d39SAndroid Build Coastguard Worker NumberingSystem *ns = nullptr;
1375*0e209d39SAndroid Build Coastguard Worker if (NumberingSystem_cache != nullptr) {
1376*0e209d39SAndroid Build Coastguard Worker // TODO: Bad hash key usage, see ticket #8504.
1377*0e209d39SAndroid Build Coastguard Worker int32_t hashKey = desiredLocale.hashCode();
1378*0e209d39SAndroid Build Coastguard Worker
1379*0e209d39SAndroid Build Coastguard Worker static UMutex nscacheMutex;
1380*0e209d39SAndroid Build Coastguard Worker Mutex lock(&nscacheMutex);
1381*0e209d39SAndroid Build Coastguard Worker ns = (NumberingSystem *)uhash_iget(NumberingSystem_cache, hashKey);
1382*0e209d39SAndroid Build Coastguard Worker if (ns == nullptr) {
1383*0e209d39SAndroid Build Coastguard Worker ns = NumberingSystem::createInstance(desiredLocale,status);
1384*0e209d39SAndroid Build Coastguard Worker uhash_iput(NumberingSystem_cache, hashKey, (void*)ns, &status);
1385*0e209d39SAndroid Build Coastguard Worker }
1386*0e209d39SAndroid Build Coastguard Worker } else {
1387*0e209d39SAndroid Build Coastguard Worker ownedNs.adoptInstead(NumberingSystem::createInstance(desiredLocale,status));
1388*0e209d39SAndroid Build Coastguard Worker ns = ownedNs.getAlias();
1389*0e209d39SAndroid Build Coastguard Worker }
1390*0e209d39SAndroid Build Coastguard Worker
1391*0e209d39SAndroid Build Coastguard Worker // check results of getting a numbering system
1392*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1393*0e209d39SAndroid Build Coastguard Worker return nullptr;
1394*0e209d39SAndroid Build Coastguard Worker }
1395*0e209d39SAndroid Build Coastguard Worker
1396*0e209d39SAndroid Build Coastguard Worker if (mustBeDecimalFormat && ns->isAlgorithmic()) {
1397*0e209d39SAndroid Build Coastguard Worker status = U_UNSUPPORTED_ERROR;
1398*0e209d39SAndroid Build Coastguard Worker return nullptr;
1399*0e209d39SAndroid Build Coastguard Worker }
1400*0e209d39SAndroid Build Coastguard Worker
1401*0e209d39SAndroid Build Coastguard Worker LocalPointer<DecimalFormatSymbols> symbolsToAdopt;
1402*0e209d39SAndroid Build Coastguard Worker UnicodeString pattern;
1403*0e209d39SAndroid Build Coastguard Worker LocalUResourceBundlePointer ownedResource(ures_open(nullptr, desiredLocale.getName(), &status));
1404*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1405*0e209d39SAndroid Build Coastguard Worker return nullptr;
1406*0e209d39SAndroid Build Coastguard Worker }
1407*0e209d39SAndroid Build Coastguard Worker else {
1408*0e209d39SAndroid Build Coastguard Worker // Loads the decimal symbols of the desired locale.
1409*0e209d39SAndroid Build Coastguard Worker symbolsToAdopt.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(desiredLocale, status), status);
1410*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1411*0e209d39SAndroid Build Coastguard Worker return nullptr;
1412*0e209d39SAndroid Build Coastguard Worker }
1413*0e209d39SAndroid Build Coastguard Worker
1414*0e209d39SAndroid Build Coastguard Worker // Load the pattern from data using the common library function
1415*0e209d39SAndroid Build Coastguard Worker const char16_t* patternPtr = number::impl::utils::getPatternForStyle(
1416*0e209d39SAndroid Build Coastguard Worker desiredLocale,
1417*0e209d39SAndroid Build Coastguard Worker ns->getName(),
1418*0e209d39SAndroid Build Coastguard Worker gFormatCldrStyles[style],
1419*0e209d39SAndroid Build Coastguard Worker status);
1420*0e209d39SAndroid Build Coastguard Worker pattern = UnicodeString(true, patternPtr, -1);
1421*0e209d39SAndroid Build Coastguard Worker }
1422*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1423*0e209d39SAndroid Build Coastguard Worker return nullptr;
1424*0e209d39SAndroid Build Coastguard Worker }
1425*0e209d39SAndroid Build Coastguard Worker if(style==UNUM_CURRENCY || style == UNUM_CURRENCY_ISO || style == UNUM_CURRENCY_ACCOUNTING
1426*0e209d39SAndroid Build Coastguard Worker || style == UNUM_CASH_CURRENCY || style == UNUM_CURRENCY_STANDARD){
1427*0e209d39SAndroid Build Coastguard Worker const char16_t* currPattern = symbolsToAdopt->getCurrencyPattern();
1428*0e209d39SAndroid Build Coastguard Worker if(currPattern!=nullptr){
1429*0e209d39SAndroid Build Coastguard Worker pattern.setTo(currPattern, u_strlen(currPattern));
1430*0e209d39SAndroid Build Coastguard Worker }
1431*0e209d39SAndroid Build Coastguard Worker }
1432*0e209d39SAndroid Build Coastguard Worker
1433*0e209d39SAndroid Build Coastguard Worker LocalPointer<NumberFormat> f;
1434*0e209d39SAndroid Build Coastguard Worker if (ns->isAlgorithmic()) {
1435*0e209d39SAndroid Build Coastguard Worker UnicodeString nsDesc;
1436*0e209d39SAndroid Build Coastguard Worker UnicodeString nsRuleSetGroup;
1437*0e209d39SAndroid Build Coastguard Worker UnicodeString nsRuleSetName;
1438*0e209d39SAndroid Build Coastguard Worker Locale nsLoc;
1439*0e209d39SAndroid Build Coastguard Worker URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM;
1440*0e209d39SAndroid Build Coastguard Worker
1441*0e209d39SAndroid Build Coastguard Worker nsDesc.setTo(ns->getDescription());
1442*0e209d39SAndroid Build Coastguard Worker int32_t firstSlash = nsDesc.indexOf(gSlash);
1443*0e209d39SAndroid Build Coastguard Worker int32_t lastSlash = nsDesc.lastIndexOf(gSlash);
1444*0e209d39SAndroid Build Coastguard Worker if ( lastSlash > firstSlash ) {
1445*0e209d39SAndroid Build Coastguard Worker CharString nsLocID;
1446*0e209d39SAndroid Build Coastguard Worker
1447*0e209d39SAndroid Build Coastguard Worker nsLocID.appendInvariantChars(nsDesc.tempSubString(0, firstSlash), status);
1448*0e209d39SAndroid Build Coastguard Worker nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1);
1449*0e209d39SAndroid Build Coastguard Worker nsRuleSetName.setTo(nsDesc,lastSlash+1);
1450*0e209d39SAndroid Build Coastguard Worker
1451*0e209d39SAndroid Build Coastguard Worker nsLoc = Locale::createFromName(nsLocID.data());
1452*0e209d39SAndroid Build Coastguard Worker
1453*0e209d39SAndroid Build Coastguard Worker UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules");
1454*0e209d39SAndroid Build Coastguard Worker if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) {
1455*0e209d39SAndroid Build Coastguard Worker desiredRulesType = URBNF_SPELLOUT;
1456*0e209d39SAndroid Build Coastguard Worker }
1457*0e209d39SAndroid Build Coastguard Worker } else {
1458*0e209d39SAndroid Build Coastguard Worker nsLoc = desiredLocale;
1459*0e209d39SAndroid Build Coastguard Worker nsRuleSetName.setTo(nsDesc);
1460*0e209d39SAndroid Build Coastguard Worker }
1461*0e209d39SAndroid Build Coastguard Worker
1462*0e209d39SAndroid Build Coastguard Worker RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status);
1463*0e209d39SAndroid Build Coastguard Worker if (r == nullptr) {
1464*0e209d39SAndroid Build Coastguard Worker status = U_MEMORY_ALLOCATION_ERROR;
1465*0e209d39SAndroid Build Coastguard Worker return nullptr;
1466*0e209d39SAndroid Build Coastguard Worker }
1467*0e209d39SAndroid Build Coastguard Worker r->setDefaultRuleSet(nsRuleSetName,status);
1468*0e209d39SAndroid Build Coastguard Worker f.adoptInstead(r);
1469*0e209d39SAndroid Build Coastguard Worker } else {
1470*0e209d39SAndroid Build Coastguard Worker // replace single currency sign in the pattern with double currency sign
1471*0e209d39SAndroid Build Coastguard Worker // if the style is UNUM_CURRENCY_ISO
1472*0e209d39SAndroid Build Coastguard Worker if (style == UNUM_CURRENCY_ISO) {
1473*0e209d39SAndroid Build Coastguard Worker pattern.findAndReplace(UnicodeString(true, gSingleCurrencySign, 1),
1474*0e209d39SAndroid Build Coastguard Worker UnicodeString(true, gDoubleCurrencySign, 2));
1475*0e209d39SAndroid Build Coastguard Worker }
1476*0e209d39SAndroid Build Coastguard Worker
1477*0e209d39SAndroid Build Coastguard Worker // "new DecimalFormat()" does not adopt the symbols argument if its memory allocation fails.
1478*0e209d39SAndroid Build Coastguard Worker // So we can't use adoptInsteadAndCheckErrorCode as we need to know if the 'new' failed.
1479*0e209d39SAndroid Build Coastguard Worker DecimalFormatSymbols *syms = symbolsToAdopt.getAlias();
1480*0e209d39SAndroid Build Coastguard Worker LocalPointer<DecimalFormat> df(new DecimalFormat(pattern, syms, style, status));
1481*0e209d39SAndroid Build Coastguard Worker
1482*0e209d39SAndroid Build Coastguard Worker if (df.isValid()) {
1483*0e209d39SAndroid Build Coastguard Worker // if the DecimalFormat object was successfully new'ed, then it will own symbolsToAdopt, even if the status is a failure.
1484*0e209d39SAndroid Build Coastguard Worker symbolsToAdopt.orphan();
1485*0e209d39SAndroid Build Coastguard Worker }
1486*0e209d39SAndroid Build Coastguard Worker else {
1487*0e209d39SAndroid Build Coastguard Worker status = U_MEMORY_ALLOCATION_ERROR;
1488*0e209d39SAndroid Build Coastguard Worker }
1489*0e209d39SAndroid Build Coastguard Worker
1490*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1491*0e209d39SAndroid Build Coastguard Worker return nullptr;
1492*0e209d39SAndroid Build Coastguard Worker }
1493*0e209d39SAndroid Build Coastguard Worker
1494*0e209d39SAndroid Build Coastguard Worker // if it is cash currency style, setCurrencyUsage with usage
1495*0e209d39SAndroid Build Coastguard Worker if (style == UNUM_CASH_CURRENCY){
1496*0e209d39SAndroid Build Coastguard Worker df->setCurrencyUsage(UCURR_USAGE_CASH, &status);
1497*0e209d39SAndroid Build Coastguard Worker }
1498*0e209d39SAndroid Build Coastguard Worker
1499*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1500*0e209d39SAndroid Build Coastguard Worker return nullptr;
1501*0e209d39SAndroid Build Coastguard Worker }
1502*0e209d39SAndroid Build Coastguard Worker
1503*0e209d39SAndroid Build Coastguard Worker f.adoptInstead(df.orphan());
1504*0e209d39SAndroid Build Coastguard Worker }
1505*0e209d39SAndroid Build Coastguard Worker
1506*0e209d39SAndroid Build Coastguard Worker f->setLocaleIDs(ures_getLocaleByType(ownedResource.getAlias(), ULOC_VALID_LOCALE, &status),
1507*0e209d39SAndroid Build Coastguard Worker ures_getLocaleByType(ownedResource.getAlias(), ULOC_ACTUAL_LOCALE, &status));
1508*0e209d39SAndroid Build Coastguard Worker if (U_FAILURE(status)) {
1509*0e209d39SAndroid Build Coastguard Worker return nullptr;
1510*0e209d39SAndroid Build Coastguard Worker }
1511*0e209d39SAndroid Build Coastguard Worker return f.orphan();
1512*0e209d39SAndroid Build Coastguard Worker }
1513*0e209d39SAndroid Build Coastguard Worker
1514*0e209d39SAndroid Build Coastguard Worker /**
1515*0e209d39SAndroid Build Coastguard Worker * Get the rounding mode.
1516*0e209d39SAndroid Build Coastguard Worker * @return A rounding mode
1517*0e209d39SAndroid Build Coastguard Worker */
getRoundingMode() const1518*0e209d39SAndroid Build Coastguard Worker NumberFormat::ERoundingMode NumberFormat::getRoundingMode() const {
1519*0e209d39SAndroid Build Coastguard Worker // Default value. ICU4J throws an exception and we can't change this API.
1520*0e209d39SAndroid Build Coastguard Worker return NumberFormat::ERoundingMode::kRoundUnnecessary;
1521*0e209d39SAndroid Build Coastguard Worker }
1522*0e209d39SAndroid Build Coastguard Worker
1523*0e209d39SAndroid Build Coastguard Worker /**
1524*0e209d39SAndroid Build Coastguard Worker * Set the rounding mode. This has no effect unless the rounding
1525*0e209d39SAndroid Build Coastguard Worker * increment is greater than zero.
1526*0e209d39SAndroid Build Coastguard Worker * @param roundingMode A rounding mode
1527*0e209d39SAndroid Build Coastguard Worker */
setRoundingMode(NumberFormat::ERoundingMode)1528*0e209d39SAndroid Build Coastguard Worker void NumberFormat::setRoundingMode(NumberFormat::ERoundingMode /*roundingMode*/) {
1529*0e209d39SAndroid Build Coastguard Worker // No-op ICU4J throws an exception, and we can't change this API.
1530*0e209d39SAndroid Build Coastguard Worker }
1531*0e209d39SAndroid Build Coastguard Worker
1532*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_END
1533*0e209d39SAndroid Build Coastguard Worker
1534*0e209d39SAndroid Build Coastguard Worker #endif /* #if !UCONFIG_NO_FORMATTING */
1535*0e209d39SAndroid Build Coastguard Worker
1536*0e209d39SAndroid Build Coastguard Worker //eof
1537