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