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