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