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