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