]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
2ca993e8 | 3 | * Copyright (C) 1996-2015, International Business Machines |
b75a7d8f A |
4 | * Corporation and others. All Rights Reserved. |
5 | ******************************************************************************* | |
6 | * Modification History: | |
7 | * | |
8 | * Date Name Description | |
9 | * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes | |
10 | ******************************************************************************* | |
11 | */ | |
12 | ||
13 | #include "unicode/utypes.h" | |
14 | ||
15 | #if !UCONFIG_NO_FORMATTING | |
16 | ||
17 | #include "unicode/unum.h" | |
18 | ||
19 | #include "unicode/uloc.h" | |
20 | #include "unicode/numfmt.h" | |
21 | #include "unicode/decimfmt.h" | |
22 | #include "unicode/rbnf.h" | |
b331163b | 23 | #include "unicode/compactdecimalformat.h" |
b75a7d8f A |
24 | #include "unicode/ustring.h" |
25 | #include "unicode/fmtable.h" | |
26 | #include "unicode/dcfmtsym.h" | |
374ca955 | 27 | #include "unicode/curramt.h" |
4388f060 | 28 | #include "unicode/localpointer.h" |
57a6839d | 29 | #include "unicode/udisplaycontext.h" |
374ca955 | 30 | #include "uassert.h" |
b75a7d8f | 31 | #include "cpputils.h" |
729e4ab9 | 32 | #include "cstring.h" |
b75a7d8f | 33 | |
b75a7d8f | 34 | |
374ca955 | 35 | U_NAMESPACE_USE |
b75a7d8f A |
36 | |
37 | ||
38 | U_CAPI UNumberFormat* U_EXPORT2 | |
39 | unum_open( UNumberFormatStyle style, | |
40 | const UChar* pattern, | |
41 | int32_t patternLength, | |
42 | const char* locale, | |
43 | UParseError* parseErr, | |
4388f060 A |
44 | UErrorCode* status) { |
45 | if(U_FAILURE(*status)) { | |
46 | return NULL; | |
374ca955 A |
47 | } |
48 | ||
4388f060 | 49 | NumberFormat *retVal = NULL; |
374ca955 A |
50 | |
51 | switch(style) { | |
52 | case UNUM_DECIMAL: | |
374ca955 | 53 | case UNUM_CURRENCY: |
374ca955 | 54 | case UNUM_PERCENT: |
374ca955 | 55 | case UNUM_SCIENTIFIC: |
57a6839d A |
56 | case UNUM_CURRENCY_ISO: |
57 | case UNUM_CURRENCY_PLURAL: | |
58 | case UNUM_CURRENCY_ACCOUNTING: | |
b331163b | 59 | case UNUM_CASH_CURRENCY: |
2ca993e8 | 60 | case UNUM_CURRENCY_STANDARD: |
4388f060 | 61 | retVal = NumberFormat::createInstance(Locale(locale), style, *status); |
b75a7d8f A |
62 | break; |
63 | ||
374ca955 A |
64 | case UNUM_PATTERN_DECIMAL: { |
65 | UParseError tErr; | |
66 | /* UnicodeString can handle the case when patternLength = -1. */ | |
67 | const UnicodeString pat(pattern, patternLength); | |
374ca955 A |
68 | |
69 | if(parseErr==NULL){ | |
70 | parseErr = &tErr; | |
71 | } | |
72 | ||
4388f060 A |
73 | DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status); |
74 | if(syms == NULL) { | |
374ca955 | 75 | *status = U_MEMORY_ALLOCATION_ERROR; |
4388f060 | 76 | return NULL; |
374ca955 | 77 | } |
729e4ab9 A |
78 | if (U_FAILURE(*status)) { |
79 | delete syms; | |
4388f060 | 80 | return NULL; |
729e4ab9 | 81 | } |
374ca955 | 82 | |
4388f060 A |
83 | retVal = new DecimalFormat(pat, syms, *parseErr, *status); |
84 | if(retVal == NULL) { | |
374ca955 A |
85 | delete syms; |
86 | } | |
4388f060 | 87 | } break; |
374ca955 | 88 | |
b75a7d8f | 89 | #if U_HAVE_RBNF |
374ca955 A |
90 | case UNUM_PATTERN_RULEBASED: { |
91 | UParseError tErr; | |
92 | /* UnicodeString can handle the case when patternLength = -1. */ | |
93 | const UnicodeString pat(pattern, patternLength); | |
94 | ||
95 | if(parseErr==NULL){ | |
96 | parseErr = &tErr; | |
97 | } | |
98 | ||
4388f060 | 99 | retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status); |
374ca955 A |
100 | } break; |
101 | ||
102 | case UNUM_SPELLOUT: | |
4388f060 | 103 | retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status); |
374ca955 | 104 | break; |
b75a7d8f | 105 | |
374ca955 | 106 | case UNUM_ORDINAL: |
4388f060 | 107 | retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status); |
374ca955 | 108 | break; |
b75a7d8f | 109 | |
374ca955 | 110 | case UNUM_DURATION: |
4388f060 | 111 | retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status); |
374ca955 | 112 | break; |
729e4ab9 A |
113 | |
114 | case UNUM_NUMBERING_SYSTEM: | |
4388f060 | 115 | retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status); |
729e4ab9 | 116 | break; |
374ca955 A |
117 | #endif |
118 | ||
b331163b A |
119 | case UNUM_DECIMAL_COMPACT_SHORT: |
120 | retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_SHORT, *status); | |
121 | break; | |
122 | ||
123 | case UNUM_DECIMAL_COMPACT_LONG: | |
124 | retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_LONG, *status); | |
125 | break; | |
126 | ||
374ca955 A |
127 | default: |
128 | *status = U_UNSUPPORTED_ERROR; | |
4388f060 | 129 | return NULL; |
374ca955 | 130 | } |
b75a7d8f | 131 | |
4388f060 | 132 | if(retVal == NULL && U_SUCCESS(*status)) { |
b75a7d8f | 133 | *status = U_MEMORY_ALLOCATION_ERROR; |
374ca955 | 134 | } |
b75a7d8f | 135 | |
4388f060 | 136 | return reinterpret_cast<UNumberFormat *>(retVal); |
b75a7d8f A |
137 | } |
138 | ||
139 | U_CAPI void U_EXPORT2 | |
140 | unum_close(UNumberFormat* fmt) | |
141 | { | |
374ca955 | 142 | delete (NumberFormat*) fmt; |
b75a7d8f A |
143 | } |
144 | ||
145 | U_CAPI UNumberFormat* U_EXPORT2 | |
146 | unum_clone(const UNumberFormat *fmt, | |
147 | UErrorCode *status) | |
148 | { | |
374ca955 A |
149 | if(U_FAILURE(*status)) |
150 | return 0; | |
151 | ||
152 | Format *res = 0; | |
729e4ab9 A |
153 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
154 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |
155 | if (df != NULL) { | |
156 | res = df->clone(); | |
374ca955 | 157 | } else { |
729e4ab9 A |
158 | const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); |
159 | U_ASSERT(rbnf != NULL); | |
160 | res = rbnf->clone(); | |
374ca955 | 161 | } |
b75a7d8f | 162 | |
374ca955 A |
163 | if(res == 0) { |
164 | *status = U_MEMORY_ALLOCATION_ERROR; | |
165 | return 0; | |
166 | } | |
167 | ||
168 | return (UNumberFormat*) res; | |
b75a7d8f A |
169 | } |
170 | ||
171 | U_CAPI int32_t U_EXPORT2 | |
172 | unum_format( const UNumberFormat* fmt, | |
374ca955 | 173 | int32_t number, |
b75a7d8f | 174 | UChar* result, |
374ca955 | 175 | int32_t resultLength, |
b75a7d8f | 176 | UFieldPosition *pos, |
374ca955 | 177 | UErrorCode* status) |
b75a7d8f | 178 | { |
374ca955 A |
179 | return unum_formatInt64(fmt, number, result, resultLength, pos, status); |
180 | } | |
b75a7d8f | 181 | |
374ca955 A |
182 | U_CAPI int32_t U_EXPORT2 |
183 | unum_formatInt64(const UNumberFormat* fmt, | |
184 | int64_t number, | |
185 | UChar* result, | |
186 | int32_t resultLength, | |
187 | UFieldPosition *pos, | |
188 | UErrorCode* status) | |
189 | { | |
190 | if(U_FAILURE(*status)) | |
191 | return -1; | |
192 | ||
193 | UnicodeString res; | |
194 | if(!(result==NULL && resultLength==0)) { | |
195 | // NULL destination for pure preflighting: empty dummy string | |
196 | // otherwise, alias the destination buffer | |
197 | res.setTo(result, 0, resultLength); | |
198 | } | |
199 | ||
200 | FieldPosition fp; | |
201 | ||
202 | if(pos != 0) | |
203 | fp.setField(pos->field); | |
204 | ||
b331163b A |
205 | const CompactDecimalFormat* cdf = dynamic_cast<const CompactDecimalFormat*>((const NumberFormat*)fmt); |
206 | if (cdf != NULL) { | |
207 | cdf->format(number, res, fp); // CompactDecimalFormat does not override the version with UErrorCode& !! | |
208 | } else { | |
209 | ((const NumberFormat*)fmt)->format(number, res, fp, *status); | |
210 | } | |
51004dcb | 211 | |
374ca955 A |
212 | if(pos != 0) { |
213 | pos->beginIndex = fp.getBeginIndex(); | |
214 | pos->endIndex = fp.getEndIndex(); | |
215 | } | |
216 | ||
217 | return res.extract(result, resultLength, *status); | |
b75a7d8f A |
218 | } |
219 | ||
220 | U_CAPI int32_t U_EXPORT2 | |
221 | unum_formatDouble( const UNumberFormat* fmt, | |
222 | double number, | |
223 | UChar* result, | |
224 | int32_t resultLength, | |
225 | UFieldPosition *pos, /* 0 if ignore */ | |
226 | UErrorCode* status) | |
227 | { | |
228 | ||
229 | if(U_FAILURE(*status)) return -1; | |
230 | ||
231 | UnicodeString res; | |
232 | if(!(result==NULL && resultLength==0)) { | |
233 | // NULL destination for pure preflighting: empty dummy string | |
234 | // otherwise, alias the destination buffer | |
235 | res.setTo(result, 0, resultLength); | |
236 | } | |
237 | ||
238 | FieldPosition fp; | |
239 | ||
240 | if(pos != 0) | |
241 | fp.setField(pos->field); | |
242 | ||
b331163b A |
243 | const CompactDecimalFormat* cdf = dynamic_cast<const CompactDecimalFormat*>((const NumberFormat*)fmt); |
244 | if (cdf != NULL) { | |
245 | cdf->format(number, res, fp); // CompactDecimalFormat does not override the version with UErrorCode& !! | |
246 | } else { | |
247 | ((const NumberFormat*)fmt)->format(number, res, fp, *status); | |
248 | } | |
b75a7d8f A |
249 | |
250 | if(pos != 0) { | |
251 | pos->beginIndex = fp.getBeginIndex(); | |
252 | pos->endIndex = fp.getEndIndex(); | |
253 | } | |
254 | ||
255 | return res.extract(result, resultLength, *status); | |
256 | } | |
257 | ||
729e4ab9 | 258 | |
51004dcb | 259 | U_CAPI int32_t U_EXPORT2 |
729e4ab9 A |
260 | unum_formatDecimal(const UNumberFormat* fmt, |
261 | const char * number, | |
262 | int32_t length, | |
263 | UChar* result, | |
264 | int32_t resultLength, | |
265 | UFieldPosition *pos, /* 0 if ignore */ | |
266 | UErrorCode* status) { | |
267 | ||
268 | if(U_FAILURE(*status)) { | |
269 | return -1; | |
270 | } | |
271 | if ((result == NULL && resultLength != 0) || resultLength < 0) { | |
272 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
273 | return -1; | |
274 | } | |
275 | ||
276 | FieldPosition fp; | |
277 | if(pos != 0) { | |
278 | fp.setField(pos->field); | |
279 | } | |
280 | ||
281 | if (length < 0) { | |
282 | length = uprv_strlen(number); | |
283 | } | |
284 | StringPiece numSP(number, length); | |
285 | Formattable numFmtbl(numSP, *status); | |
286 | ||
287 | UnicodeString resultStr; | |
288 | if (resultLength > 0) { | |
289 | // Alias the destination buffer. | |
290 | resultStr.setTo(result, 0, resultLength); | |
291 | } | |
292 | ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status); | |
293 | if(pos != 0) { | |
294 | pos->beginIndex = fp.getBeginIndex(); | |
295 | pos->endIndex = fp.getEndIndex(); | |
296 | } | |
297 | return resultStr.extract(result, resultLength, *status); | |
298 | } | |
299 | ||
300 | ||
301 | ||
302 | ||
46f4442e | 303 | U_CAPI int32_t U_EXPORT2 |
374ca955 A |
304 | unum_formatDoubleCurrency(const UNumberFormat* fmt, |
305 | double number, | |
306 | UChar* currency, | |
307 | UChar* result, | |
308 | int32_t resultLength, | |
309 | UFieldPosition* pos, /* ignored if 0 */ | |
310 | UErrorCode* status) { | |
311 | if (U_FAILURE(*status)) return -1; | |
312 | ||
313 | UnicodeString res; | |
314 | if (!(result==NULL && resultLength==0)) { | |
315 | // NULL destination for pure preflighting: empty dummy string | |
316 | // otherwise, alias the destination buffer | |
317 | res.setTo(result, 0, resultLength); | |
318 | } | |
319 | ||
320 | FieldPosition fp; | |
321 | if (pos != 0) { | |
322 | fp.setField(pos->field); | |
323 | } | |
46f4442e A |
324 | CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status); |
325 | // Check for null pointer. | |
326 | if (tempCurrAmnt == NULL) { | |
327 | *status = U_MEMORY_ALLOCATION_ERROR; | |
328 | return -1; | |
329 | } | |
330 | Formattable n(tempCurrAmnt); | |
374ca955 A |
331 | ((const NumberFormat*)fmt)->format(n, res, fp, *status); |
332 | ||
333 | if (pos != 0) { | |
334 | pos->beginIndex = fp.getBeginIndex(); | |
335 | pos->endIndex = fp.getEndIndex(); | |
336 | } | |
337 | ||
338 | return res.extract(result, resultLength, *status); | |
339 | } | |
340 | ||
341 | static void | |
342 | parseRes(Formattable& res, | |
343 | const UNumberFormat* fmt, | |
344 | const UChar* text, | |
345 | int32_t textLength, | |
346 | int32_t *parsePos /* 0 = start */, | |
374ca955 A |
347 | UErrorCode *status) |
348 | { | |
349 | if(U_FAILURE(*status)) | |
350 | return; | |
351 | ||
4388f060 | 352 | const UnicodeString src((UBool)(textLength == -1), text, textLength); |
374ca955 A |
353 | ParsePosition pp; |
354 | ||
355 | if(parsePos != 0) | |
356 | pp.setIndex(*parsePos); | |
357 | ||
4388f060 | 358 | ((const NumberFormat*)fmt)->parse(src, res, pp); |
374ca955 | 359 | |
46f4442e A |
360 | if(pp.getErrorIndex() != -1) { |
361 | *status = U_PARSE_ERROR; | |
362 | if(parsePos != 0) { | |
374ca955 | 363 | *parsePos = pp.getErrorIndex(); |
374ca955 | 364 | } |
46f4442e A |
365 | } else if(parsePos != 0) { |
366 | *parsePos = pp.getIndex(); | |
374ca955 A |
367 | } |
368 | } | |
369 | ||
b75a7d8f A |
370 | U_CAPI int32_t U_EXPORT2 |
371 | unum_parse( const UNumberFormat* fmt, | |
372 | const UChar* text, | |
373 | int32_t textLength, | |
374 | int32_t *parsePos /* 0 = start */, | |
375 | UErrorCode *status) | |
376 | { | |
374ca955 | 377 | Formattable res; |
4388f060 | 378 | parseRes(res, fmt, text, textLength, parsePos, status); |
374ca955 A |
379 | return res.getLong(*status); |
380 | } | |
b75a7d8f | 381 | |
374ca955 A |
382 | U_CAPI int64_t U_EXPORT2 |
383 | unum_parseInt64( const UNumberFormat* fmt, | |
384 | const UChar* text, | |
385 | int32_t textLength, | |
386 | int32_t *parsePos /* 0 = start */, | |
387 | UErrorCode *status) | |
388 | { | |
389 | Formattable res; | |
4388f060 | 390 | parseRes(res, fmt, text, textLength, parsePos, status); |
374ca955 | 391 | return res.getInt64(*status); |
b75a7d8f A |
392 | } |
393 | ||
394 | U_CAPI double U_EXPORT2 | |
395 | unum_parseDouble( const UNumberFormat* fmt, | |
396 | const UChar* text, | |
397 | int32_t textLength, | |
398 | int32_t *parsePos /* 0 = start */, | |
399 | UErrorCode *status) | |
400 | { | |
374ca955 | 401 | Formattable res; |
4388f060 | 402 | parseRes(res, fmt, text, textLength, parsePos, status); |
374ca955 A |
403 | return res.getDouble(*status); |
404 | } | |
b75a7d8f | 405 | |
729e4ab9 A |
406 | U_CAPI int32_t U_EXPORT2 |
407 | unum_parseDecimal(const UNumberFormat* fmt, | |
408 | const UChar* text, | |
409 | int32_t textLength, | |
410 | int32_t *parsePos /* 0 = start */, | |
411 | char *outBuf, | |
412 | int32_t outBufLength, | |
413 | UErrorCode *status) | |
414 | { | |
415 | if (U_FAILURE(*status)) { | |
416 | return -1; | |
417 | } | |
418 | if ((outBuf == NULL && outBufLength != 0) || outBufLength < 0) { | |
419 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
420 | return -1; | |
421 | } | |
422 | Formattable res; | |
4388f060 | 423 | parseRes(res, fmt, text, textLength, parsePos, status); |
729e4ab9 A |
424 | StringPiece sp = res.getDecimalNumber(*status); |
425 | if (U_FAILURE(*status)) { | |
426 | return -1; | |
427 | } else if (sp.size() > outBufLength) { | |
428 | *status = U_BUFFER_OVERFLOW_ERROR; | |
429 | } else if (sp.size() == outBufLength) { | |
430 | uprv_strncpy(outBuf, sp.data(), sp.size()); | |
431 | *status = U_STRING_NOT_TERMINATED_WARNING; | |
432 | } else { | |
4388f060 | 433 | U_ASSERT(outBufLength > 0); |
729e4ab9 A |
434 | uprv_strcpy(outBuf, sp.data()); |
435 | } | |
436 | return sp.size(); | |
437 | } | |
438 | ||
46f4442e | 439 | U_CAPI double U_EXPORT2 |
374ca955 A |
440 | unum_parseDoubleCurrency(const UNumberFormat* fmt, |
441 | const UChar* text, | |
442 | int32_t textLength, | |
443 | int32_t* parsePos, /* 0 = start */ | |
444 | UChar* currency, | |
445 | UErrorCode* status) { | |
4388f060 | 446 | double doubleVal = 0.0; |
374ca955 | 447 | currency[0] = 0; |
4388f060 A |
448 | if (U_FAILURE(*status)) { |
449 | return doubleVal; | |
b75a7d8f | 450 | } |
4388f060 A |
451 | const UnicodeString src((UBool)(textLength == -1), text, textLength); |
452 | ParsePosition pp; | |
453 | if (parsePos != NULL) { | |
454 | pp.setIndex(*parsePos); | |
455 | } | |
456 | *status = U_PARSE_ERROR; // assume failure, reset if succeed | |
457 | LocalPointer<CurrencyAmount> currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp)); | |
458 | if (pp.getErrorIndex() != -1) { | |
459 | if (parsePos != NULL) { | |
460 | *parsePos = pp.getErrorIndex(); | |
461 | } | |
462 | } else { | |
463 | if (parsePos != NULL) { | |
464 | *parsePos = pp.getIndex(); | |
465 | } | |
466 | if (pp.getIndex() > 0) { | |
467 | *status = U_ZERO_ERROR; | |
468 | u_strcpy(currency, currAmt->getISOCurrency()); | |
469 | doubleVal = currAmt->getNumber().getDouble(*status); | |
470 | } | |
471 | } | |
472 | return doubleVal; | |
b75a7d8f A |
473 | } |
474 | ||
475 | U_CAPI const char* U_EXPORT2 | |
476 | unum_getAvailable(int32_t index) | |
477 | { | |
374ca955 | 478 | return uloc_getAvailable(index); |
b75a7d8f A |
479 | } |
480 | ||
481 | U_CAPI int32_t U_EXPORT2 | |
482 | unum_countAvailable() | |
483 | { | |
374ca955 | 484 | return uloc_countAvailable(); |
b75a7d8f A |
485 | } |
486 | ||
487 | U_CAPI int32_t U_EXPORT2 | |
488 | unum_getAttribute(const UNumberFormat* fmt, | |
489 | UNumberFormatAttribute attr) | |
490 | { | |
729e4ab9 | 491 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
4388f060 A |
492 | if ( attr == UNUM_LENIENT_PARSE ) { |
493 | // Supported for all subclasses | |
494 | return nf->isLenient(); | |
495 | } | |
51004dcb | 496 | |
4388f060 | 497 | // The remaining attributea are only supported for DecimalFormat |
729e4ab9 A |
498 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); |
499 | if (df != NULL) { | |
51004dcb A |
500 | UErrorCode ignoredStatus = U_ZERO_ERROR; |
501 | return df->getAttribute( attr, ignoredStatus ); | |
b75a7d8f | 502 | } |
374ca955 | 503 | |
b75a7d8f A |
504 | return -1; |
505 | } | |
506 | ||
507 | U_CAPI void U_EXPORT2 | |
508 | unum_setAttribute( UNumberFormat* fmt, | |
509 | UNumberFormatAttribute attr, | |
510 | int32_t newValue) | |
511 | { | |
729e4ab9 | 512 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
4388f060 A |
513 | if ( attr == UNUM_LENIENT_PARSE ) { |
514 | // Supported for all subclasses | |
51004dcb | 515 | // keep this here as the class may not be a DecimalFormat |
4388f060 A |
516 | return nf->setLenient(newValue != 0); |
517 | } | |
518 | // The remaining attributea are only supported for DecimalFormat | |
729e4ab9 A |
519 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); |
520 | if (df != NULL) { | |
51004dcb A |
521 | UErrorCode ignoredStatus = U_ZERO_ERROR; |
522 | df->setAttribute(attr, newValue, ignoredStatus); | |
b75a7d8f A |
523 | } |
524 | } | |
525 | ||
526 | U_CAPI double U_EXPORT2 | |
527 | unum_getDoubleAttribute(const UNumberFormat* fmt, | |
528 | UNumberFormatAttribute attr) | |
529 | { | |
729e4ab9 A |
530 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
531 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |
532 | if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { | |
533 | return df->getRoundingIncrement(); | |
374ca955 A |
534 | } else { |
535 | return -1.0; | |
536 | } | |
b75a7d8f A |
537 | } |
538 | ||
539 | U_CAPI void U_EXPORT2 | |
540 | unum_setDoubleAttribute( UNumberFormat* fmt, | |
541 | UNumberFormatAttribute attr, | |
542 | double newValue) | |
543 | { | |
729e4ab9 A |
544 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
545 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |
546 | if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { | |
547 | df->setRoundingIncrement(newValue); | |
374ca955 | 548 | } |
b75a7d8f A |
549 | } |
550 | ||
551 | U_CAPI int32_t U_EXPORT2 | |
552 | unum_getTextAttribute(const UNumberFormat* fmt, | |
553 | UNumberFormatTextAttribute tag, | |
554 | UChar* result, | |
555 | int32_t resultLength, | |
556 | UErrorCode* status) | |
557 | { | |
374ca955 A |
558 | if(U_FAILURE(*status)) |
559 | return -1; | |
560 | ||
561 | UnicodeString res; | |
562 | if(!(result==NULL && resultLength==0)) { | |
563 | // NULL destination for pure preflighting: empty dummy string | |
564 | // otherwise, alias the destination buffer | |
565 | res.setTo(result, 0, resultLength); | |
566 | } | |
b75a7d8f | 567 | |
729e4ab9 A |
568 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
569 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |
570 | if (df != NULL) { | |
374ca955 A |
571 | switch(tag) { |
572 | case UNUM_POSITIVE_PREFIX: | |
573 | df->getPositivePrefix(res); | |
574 | break; | |
575 | ||
576 | case UNUM_POSITIVE_SUFFIX: | |
577 | df->getPositiveSuffix(res); | |
578 | break; | |
579 | ||
580 | case UNUM_NEGATIVE_PREFIX: | |
581 | df->getNegativePrefix(res); | |
582 | break; | |
583 | ||
584 | case UNUM_NEGATIVE_SUFFIX: | |
585 | df->getNegativeSuffix(res); | |
586 | break; | |
587 | ||
588 | case UNUM_PADDING_CHARACTER: | |
589 | res = df->getPadCharacterString(); | |
590 | break; | |
591 | ||
592 | case UNUM_CURRENCY_CODE: | |
593 | res = UnicodeString(df->getCurrency()); | |
594 | break; | |
595 | ||
596 | default: | |
597 | *status = U_UNSUPPORTED_ERROR; | |
598 | return -1; | |
599 | } | |
600 | } else { | |
729e4ab9 A |
601 | const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); |
602 | U_ASSERT(rbnf != NULL); | |
374ca955 A |
603 | if (tag == UNUM_DEFAULT_RULESET) { |
604 | res = rbnf->getDefaultRuleSetName(); | |
605 | } else if (tag == UNUM_PUBLIC_RULESETS) { | |
606 | int32_t count = rbnf->getNumberOfRuleSetNames(); | |
607 | for (int i = 0; i < count; ++i) { | |
608 | res += rbnf->getRuleSetName(i); | |
609 | res += (UChar)0x003b; // semicolon | |
610 | } | |
611 | } else { | |
612 | *status = U_UNSUPPORTED_ERROR; | |
613 | return -1; | |
614 | } | |
615 | } | |
b75a7d8f | 616 | |
374ca955 | 617 | return res.extract(result, resultLength, *status); |
b75a7d8f A |
618 | } |
619 | ||
620 | U_CAPI void U_EXPORT2 | |
621 | unum_setTextAttribute( UNumberFormat* fmt, | |
622 | UNumberFormatTextAttribute tag, | |
623 | const UChar* newValue, | |
624 | int32_t newValueLength, | |
625 | UErrorCode *status) | |
626 | { | |
374ca955 A |
627 | if(U_FAILURE(*status)) |
628 | return; | |
729e4ab9 | 629 | |
4388f060 | 630 | UnicodeString val(newValue, newValueLength); |
729e4ab9 A |
631 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
632 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |
633 | if (df != NULL) { | |
374ca955 A |
634 | switch(tag) { |
635 | case UNUM_POSITIVE_PREFIX: | |
636 | df->setPositivePrefix(val); | |
637 | break; | |
638 | ||
639 | case UNUM_POSITIVE_SUFFIX: | |
640 | df->setPositiveSuffix(val); | |
641 | break; | |
642 | ||
643 | case UNUM_NEGATIVE_PREFIX: | |
644 | df->setNegativePrefix(val); | |
645 | break; | |
646 | ||
647 | case UNUM_NEGATIVE_SUFFIX: | |
648 | df->setNegativeSuffix(val); | |
649 | break; | |
650 | ||
651 | case UNUM_PADDING_CHARACTER: | |
4388f060 | 652 | df->setPadCharacter(val); |
374ca955 A |
653 | break; |
654 | ||
655 | case UNUM_CURRENCY_CODE: | |
4388f060 | 656 | df->setCurrency(val.getTerminatedBuffer(), *status); |
374ca955 A |
657 | break; |
658 | ||
659 | default: | |
660 | *status = U_UNSUPPORTED_ERROR; | |
661 | break; | |
662 | } | |
663 | } else { | |
729e4ab9 A |
664 | RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf); |
665 | U_ASSERT(rbnf != NULL); | |
374ca955 | 666 | if (tag == UNUM_DEFAULT_RULESET) { |
4388f060 | 667 | rbnf->setDefaultRuleSet(val, *status); |
374ca955 | 668 | } else { |
729e4ab9 | 669 | *status = U_UNSUPPORTED_ERROR; |
374ca955 A |
670 | } |
671 | } | |
b75a7d8f A |
672 | } |
673 | ||
674 | U_CAPI int32_t U_EXPORT2 | |
675 | unum_toPattern( const UNumberFormat* fmt, | |
676 | UBool isPatternLocalized, | |
677 | UChar* result, | |
678 | int32_t resultLength, | |
679 | UErrorCode* status) | |
680 | { | |
374ca955 A |
681 | if(U_FAILURE(*status)) |
682 | return -1; | |
683 | ||
684 | UnicodeString pat; | |
685 | if(!(result==NULL && resultLength==0)) { | |
686 | // NULL destination for pure preflighting: empty dummy string | |
687 | // otherwise, alias the destination buffer | |
688 | pat.setTo(result, 0, resultLength); | |
689 | } | |
b75a7d8f | 690 | |
729e4ab9 A |
691 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
692 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |
693 | if (df != NULL) { | |
374ca955 A |
694 | if(isPatternLocalized) |
695 | df->toLocalizedPattern(pat); | |
696 | else | |
697 | df->toPattern(pat); | |
698 | } else { | |
729e4ab9 A |
699 | const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); |
700 | U_ASSERT(rbnf != NULL); | |
701 | pat = rbnf->getRules(); | |
374ca955 A |
702 | } |
703 | return pat.extract(result, resultLength, *status); | |
b75a7d8f A |
704 | } |
705 | ||
706 | U_CAPI int32_t U_EXPORT2 | |
374ca955 | 707 | unum_getSymbol(const UNumberFormat *fmt, |
b75a7d8f A |
708 | UNumberFormatSymbol symbol, |
709 | UChar *buffer, | |
710 | int32_t size, | |
374ca955 A |
711 | UErrorCode *status) |
712 | { | |
713 | if(status==NULL || U_FAILURE(*status)) { | |
714 | return 0; | |
715 | } | |
4388f060 | 716 | if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) { |
374ca955 A |
717 | *status=U_ILLEGAL_ARGUMENT_ERROR; |
718 | return 0; | |
719 | } | |
729e4ab9 A |
720 | const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt); |
721 | const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf); | |
722 | if (dcf == NULL) { | |
374ca955 A |
723 | *status = U_UNSUPPORTED_ERROR; |
724 | return 0; | |
725 | } | |
b75a7d8f | 726 | |
729e4ab9 | 727 | return dcf-> |
b75a7d8f A |
728 | getDecimalFormatSymbols()-> |
729 | getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol). | |
730 | extract(buffer, size, *status); | |
731 | } | |
732 | ||
733 | U_CAPI void U_EXPORT2 | |
734 | unum_setSymbol(UNumberFormat *fmt, | |
735 | UNumberFormatSymbol symbol, | |
736 | const UChar *value, | |
737 | int32_t length, | |
374ca955 | 738 | UErrorCode *status) |
b75a7d8f | 739 | { |
374ca955 A |
740 | if(status==NULL || U_FAILURE(*status)) { |
741 | return; | |
742 | } | |
4388f060 | 743 | if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) { |
374ca955 A |
744 | *status=U_ILLEGAL_ARGUMENT_ERROR; |
745 | return; | |
746 | } | |
729e4ab9 A |
747 | NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt); |
748 | DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf); | |
749 | if (dcf == NULL) { | |
374ca955 A |
750 | *status = U_UNSUPPORTED_ERROR; |
751 | return; | |
752 | } | |
753 | ||
729e4ab9 | 754 | DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols()); |
374ca955 A |
755 | symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol, |
756 | UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */ | |
729e4ab9 | 757 | dcf->setDecimalFormatSymbols(symbols); |
b75a7d8f | 758 | } |
b75a7d8f A |
759 | |
760 | U_CAPI void U_EXPORT2 | |
729e4ab9 | 761 | unum_applyPattern( UNumberFormat *fmt, |
b75a7d8f A |
762 | UBool localized, |
763 | const UChar *pattern, | |
764 | int32_t patternLength, | |
765 | UParseError *parseError, | |
766 | UErrorCode* status) | |
767 | { | |
374ca955 A |
768 | UErrorCode tStatus = U_ZERO_ERROR; |
769 | UParseError tParseError; | |
770 | ||
771 | if(parseError == NULL){ | |
772 | parseError = &tParseError; | |
773 | } | |
774 | ||
775 | if(status==NULL){ | |
776 | status = &tStatus; | |
777 | } | |
778 | ||
779 | int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength); | |
780 | const UnicodeString pat((UChar*)pattern, len, len); | |
729e4ab9 | 781 | |
374ca955 | 782 | // Verify if the object passed is a DecimalFormat object |
729e4ab9 A |
783 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
784 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |
785 | if (df != NULL) { | |
374ca955 | 786 | if(localized) { |
729e4ab9 | 787 | df->applyLocalizedPattern(pat,*parseError, *status); |
374ca955 | 788 | } else { |
729e4ab9 | 789 | df->applyPattern(pat,*parseError, *status); |
374ca955 A |
790 | } |
791 | } else { | |
792 | *status = U_UNSUPPORTED_ERROR; | |
b75a7d8f | 793 | return; |
374ca955 A |
794 | } |
795 | } | |
796 | ||
797 | U_CAPI const char* U_EXPORT2 | |
798 | unum_getLocaleByType(const UNumberFormat *fmt, | |
799 | ULocDataLocaleType type, | |
800 | UErrorCode* status) | |
801 | { | |
802 | if (fmt == NULL) { | |
803 | if (U_SUCCESS(*status)) { | |
804 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
805 | } | |
806 | return NULL; | |
807 | } | |
808 | return ((const Format*)fmt)->getLocaleID(type, *status); | |
b75a7d8f A |
809 | } |
810 | ||
57a6839d A |
811 | U_CAPI void U_EXPORT2 |
812 | unum_setContext(UNumberFormat* fmt, UDisplayContext value, UErrorCode* status) | |
813 | { | |
814 | if (U_FAILURE(*status)) { | |
815 | return; | |
816 | } | |
817 | ((NumberFormat*)fmt)->setContext(value, *status); | |
818 | return; | |
819 | } | |
820 | ||
821 | U_CAPI UDisplayContext U_EXPORT2 | |
822 | unum_getContext(const UNumberFormat *fmt, UDisplayContextType type, UErrorCode* status) | |
823 | { | |
824 | if (U_FAILURE(*status)) { | |
825 | return (UDisplayContext)0; | |
826 | } | |
827 | return ((const NumberFormat*)fmt)->getContext(type, *status); | |
828 | } | |
829 | ||
830 | U_INTERNAL UFormattable * U_EXPORT2 | |
831 | unum_parseToUFormattable(const UNumberFormat* fmt, | |
832 | UFormattable *result, | |
833 | const UChar* text, | |
834 | int32_t textLength, | |
835 | int32_t* parsePos, /* 0 = start */ | |
836 | UErrorCode* status) { | |
837 | UFormattable *newFormattable = NULL; | |
838 | if (U_FAILURE(*status)) return result; | |
839 | if (fmt == NULL || (text==NULL && textLength!=0)) { | |
840 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
841 | return result; | |
842 | } | |
843 | if (result == NULL) { // allocate if not allocated. | |
844 | newFormattable = result = ufmt_open(status); | |
845 | } | |
846 | parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status); | |
847 | if (U_FAILURE(*status) && newFormattable != NULL) { | |
848 | ufmt_close(newFormattable); | |
849 | result = NULL; // deallocate if there was a parse error | |
850 | } | |
851 | return result; | |
852 | } | |
853 | ||
854 | U_INTERNAL int32_t U_EXPORT2 | |
855 | unum_formatUFormattable(const UNumberFormat* fmt, | |
856 | const UFormattable *number, | |
857 | UChar *result, | |
858 | int32_t resultLength, | |
859 | UFieldPosition *pos, /* ignored if 0 */ | |
860 | UErrorCode *status) { | |
861 | if (U_FAILURE(*status)) { | |
862 | return 0; | |
863 | } | |
864 | if (fmt == NULL || number==NULL || | |
865 | (result==NULL ? resultLength!=0 : resultLength<0)) { | |
866 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
867 | return 0; | |
868 | } | |
869 | UnicodeString res(result, 0, resultLength); | |
870 | ||
871 | FieldPosition fp; | |
872 | ||
873 | if(pos != 0) | |
874 | fp.setField(pos->field); | |
875 | ||
876 | ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status); | |
877 | ||
878 | if(pos != 0) { | |
879 | pos->beginIndex = fp.getBeginIndex(); | |
880 | pos->endIndex = fp.getEndIndex(); | |
881 | } | |
882 | ||
883 | return res.extract(result, resultLength, *status); | |
884 | } | |
885 | ||
b75a7d8f | 886 | #endif /* #if !UCONFIG_NO_FORMATTING */ |