intl/icu/source/i18n/unum.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2 *******************************************************************************
     3 *   Copyright (C) 1996-2013, 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 */
    13 #include "unicode/utypes.h"
    15 #if !UCONFIG_NO_FORMATTING
    17 #include "unicode/unum.h"
    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"
    33 U_NAMESPACE_USE
    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     }
    47     NumberFormat *retVal = NULL;
    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;
    57     case UNUM_PATTERN_DECIMAL: {
    58         UParseError tErr;
    59         /* UnicodeString can handle the case when patternLength = -1. */
    60         const UnicodeString pat(pattern, patternLength);
    62         if(parseErr==NULL){
    63             parseErr = &tErr;
    64         }
    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         }
    76         retVal = new DecimalFormat(pat, syms, *parseErr, *status);
    77         if(retVal == NULL) {
    78             delete syms;
    79         }
    80     } break;
    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);
    88         if(parseErr==NULL){
    89             parseErr = &tErr;
    90         }
    92         retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status);
    93     } break;
    95     case UNUM_SPELLOUT:
    96         retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
    97         break;
    99     case UNUM_ORDINAL:
   100         retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status);
   101         break;
   103     case UNUM_DURATION:
   104         retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
   105         break;
   107     case UNUM_NUMBERING_SYSTEM:
   108         retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status);
   109         break;
   110 #endif
   112     default:
   113         *status = U_UNSUPPORTED_ERROR;
   114         return NULL;
   115     }
   117     if(retVal == NULL && U_SUCCESS(*status)) {
   118         *status = U_MEMORY_ALLOCATION_ERROR;
   119     }
   121     return reinterpret_cast<UNumberFormat *>(retVal);
   122 }
   124 U_CAPI void U_EXPORT2
   125 unum_close(UNumberFormat* fmt)
   126 {
   127     delete (NumberFormat*) fmt;
   128 }
   130 U_CAPI UNumberFormat* U_EXPORT2
   131 unum_clone(const UNumberFormat *fmt,
   132        UErrorCode *status)
   133 {
   134     if(U_FAILURE(*status))
   135         return 0;
   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     }
   148     if(res == 0) {
   149         *status = U_MEMORY_ALLOCATION_ERROR;
   150         return 0;
   151     }
   153     return (UNumberFormat*) res;
   154 }
   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 }
   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;
   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     }
   185     FieldPosition fp;
   187     if(pos != 0)
   188         fp.setField(pos->field);
   190     ((const NumberFormat*)fmt)->format(number, res, fp, *status);
   192     if(pos != 0) {
   193         pos->beginIndex = fp.getBeginIndex();
   194         pos->endIndex = fp.getEndIndex();
   195     }
   197     return res.extract(result, resultLength, *status);
   198 }
   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 {
   209   if(U_FAILURE(*status)) return -1;
   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   }
   218   FieldPosition fp;
   220   if(pos != 0)
   221     fp.setField(pos->field);
   223   ((const NumberFormat*)fmt)->format(number, res, fp, *status);
   225   if(pos != 0) {
   226     pos->beginIndex = fp.getBeginIndex();
   227     pos->endIndex = fp.getEndIndex();
   228   }
   230   return res.extract(result, resultLength, *status);
   231 }
   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) {
   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     }
   251     FieldPosition fp;
   252     if(pos != 0) {
   253         fp.setField(pos->field);
   254     }
   256     if (length < 0) {
   257         length = uprv_strlen(number);
   258     }
   259     StringPiece numSP(number, length);
   260     Formattable numFmtbl(numSP, *status);
   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 }
   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;
   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     }
   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);
   308     if (pos != 0) {
   309         pos->beginIndex = fp.getBeginIndex();
   310         pos->endIndex = fp.getEndIndex();
   311     }
   313     return res.extract(result, resultLength, *status);
   314 }
   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;
   327     const UnicodeString src((UBool)(textLength == -1), text, textLength);
   328     ParsePosition pp;
   330     if(parsePos != 0)
   331         pp.setIndex(*parsePos);
   333     ((const NumberFormat*)fmt)->parse(src, res, pp);
   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 }
   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 }
   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 }
   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 }
   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 }
   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 }
   450 U_CAPI const char* U_EXPORT2
   451 unum_getAvailable(int32_t index)
   452 {
   453     return uloc_getAvailable(index);
   454 }
   456 U_CAPI int32_t U_EXPORT2
   457 unum_countAvailable()
   458 {
   459     return uloc_countAvailable();
   460 }
   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   }
   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   }
   479   return -1;
   480 }
   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 }
   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 }
   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 }
   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;
   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     }
   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;
   551         case UNUM_POSITIVE_SUFFIX:
   552             df->getPositiveSuffix(res);
   553             break;
   555         case UNUM_NEGATIVE_PREFIX:
   556             df->getNegativePrefix(res);
   557             break;
   559         case UNUM_NEGATIVE_SUFFIX:
   560             df->getNegativeSuffix(res);
   561             break;
   563         case UNUM_PADDING_CHARACTER:
   564             res = df->getPadCharacterString();
   565             break;
   567         case UNUM_CURRENCY_CODE:
   568             res = UnicodeString(df->getCurrency());
   569             break;
   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     }
   592     return res.extract(result, resultLength, *status);
   593 }
   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;
   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;
   614       case UNUM_POSITIVE_SUFFIX:
   615         df->setPositiveSuffix(val);
   616         break;
   618       case UNUM_NEGATIVE_PREFIX:
   619         df->setNegativePrefix(val);
   620         break;
   622       case UNUM_NEGATIVE_SUFFIX:
   623         df->setNegativeSuffix(val);
   624         break;
   626       case UNUM_PADDING_CHARACTER:
   627         df->setPadCharacter(val);
   628         break;
   630       case UNUM_CURRENCY_CODE:
   631         df->setCurrency(val.getTerminatedBuffer(), *status);
   632         break;
   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 }
   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;
   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     }
   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 }
   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     }
   702     return dcf->
   703       getDecimalFormatSymbols()->
   704         getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol).
   705           extract(buffer, size, *status);
   706 }
   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     }
   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 }
   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;
   746     if(parseError == NULL){
   747         parseError = &tParseError;
   748     }
   750     if(status==NULL){
   751         status = &tStatus;
   752     }
   754     int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
   755     const UnicodeString pat((UChar*)pattern, len, len);
   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 }
   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 }
   786 U_INTERNAL UFormattable * U_EXPORT2
   787 unum_parseToUFormattable(const UNumberFormat* fmt,
   788                          UFormattable *result,
   789                          const UChar* text,
   790                          int32_t textLength,
   791                          int32_t* parsePos, /* 0 = start */
   792                          UErrorCode* status) {
   793   UFormattable *newFormattable = NULL;
   794   if (U_FAILURE(*status)) return result;
   795   if (fmt == NULL || (text==NULL && textLength!=0)) {
   796     *status = U_ILLEGAL_ARGUMENT_ERROR;
   797     return result;
   798   }
   799   if (result == NULL) { // allocate if not allocated.
   800     newFormattable = result = ufmt_open(status);
   801   }
   802   parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status);
   803   if (U_FAILURE(*status) && newFormattable != NULL) {
   804     ufmt_close(newFormattable);
   805     result = NULL; // deallocate if there was a parse error
   806   }
   807   return result;
   808 }
   810 U_INTERNAL int32_t U_EXPORT2
   811 unum_formatUFormattable(const UNumberFormat* fmt,
   812                         const UFormattable *number,
   813                         UChar *result,
   814                         int32_t resultLength,
   815                         UFieldPosition *pos, /* ignored if 0 */
   816                         UErrorCode *status) {
   817     if (U_FAILURE(*status)) {
   818       return 0;
   819     }
   820     if (fmt == NULL || number==NULL ||
   821         (result==NULL ? resultLength!=0 : resultLength<0)) {
   822       *status = U_ILLEGAL_ARGUMENT_ERROR;
   823       return 0;
   824     }
   825     UnicodeString res(result, 0, resultLength);
   827     FieldPosition fp;
   829     if(pos != 0)
   830         fp.setField(pos->field);
   832     ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status);
   834     if(pos != 0) {
   835         pos->beginIndex = fp.getBeginIndex();
   836         pos->endIndex = fp.getEndIndex();
   837     }
   839     return res.extract(result, resultLength, *status);
   840 }
   842 #endif /* #if !UCONFIG_NO_FORMATTING */

mercurial