Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 *   Copyright (C) 1996-2012, International Business Machines
      4 *   Corporation and others.  All Rights Reserved.
      5 *******************************************************************************
      6 * Modification History:
      7 *
      8 *   Date        Name        Description
      9 *   06/24/99    helena      Integrated Alan's NF enhancements and Java2 bug fixes
     10 *******************************************************************************
     11 */
     12 
     13 #include "unicode/utypes.h"
     14 
     15 #if !UCONFIG_NO_FORMATTING
     16 
     17 #include "unicode/unum.h"
     18 
     19 #include "unicode/uloc.h"
     20 #include "unicode/numfmt.h"
     21 #include "unicode/decimfmt.h"
     22 #include "unicode/rbnf.h"
     23 #include "unicode/ustring.h"
     24 #include "unicode/fmtable.h"
     25 #include "unicode/dcfmtsym.h"
     26 #include "unicode/curramt.h"
     27 #include "unicode/localpointer.h"
     28 #include "uassert.h"
     29 #include "cpputils.h"
     30 #include "cstring.h"
     31 
     32 
     33 U_NAMESPACE_USE
     34 
     35 
     36 U_CAPI UNumberFormat* U_EXPORT2
     37 unum_open(  UNumberFormatStyle    style,
     38             const    UChar*    pattern,
     39             int32_t            patternLength,
     40             const    char*     locale,
     41             UParseError*       parseErr,
     42             UErrorCode*        status) {
     43     if(U_FAILURE(*status)) {
     44         return NULL;
     45     }
     46 
     47     NumberFormat *retVal = NULL;
     48 
     49     switch(style) {
     50     case UNUM_DECIMAL:
     51     case UNUM_CURRENCY:
     52     case UNUM_PERCENT:
     53     case UNUM_SCIENTIFIC:
     54         retVal = NumberFormat::createInstance(Locale(locale), style, *status);
     55         break;
     56 
     57     case UNUM_PATTERN_DECIMAL: {
     58         UParseError tErr;
     59         /* UnicodeString can handle the case when patternLength = -1. */
     60         const UnicodeString pat(pattern, patternLength);
     61 
     62         if(parseErr==NULL){
     63             parseErr = &tErr;
     64         }
     65 
     66         DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status);
     67         if(syms == NULL) {
     68             *status = U_MEMORY_ALLOCATION_ERROR;
     69             return NULL;
     70         }
     71         if (U_FAILURE(*status)) {
     72             delete syms;
     73             return NULL;
     74         }
     75 
     76         retVal = new DecimalFormat(pat, syms, *parseErr, *status);
     77         if(retVal == NULL) {
     78             delete syms;
     79         }
     80     } break;
     81 
     82 #if U_HAVE_RBNF
     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 
     92         retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status);
     93     } break;
     94 
     95     case UNUM_SPELLOUT:
     96         retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
     97         break;
     98 
     99     case UNUM_ORDINAL:
    100         retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status);
    101         break;
    102 
    103     case UNUM_DURATION:
    104         retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
    105         break;
    106 
    107     case UNUM_NUMBERING_SYSTEM:
    108         retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status);
    109         break;
    110 #endif
    111 
    112     default:
    113         *status = U_UNSUPPORTED_ERROR;
    114         return NULL;
    115     }
    116 
    117     if(retVal == NULL && U_SUCCESS(*status)) {
    118         *status = U_MEMORY_ALLOCATION_ERROR;
    119     }
    120 
    121     return reinterpret_cast<UNumberFormat *>(retVal);
    122 }
    123 
    124 U_CAPI void U_EXPORT2
    125 unum_close(UNumberFormat* fmt)
    126 {
    127     delete (NumberFormat*) fmt;
    128 }
    129 
    130 U_CAPI UNumberFormat* U_EXPORT2
    131 unum_clone(const UNumberFormat *fmt,
    132        UErrorCode *status)
    133 {
    134     if(U_FAILURE(*status))
    135         return 0;
    136 
    137     Format *res = 0;
    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();
    142     } else {
    143         const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
    144         U_ASSERT(rbnf != NULL);
    145         res = rbnf->clone();
    146     }
    147 
    148     if(res == 0) {
    149         *status = U_MEMORY_ALLOCATION_ERROR;
    150         return 0;
    151     }
    152 
    153     return (UNumberFormat*) res;
    154 }
    155 
    156 U_CAPI int32_t U_EXPORT2
    157 unum_format(    const    UNumberFormat*    fmt,
    158         int32_t           number,
    159         UChar*            result,
    160         int32_t           resultLength,
    161         UFieldPosition    *pos,
    162         UErrorCode*       status)
    163 {
    164         return unum_formatInt64(fmt, number, result, resultLength, pos, status);
    165 }
    166 
    167 U_CAPI int32_t U_EXPORT2
    168 unum_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, *status);
    191 
    192     if(pos != 0) {
    193         pos->beginIndex = fp.getBeginIndex();
    194         pos->endIndex = fp.getEndIndex();
    195     }
    196 
    197     return res.extract(result, resultLength, *status);
    198 }
    199 
    200 U_CAPI int32_t U_EXPORT2
    201 unum_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 
    223   ((const NumberFormat*)fmt)->format(number, res, fp, *status);
    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 
    233 
    234 U_CAPI int32_t U_EXPORT2
    235 unum_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 
    278 U_CAPI int32_t U_EXPORT2
    279 unum_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     }
    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);
    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 
    316 static void
    317 parseRes(Formattable& res,
    318          const   UNumberFormat*  fmt,
    319          const   UChar*          text,
    320          int32_t         textLength,
    321          int32_t         *parsePos /* 0 = start */,
    322          UErrorCode      *status)
    323 {
    324     if(U_FAILURE(*status))
    325         return;
    326 
    327     const UnicodeString src((UBool)(textLength == -1), text, textLength);
    328     ParsePosition pp;
    329 
    330     if(parsePos != 0)
    331         pp.setIndex(*parsePos);
    332 
    333     ((const NumberFormat*)fmt)->parse(src, res, pp);
    334 
    335     if(pp.getErrorIndex() != -1) {
    336         *status = U_PARSE_ERROR;
    337         if(parsePos != 0) {
    338             *parsePos = pp.getErrorIndex();
    339         }
    340     } else if(parsePos != 0) {
    341         *parsePos = pp.getIndex();
    342     }
    343 }
    344 
    345 U_CAPI int32_t U_EXPORT2
    346 unum_parse(    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, status);
    354     return res.getLong(*status);
    355 }
    356 
    357 U_CAPI int64_t U_EXPORT2
    358 unum_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;
    365     parseRes(res, fmt, text, textLength, parsePos, status);
    366     return res.getInt64(*status);
    367 }
    368 
    369 U_CAPI double U_EXPORT2
    370 unum_parseDouble(    const   UNumberFormat*  fmt,
    371             const   UChar*          text,
    372             int32_t         textLength,
    373             int32_t         *parsePos /* 0 = start */,
    374             UErrorCode      *status)
    375 {
    376     Formattable res;
    377     parseRes(res, fmt, text, textLength, parsePos, status);
    378     return res.getDouble(*status);
    379 }
    380 
    381 U_CAPI int32_t U_EXPORT2
    382 unum_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;
    398     parseRes(res, fmt, text, textLength, parsePos, status);
    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 {
    408         U_ASSERT(outBufLength > 0);
    409         uprv_strcpy(outBuf, sp.data());
    410     }
    411     return sp.size();
    412 }
    413 
    414 U_CAPI double U_EXPORT2
    415 unum_parseDoubleCurrency(const UNumberFormat* fmt,
    416                          const UChar* text,
    417                          int32_t textLength,
    418                          int32_t* parsePos, /* 0 = start */
    419                          UChar* currency,
    420                          UErrorCode* status) {
    421     double doubleVal = 0.0;
    422     currency[0] = 0;
    423     if (U_FAILURE(*status)) {
    424         return doubleVal;
    425     }
    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;
    448 }
    449 
    450 U_CAPI const char* U_EXPORT2
    451 unum_getAvailable(int32_t index)
    452 {
    453     return uloc_getAvailable(index);
    454 }
    455 
    456 U_CAPI int32_t U_EXPORT2
    457 unum_countAvailable()
    458 {
    459     return uloc_countAvailable();
    460 }
    461 
    462 U_CAPI int32_t U_EXPORT2
    463 unum_getAttribute(const UNumberFormat*          fmt,
    464           UNumberFormatAttribute  attr)
    465 {
    466   const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
    467   if ( attr == UNUM_LENIENT_PARSE ) {
    468     // Supported for all subclasses
    469     return nf->isLenient();
    470   }
    471 
    472   // The remaining attributea are only supported for DecimalFormat
    473   const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
    474   if (df != NULL) {
    475     UErrorCode ignoredStatus = U_ZERO_ERROR;
    476     return df->getAttribute( attr, ignoredStatus );
    477   }
    478 
    479   return -1;
    480 }
    481 
    482 U_CAPI void U_EXPORT2
    483 unum_setAttribute(    UNumberFormat*          fmt,
    484             UNumberFormatAttribute  attr,
    485             int32_t                 newValue)
    486 {
    487   NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
    488   if ( attr == UNUM_LENIENT_PARSE ) {
    489     // Supported for all subclasses
    490     // keep this here as the class may not be a DecimalFormat
    491     return nf->setLenient(newValue != 0);
    492   }
    493   // The remaining attributea are only supported for DecimalFormat
    494   DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
    495   if (df != NULL) {
    496     UErrorCode ignoredStatus = U_ZERO_ERROR;
    497     df->setAttribute(attr, newValue, ignoredStatus);
    498   }
    499 }
    500 
    501 U_CAPI double U_EXPORT2
    502 unum_getDoubleAttribute(const UNumberFormat*          fmt,
    503           UNumberFormatAttribute  attr)
    504 {
    505     const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
    506     const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
    507     if (df != NULL &&  attr == UNUM_ROUNDING_INCREMENT) {
    508         return df->getRoundingIncrement();
    509     } else {
    510         return -1.0;
    511     }
    512 }
    513 
    514 U_CAPI void U_EXPORT2
    515 unum_setDoubleAttribute(    UNumberFormat*          fmt,
    516             UNumberFormatAttribute  attr,
    517             double                 newValue)
    518 {
    519     NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
    520     DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
    521     if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) {
    522         df->setRoundingIncrement(newValue);
    523     }
    524 }
    525 
    526 U_CAPI int32_t U_EXPORT2
    527 unum_getTextAttribute(const UNumberFormat*  fmt,
    528             UNumberFormatTextAttribute      tag,
    529             UChar*                          result,
    530             int32_t                         resultLength,
    531             UErrorCode*                     status)
    532 {
    533     if(U_FAILURE(*status))
    534         return -1;
    535 
    536     UnicodeString res;
    537     if(!(result==NULL && resultLength==0)) {
    538         // NULL destination for pure preflighting: empty dummy string
    539         // otherwise, alias the destination buffer
    540         res.setTo(result, 0, resultLength);
    541     }
    542 
    543     const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
    544     const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
    545     if (df != NULL) {
    546         switch(tag) {
    547         case UNUM_POSITIVE_PREFIX:
    548             df->getPositivePrefix(res);
    549             break;
    550 
    551         case UNUM_POSITIVE_SUFFIX:
    552             df->getPositiveSuffix(res);
    553             break;
    554 
    555         case UNUM_NEGATIVE_PREFIX:
    556             df->getNegativePrefix(res);
    557             break;
    558 
    559         case UNUM_NEGATIVE_SUFFIX:
    560             df->getNegativeSuffix(res);
    561             break;
    562 
    563         case UNUM_PADDING_CHARACTER:
    564             res = df->getPadCharacterString();
    565             break;
    566 
    567         case UNUM_CURRENCY_CODE:
    568             res = UnicodeString(df->getCurrency());
    569             break;
    570 
    571         default:
    572             *status = U_UNSUPPORTED_ERROR;
    573             return -1;
    574         }
    575     } else {
    576         const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
    577         U_ASSERT(rbnf != NULL);
    578         if (tag == UNUM_DEFAULT_RULESET) {
    579             res = rbnf->getDefaultRuleSetName();
    580         } else if (tag == UNUM_PUBLIC_RULESETS) {
    581             int32_t count = rbnf->getNumberOfRuleSetNames();
    582             for (int i = 0; i < count; ++i) {
    583                 res += rbnf->getRuleSetName(i);
    584                 res += (UChar)0x003b; // semicolon
    585             }
    586         } else {
    587             *status = U_UNSUPPORTED_ERROR;
    588             return -1;
    589         }
    590     }
    591 
    592     return res.extract(result, resultLength, *status);
    593 }
    594 
    595 U_CAPI void U_EXPORT2
    596 unum_setTextAttribute(    UNumberFormat*                    fmt,
    597             UNumberFormatTextAttribute      tag,
    598             const    UChar*                            newValue,
    599             int32_t                            newValueLength,
    600             UErrorCode                        *status)
    601 {
    602     if(U_FAILURE(*status))
    603         return;
    604 
    605     UnicodeString val(newValue, newValueLength);
    606     NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
    607     DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
    608     if (df != NULL) {
    609       switch(tag) {
    610       case UNUM_POSITIVE_PREFIX:
    611         df->setPositivePrefix(val);
    612         break;
    613 
    614       case UNUM_POSITIVE_SUFFIX:
    615         df->setPositiveSuffix(val);
    616         break;
    617 
    618       case UNUM_NEGATIVE_PREFIX:
    619         df->setNegativePrefix(val);
    620         break;
    621 
    622       case UNUM_NEGATIVE_SUFFIX:
    623         df->setNegativeSuffix(val);
    624         break;
    625 
    626       case UNUM_PADDING_CHARACTER:
    627         df->setPadCharacter(val);
    628         break;
    629 
    630       case UNUM_CURRENCY_CODE:
    631         df->setCurrency(val.getTerminatedBuffer(), *status);
    632         break;
    633 
    634       default:
    635         *status = U_UNSUPPORTED_ERROR;
    636         break;
    637       }
    638     } else {
    639       RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf);
    640       U_ASSERT(rbnf != NULL);
    641       if (tag == UNUM_DEFAULT_RULESET) {
    642         rbnf->setDefaultRuleSet(val, *status);
    643       } else {
    644         *status = U_UNSUPPORTED_ERROR;
    645       }
    646     }
    647 }
    648 
    649 U_CAPI int32_t U_EXPORT2
    650 unum_toPattern(    const    UNumberFormat*          fmt,
    651         UBool                  isPatternLocalized,
    652         UChar*                  result,
    653         int32_t                 resultLength,
    654         UErrorCode*             status)
    655 {
    656     if(U_FAILURE(*status))
    657         return -1;
    658 
    659     UnicodeString pat;
    660     if(!(result==NULL && resultLength==0)) {
    661         // NULL destination for pure preflighting: empty dummy string
    662         // otherwise, alias the destination buffer
    663         pat.setTo(result, 0, resultLength);
    664     }
    665 
    666     const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
    667     const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
    668     if (df != NULL) {
    669       if(isPatternLocalized)
    670         df->toLocalizedPattern(pat);
    671       else
    672         df->toPattern(pat);
    673     } else {
    674       const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
    675       U_ASSERT(rbnf != NULL);
    676       pat = rbnf->getRules();
    677     }
    678     return pat.extract(result, resultLength, *status);
    679 }
    680 
    681 U_CAPI int32_t U_EXPORT2
    682 unum_getSymbol(const UNumberFormat *fmt,
    683                UNumberFormatSymbol symbol,
    684                UChar *buffer,
    685                int32_t size,
    686                UErrorCode *status)
    687 {
    688     if(status==NULL || U_FAILURE(*status)) {
    689         return 0;
    690     }
    691     if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) {
    692         *status=U_ILLEGAL_ARGUMENT_ERROR;
    693         return 0;
    694     }
    695     const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt);
    696     const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf);
    697     if (dcf == NULL) {
    698       *status = U_UNSUPPORTED_ERROR;
    699       return 0;
    700     }
    701 
    702     return dcf->
    703       getDecimalFormatSymbols()->
    704         getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol).
    705           extract(buffer, size, *status);
    706 }
    707 
    708 U_CAPI void U_EXPORT2
    709 unum_setSymbol(UNumberFormat *fmt,
    710                UNumberFormatSymbol symbol,
    711                const UChar *value,
    712                int32_t length,
    713                UErrorCode *status)
    714 {
    715     if(status==NULL || U_FAILURE(*status)) {
    716         return;
    717     }
    718     if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) {
    719         *status=U_ILLEGAL_ARGUMENT_ERROR;
    720         return;
    721     }
    722     NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt);
    723     DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf);
    724     if (dcf == NULL) {
    725       *status = U_UNSUPPORTED_ERROR;
    726       return;
    727     }
    728 
    729     DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols());
    730     symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol,
    731         UnicodeString(value, length));  /* UnicodeString can handle the case when length = -1. */
    732     dcf->setDecimalFormatSymbols(symbols);
    733 }
    734 
    735 U_CAPI void U_EXPORT2
    736 unum_applyPattern(  UNumberFormat  *fmt,
    737                     UBool          localized,
    738                     const UChar    *pattern,
    739                     int32_t        patternLength,
    740                     UParseError    *parseError,
    741                     UErrorCode*    status)
    742 {
    743     UErrorCode tStatus = U_ZERO_ERROR;
    744     UParseError tParseError;
    745 
    746     if(parseError == NULL){
    747         parseError = &tParseError;
    748     }
    749 
    750     if(status==NULL){
    751         status = &tStatus;
    752     }
    753 
    754     int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
    755     const UnicodeString pat((UChar*)pattern, len, len);
    756 
    757     // Verify if the object passed is a DecimalFormat object
    758     NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
    759     DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
    760     if (df != NULL) {
    761       if(localized) {
    762         df->applyLocalizedPattern(pat,*parseError, *status);
    763       } else {
    764         df->applyPattern(pat,*parseError, *status);
    765       }
    766     } else {
    767       *status = U_UNSUPPORTED_ERROR;
    768       return;
    769     }
    770 }
    771 
    772 U_CAPI const char* U_EXPORT2
    773 unum_getLocaleByType(const UNumberFormat *fmt,
    774                      ULocDataLocaleType type,
    775                      UErrorCode* status)
    776 {
    777     if (fmt == NULL) {
    778         if (U_SUCCESS(*status)) {
    779             *status = U_ILLEGAL_ARGUMENT_ERROR;
    780         }
    781         return NULL;
    782     }
    783     return ((const Format*)fmt)->getLocaleID(type, *status);
    784 }
    785 
    786 #endif /* #if !UCONFIG_NO_FORMATTING */
    787