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