]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/unum.cpp
ICU-64252.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / unum.cpp
index ac2641185f1e4cb4ee6ef2564b761c954245f2ad..c2bd548879cecb30844bc7a965d44b3afcf3bc8a 100644 (file)
@@ -1,6 +1,8 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /*
 *******************************************************************************
-*   Copyright (C) 1996-2010, International Business Machines
+*   Copyright (C) 1996-2015, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *******************************************************************************
 * Modification History:
 #include "unicode/numfmt.h"
 #include "unicode/decimfmt.h"
 #include "unicode/rbnf.h"
+#include "unicode/compactdecimalformat.h"
 #include "unicode/ustring.h"
 #include "unicode/fmtable.h"
 #include "unicode/dcfmtsym.h"
 #include "unicode/curramt.h"
+#include "unicode/localpointer.h"
+#include "unicode/udisplaycontext.h"
 #include "uassert.h"
 #include "cpputils.h"
 #include "cstring.h"
@@ -38,78 +43,50 @@ unum_open(  UNumberFormatStyle    style,
             int32_t            patternLength,
             const    char*     locale,
             UParseError*       parseErr,
-            UErrorCode*        status)
-{
-
-    if(U_FAILURE(*status))
-    {
-        return 0;
+            UErrorCode*        status) {
+    if(U_FAILURE(*status)) {
+        return NULL;
     }
 
-    UNumberFormat *retVal = 0;
+    NumberFormat *retVal = NULL;
 
     switch(style) {
     case UNUM_DECIMAL:
-        if(locale == 0)
-            retVal = (UNumberFormat*)NumberFormat::createInstance(*status);
-        else
-            retVal = (UNumberFormat*)NumberFormat::createInstance(Locale(locale),
-            *status);
-        break;
-
     case UNUM_CURRENCY:
-        if(locale == 0)
-            retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(*status);
-        else
-            retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(Locale(locale),
-            *status);
-        break;
-
     case UNUM_PERCENT:
-        if(locale == 0)
-            retVal = (UNumberFormat*)NumberFormat::createPercentInstance(*status);
-        else
-            retVal = (UNumberFormat*)NumberFormat::createPercentInstance(Locale(locale),
-            *status);
-        break;
-
     case UNUM_SCIENTIFIC:
-        if(locale == 0)
-            retVal = (UNumberFormat*)NumberFormat::createScientificInstance(*status);
-        else
-            retVal = (UNumberFormat*)NumberFormat::createScientificInstance(Locale(locale),
-            *status);
+    case UNUM_CURRENCY_ISO:
+    case UNUM_CURRENCY_PLURAL:
+    case UNUM_CURRENCY_ACCOUNTING:
+    case UNUM_CASH_CURRENCY:
+    case UNUM_CURRENCY_STANDARD:
+        retVal = NumberFormat::createInstance(Locale(locale), style, *status);
         break;
 
     case UNUM_PATTERN_DECIMAL: {
         UParseError tErr;
         /* UnicodeString can handle the case when patternLength = -1. */
         const UnicodeString pat(pattern, patternLength);
-        DecimalFormatSymbols *syms = 0;
 
         if(parseErr==NULL){
             parseErr = &tErr;
         }
 
-        if(locale == 0)
-            syms = new DecimalFormatSymbols(*status);
-        else
-            syms = new DecimalFormatSymbols(Locale(locale), *status);
-
-        if(syms == 0) {
+        DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status);
+        if(syms == NULL) {
             *status = U_MEMORY_ALLOCATION_ERROR;
-            return 0;
+            return NULL;
         }
         if (U_FAILURE(*status)) {
             delete syms;
-            return 0;
+            return NULL;
         }
 
-        retVal = (UNumberFormat*)new DecimalFormat(pat, syms, *parseErr, *status);
-        if(retVal == 0) {
+        retVal = new DecimalFormat(pat, syms, *parseErr, *status);
+        if(retVal == NULL) {
             delete syms;
         }
-                               } break;
+    } break;
 
 #if U_HAVE_RBNF
     case UNUM_PATTERN_RULEBASED: {
@@ -121,36 +98,44 @@ unum_open(  UNumberFormatStyle    style,
             parseErr = &tErr;
         }
         
-        retVal = (UNumberFormat*)new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status);
+        retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status);
     } break;
 
     case UNUM_SPELLOUT:
-        retVal = (UNumberFormat*)new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
+        retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
         break;
 
     case UNUM_ORDINAL:
-        retVal = (UNumberFormat*)new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status);
+        retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status);
         break;
 
     case UNUM_DURATION:
-        retVal = (UNumberFormat*)new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
+        retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
         break;
 
     case UNUM_NUMBERING_SYSTEM:
-        retVal = (UNumberFormat*)new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status);
+        retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status);
         break;
 #endif
 
+    case UNUM_DECIMAL_COMPACT_SHORT:
+        retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_SHORT, *status);
+        break;
+
+    case UNUM_DECIMAL_COMPACT_LONG:
+        retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_LONG, *status);
+        break;
+
     default:
         *status = U_UNSUPPORTED_ERROR;
-        return 0;
+        return NULL;
     }
 
-    if(retVal == 0 && U_SUCCESS(*status)) {
+    if(retVal == NULL && U_SUCCESS(*status)) {
         *status = U_MEMORY_ALLOCATION_ERROR;
     }
 
-    return retVal;
+    return reinterpret_cast<UNumberFormat *>(retVal);
 }
 
 U_CAPI void U_EXPORT2
@@ -219,8 +204,13 @@ unum_formatInt64(const UNumberFormat* fmt,
     if(pos != 0)
         fp.setField(pos->field);
     
-    ((const NumberFormat*)fmt)->format(number, res, fp);
-    
+    const CompactDecimalFormat* cdf = dynamic_cast<const CompactDecimalFormat*>((const NumberFormat*)fmt);
+    if (cdf != NULL) {
+        cdf->format(number, res, fp); // CompactDecimalFormat does not override the version with UErrorCode& !!
+    } else {
+        ((const NumberFormat*)fmt)->format(number, res, fp, *status);
+    }
+
     if(pos != 0) {
         pos->beginIndex = fp.getBeginIndex();
         pos->endIndex = fp.getEndIndex();
@@ -252,7 +242,12 @@ unum_formatDouble(    const    UNumberFormat*  fmt,
   if(pos != 0)
     fp.setField(pos->field);
   
-  ((const NumberFormat*)fmt)->format(number, res, fp);
+  const CompactDecimalFormat* cdf = dynamic_cast<const CompactDecimalFormat*>((const NumberFormat*)fmt);
+  if (cdf != NULL) {
+      cdf->format(number, res, fp); // CompactDecimalFormat does not override the version with UErrorCode& !!
+  } else {
+      ((const NumberFormat*)fmt)->format(number, res, fp, *status);
+  }
   
   if(pos != 0) {
     pos->beginIndex = fp.getBeginIndex();
@@ -262,8 +257,35 @@ unum_formatDouble(    const    UNumberFormat*  fmt,
   return res.extract(result, resultLength, *status);
 }
 
+U_CAPI int32_t U_EXPORT2
+unum_formatDoubleForFields(const UNumberFormat* format,
+                           double number,
+                           UChar* result,
+                           int32_t resultLength,
+                           UFieldPositionIterator* fpositer,
+                           UErrorCode* status)
+{
+    if (U_FAILURE(*status))
+        return -1;
+
+    if (result == NULL ? resultLength != 0 : resultLength < 0) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return -1;
+    }
+
+    UnicodeString res;
+    if (result != NULL) {
+        // NULL destination for pure preflighting: empty dummy string
+        // otherwise, alias the destination buffer
+        res.setTo(result, 0, resultLength);
+    }
+
+    ((const NumberFormat*)format)->format(number, res, (FieldPositionIterator*)fpositer, *status);
+
+    return res.extract(result, resultLength, *status);
+}
 
-U_DRAFT int32_t U_EXPORT2 
+U_CAPI int32_t U_EXPORT2 
 unum_formatDecimal(const    UNumberFormat*  fmt,
             const char *    number,
             int32_t         length,
@@ -286,7 +308,7 @@ unum_formatDecimal(const    UNumberFormat*  fmt,
     }
 
     if (length < 0) {
-        length = uprv_strlen(number);
+        length = static_cast<int32_t>(uprv_strlen(number));
     }
     StringPiece numSP(number, length);
     Formattable numFmtbl(numSP, *status);
@@ -351,24 +373,18 @@ parseRes(Formattable& res,
          const   UChar*          text,
          int32_t         textLength,
          int32_t         *parsePos /* 0 = start */,
-         UBool parseCurrency,
          UErrorCode      *status)
 {
     if(U_FAILURE(*status))
         return;
     
-    int32_t len = (textLength == -1 ? u_strlen(text) : textLength);
-    const UnicodeString src((UChar*)text, len, len);
+    const UnicodeString src((UBool)(textLength == -1), text, textLength);
     ParsePosition pp;
     
     if(parsePos != 0)
         pp.setIndex(*parsePos);
     
-    if (parseCurrency) {
-        ((const NumberFormat*)fmt)->parseCurrency(src, res, pp);
-    } else {
-        ((const NumberFormat*)fmt)->parse(src, res, pp);
-    }
+    ((const NumberFormat*)fmt)->parse(src, res, pp);
     
     if(pp.getErrorIndex() != -1) {
         *status = U_PARSE_ERROR;
@@ -388,7 +404,7 @@ unum_parse(    const   UNumberFormat*  fmt,
         UErrorCode      *status)
 {
     Formattable res;
-    parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
+    parseRes(res, fmt, text, textLength, parsePos, status);
     return res.getLong(*status);
 }
 
@@ -400,7 +416,7 @@ unum_parseInt64(    const   UNumberFormat*  fmt,
         UErrorCode      *status)
 {
     Formattable res;
-    parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
+    parseRes(res, fmt, text, textLength, parsePos, status);
     return res.getInt64(*status);
 }
 
@@ -412,7 +428,7 @@ unum_parseDouble(    const   UNumberFormat*  fmt,
             UErrorCode      *status)
 {
     Formattable res;
-    parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
+    parseRes(res, fmt, text, textLength, parsePos, status);
     return res.getDouble(*status);
 }
 
@@ -433,7 +449,7 @@ unum_parseDecimal(const UNumberFormat*  fmt,
         return -1;
     }
     Formattable res;
-    parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
+    parseRes(res, fmt, text, textLength, parsePos, status);
     StringPiece sp = res.getDecimalNumber(*status);
     if (U_FAILURE(*status)) {
        return -1;
@@ -443,6 +459,7 @@ unum_parseDecimal(const UNumberFormat*  fmt,
         uprv_strncpy(outBuf, sp.data(), sp.size());
         *status = U_STRING_NOT_TERMINATED_WARNING;
     } else {
+        U_ASSERT(outBufLength > 0);
         uprv_strcpy(outBuf, sp.data());
     }
     return sp.size();
@@ -455,15 +472,33 @@ unum_parseDoubleCurrency(const UNumberFormat* fmt,
                          int32_t* parsePos, /* 0 = start */
                          UChar* currency,
                          UErrorCode* status) {
-    Formattable res;
-    parseRes(res, fmt, text, textLength, parsePos, TRUE, status);
+    double doubleVal = 0.0;
     currency[0] = 0;
-    const CurrencyAmount* c;
-    if (res.getType() == Formattable::kObject &&
-        (c = dynamic_cast<const CurrencyAmount*>(res.getObject())) != NULL) {
-        u_strcpy(currency, c->getISOCurrency());
+    if (U_FAILURE(*status)) {
+        return doubleVal;
     }
-    return res.getDouble(*status);
+    const UnicodeString src((UBool)(textLength == -1), text, textLength);
+    ParsePosition pp;
+    if (parsePos != NULL) {
+        pp.setIndex(*parsePos);
+    }
+    *status = U_PARSE_ERROR; // assume failure, reset if succeed
+    LocalPointer<CurrencyAmount> currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp));
+    if (pp.getErrorIndex() != -1) {
+        if (parsePos != NULL) {
+            *parsePos = pp.getErrorIndex();
+        }
+    } else {
+        if (parsePos != NULL) {
+            *parsePos = pp.getIndex();
+        }
+        if (pp.getIndex() > 0) {
+            *status = U_ZERO_ERROR;
+            u_strcpy(currency, currAmt->getISOCurrency());
+            doubleVal = currAmt->getNumber().getDouble(*status);
+        }
+    }
+    return doubleVal;
 }
 
 U_CAPI const char* U_EXPORT2
@@ -482,84 +517,43 @@ U_CAPI int32_t U_EXPORT2
 unum_getAttribute(const UNumberFormat*          fmt,
           UNumberFormatAttribute  attr)
 {
-  const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
-  const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
-  if (df != NULL) {
-    switch(attr) {
-    case UNUM_PARSE_INT_ONLY:
-        return df->isParseIntegerOnly();
-        
-    case UNUM_GROUPING_USED:
-        return df->isGroupingUsed();
-        
-    case UNUM_DECIMAL_ALWAYS_SHOWN:
-        return df->isDecimalSeparatorAlwaysShown();    
-        
-    case UNUM_MAX_INTEGER_DIGITS:
-        return df->getMaximumIntegerDigits();
-        
-    case UNUM_MIN_INTEGER_DIGITS:
-        return df->getMinimumIntegerDigits();
-        
-    case UNUM_INTEGER_DIGITS:
-        // TBD: what should this return?
-        return df->getMinimumIntegerDigits();
-        
-    case UNUM_MAX_FRACTION_DIGITS:
-        return df->getMaximumFractionDigits();
-        
-    case UNUM_MIN_FRACTION_DIGITS:
-        return df->getMinimumFractionDigits();
-        
-    case UNUM_FRACTION_DIGITS:
-        // TBD: what should this return?
-        return df->getMinimumFractionDigits();
-        
-    case UNUM_SIGNIFICANT_DIGITS_USED:
-        return df->areSignificantDigitsUsed();
-        
-    case UNUM_MAX_SIGNIFICANT_DIGITS:
-        return df->getMaximumSignificantDigits();
-        
-    case UNUM_MIN_SIGNIFICANT_DIGITS:
-        return df->getMinimumSignificantDigits();
-        
-    case UNUM_MULTIPLIER:
-        return df->getMultiplier();    
-        
-    case UNUM_GROUPING_SIZE:
-        return df->getGroupingSize();    
-        
-    case UNUM_ROUNDING_MODE:
-        return df->getRoundingMode();
-        
-    case UNUM_FORMAT_WIDTH:
-        return df->getFormatWidth();
-        
-    case UNUM_PADDING_POSITION:
-        return df->getPadPosition();
-        
-    case UNUM_SECONDARY_GROUPING_SIZE:
-        return df->getSecondaryGroupingSize();
-
-    case UNUM_LENIENT_PARSE:
-       return ! df->isParseStrict();
-
-    default:
-        /* enums out of sync? unsupported enum? */
-        break;
-    }
-  } else {
-    const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
-    U_ASSERT(rbnf != NULL);
+    const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
     if (attr == UNUM_LENIENT_PARSE) {
-#if !UCONFIG_NO_COLLATION
-      return rbnf->isLenient();
-#endif
+        // Supported for all subclasses
+        return nf->isLenient();
+    }
+    else if (attr == UNUM_MAX_INTEGER_DIGITS) {
+        return nf->getMaximumIntegerDigits();
+    }
+    else if (attr == UNUM_MIN_INTEGER_DIGITS) {
+        return nf->getMinimumIntegerDigits();
+    }
+    else if (attr == UNUM_INTEGER_DIGITS) {
+        // TODO: what should this return?
+        return nf->getMinimumIntegerDigits();
+    }
+    else if (attr == UNUM_MAX_FRACTION_DIGITS) {
+        return nf->getMaximumFractionDigits();
+    }
+    else if (attr == UNUM_MIN_FRACTION_DIGITS) {
+        return nf->getMinimumFractionDigits();
+    }
+    else if (attr == UNUM_FRACTION_DIGITS) {
+        // TODO: what should this return?
+        return nf->getMinimumFractionDigits();
+    }
+    else if (attr == UNUM_ROUNDING_MODE) {
+        return nf->getRoundingMode();
+    }
+
+    // The remaining attributes are only supported for DecimalFormat
+    const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
+    if (df != NULL) {
+        UErrorCode ignoredStatus = U_ZERO_ERROR;
+        return df->getAttribute(attr, ignoredStatus);
     }
-  }
 
-  return -1;
+    return -1;
 }
 
 U_CAPI void U_EXPORT2
@@ -567,102 +561,42 @@ unum_setAttribute(    UNumberFormat*          fmt,
             UNumberFormatAttribute  attr,
             int32_t                 newValue)
 {
-  NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
-  DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
-  if (df != NULL) {
-    switch(attr) {
-    case UNUM_PARSE_INT_ONLY:
-        df->setParseIntegerOnly(newValue!=0);
-        break;
-        
-    case UNUM_GROUPING_USED:
-        df->setGroupingUsed(newValue!=0);
-        break;
-        
-    case UNUM_DECIMAL_ALWAYS_SHOWN:
-        df->setDecimalSeparatorAlwaysShown(newValue!=0);
-        break;
-        
-    case UNUM_MAX_INTEGER_DIGITS:
-        df->setMaximumIntegerDigits(newValue);
-        break;
-        
-    case UNUM_MIN_INTEGER_DIGITS:
-        df->setMinimumIntegerDigits(newValue);
-        break;
-        
-    case UNUM_INTEGER_DIGITS:
-        df->setMinimumIntegerDigits(newValue);
-        df->setMaximumIntegerDigits(newValue);
-        break;
-        
-    case UNUM_MAX_FRACTION_DIGITS:
-        df->setMaximumFractionDigits(newValue);
-        break;
-        
-    case UNUM_MIN_FRACTION_DIGITS:
-        df->setMinimumFractionDigits(newValue);
-        break;
-        
-    case UNUM_FRACTION_DIGITS:
-        df->setMinimumFractionDigits(newValue);
-        df->setMaximumFractionDigits(newValue);
-        break;
-        
-    case UNUM_SIGNIFICANT_DIGITS_USED:
-        df->setSignificantDigitsUsed(newValue!=0);
-        break;
-
-    case UNUM_MAX_SIGNIFICANT_DIGITS:
-        df->setMaximumSignificantDigits(newValue);
-        break;
-        
-    case UNUM_MIN_SIGNIFICANT_DIGITS:
-        df->setMinimumSignificantDigits(newValue);
-        break;
-        
-    case UNUM_MULTIPLIER:
-        df->setMultiplier(newValue);    
-        break;
-        
-    case UNUM_GROUPING_SIZE:
-        df->setGroupingSize(newValue);    
-        break;
-        
-    case UNUM_ROUNDING_MODE:
-        df->setRoundingMode((DecimalFormat::ERoundingMode)newValue);
-        break;
-        
-    case UNUM_FORMAT_WIDTH:
-        df->setFormatWidth(newValue);
-        break;
-        
-    case UNUM_PADDING_POSITION:
-        /** The position at which padding will take place. */
-        df->setPadPosition((DecimalFormat::EPadPosition)newValue);
-        break;
-        
-    case UNUM_SECONDARY_GROUPING_SIZE:
-        df->setSecondaryGroupingSize(newValue);
-        break;
-
-    case UNUM_LENIENT_PARSE:
-       df->setParseStrict(newValue == 0);
-       break;
-
-    default:
-        /* Shouldn't get here anyway */
-        break;
-    }
-  } else {
-    RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf);
-    U_ASSERT(rbnf != NULL);
+    NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
     if (attr == UNUM_LENIENT_PARSE) {
-#if !UCONFIG_NO_COLLATION
-      rbnf->setLenient((UBool)newValue);
-#endif
+        // Supported for all subclasses
+        // keep this here as the class may not be a DecimalFormat
+        return nf->setLenient(newValue != 0);
+    }
+    else if (attr == UNUM_MAX_INTEGER_DIGITS) {
+        return nf->setMaximumIntegerDigits(newValue);
+    }
+    else if (attr == UNUM_MIN_INTEGER_DIGITS) {
+        return nf->setMinimumIntegerDigits(newValue);
+    }
+    else if (attr == UNUM_INTEGER_DIGITS) {
+        nf->setMinimumIntegerDigits(newValue);
+        return nf->setMaximumIntegerDigits(newValue);
+    }
+    else if (attr == UNUM_MAX_FRACTION_DIGITS) {
+        return nf->setMaximumFractionDigits(newValue);
+    }
+    else if (attr == UNUM_MIN_FRACTION_DIGITS) {
+        return nf->setMinimumFractionDigits(newValue);
+    }
+    else if (attr == UNUM_FRACTION_DIGITS) {
+        nf->setMinimumFractionDigits(newValue);
+        return nf->setMaximumFractionDigits(newValue);
+    }
+    else if (attr == UNUM_ROUNDING_MODE) {
+        return nf->setRoundingMode((NumberFormat::ERoundingMode)newValue);
+    }
+
+    // The remaining attributes are only supported for DecimalFormat
+    DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
+    if (df != NULL) {
+        UErrorCode ignoredStatus = U_ZERO_ERROR;
+        df->setAttribute(attr, newValue, ignoredStatus);
     }
-  }
 }
 
 U_CAPI double U_EXPORT2
@@ -769,8 +703,7 @@ unum_setTextAttribute(    UNumberFormat*                    fmt,
     if(U_FAILURE(*status))
         return;
 
-    int32_t len = (newValueLength == -1 ? u_strlen(newValue) : newValueLength);
-    const UnicodeString val((UChar*)newValue, len, len);
+    UnicodeString val(newValue, newValueLength);
     NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
     DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
     if (df != NULL) {
@@ -792,11 +725,11 @@ unum_setTextAttribute(    UNumberFormat*                    fmt,
         break;
         
       case UNUM_PADDING_CHARACTER:
-        df->setPadCharacter(*newValue);
+        df->setPadCharacter(val);
         break;
         
       case UNUM_CURRENCY_CODE:
-        df->setCurrency(newValue, *status);
+        df->setCurrency(val.getTerminatedBuffer(), *status);
         break;
         
       default:
@@ -807,7 +740,7 @@ unum_setTextAttribute(    UNumberFormat*                    fmt,
       RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf);
       U_ASSERT(rbnf != NULL);
       if (tag == UNUM_DEFAULT_RULESET) {
-        rbnf->setDefaultRuleSet(newValue, *status);
+        rbnf->setDefaultRuleSet(val, *status);
       } else {
         *status = U_UNSUPPORTED_ERROR;
       }
@@ -856,7 +789,7 @@ unum_getSymbol(const UNumberFormat *fmt,
     if(status==NULL || U_FAILURE(*status)) {
         return 0;
     }
-    if(fmt==NULL || (uint16_t)symbol>=UNUM_FORMAT_SYMBOL_COUNT) {
+    if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) {
         *status=U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
     }
@@ -883,7 +816,7 @@ unum_setSymbol(UNumberFormat *fmt,
     if(status==NULL || U_FAILURE(*status)) {
         return;
     }
-    if(fmt==NULL || (uint16_t)symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) {
+    if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) {
         *status=U_ILLEGAL_ARGUMENT_ERROR;
         return;
     }
@@ -951,4 +884,79 @@ unum_getLocaleByType(const UNumberFormat *fmt,
     return ((const Format*)fmt)->getLocaleID(type, *status);
 }
 
+U_CAPI void U_EXPORT2
+unum_setContext(UNumberFormat* fmt, UDisplayContext value, UErrorCode* status)
+{
+    if (U_FAILURE(*status)) {
+        return;
+    }
+    ((NumberFormat*)fmt)->setContext(value, *status);
+    return;
+}
+
+U_CAPI UDisplayContext U_EXPORT2
+unum_getContext(const UNumberFormat *fmt, UDisplayContextType type, UErrorCode* status)
+{
+    if (U_FAILURE(*status)) {
+        return (UDisplayContext)0;
+    }
+    return ((const NumberFormat*)fmt)->getContext(type, *status);
+}
+
+U_INTERNAL UFormattable * U_EXPORT2
+unum_parseToUFormattable(const UNumberFormat* fmt,
+                         UFormattable *result,
+                         const UChar* text,
+                         int32_t textLength,
+                         int32_t* parsePos, /* 0 = start */
+                         UErrorCode* status) {
+  UFormattable *newFormattable = NULL;
+  if (U_FAILURE(*status)) return result;
+  if (fmt == NULL || (text==NULL && textLength!=0)) {
+    *status = U_ILLEGAL_ARGUMENT_ERROR;
+    return result;
+  }
+  if (result == NULL) { // allocate if not allocated.
+    newFormattable = result = ufmt_open(status);
+  }
+  parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status);
+  if (U_FAILURE(*status) && newFormattable != NULL) {
+    ufmt_close(newFormattable);
+    result = NULL; // deallocate if there was a parse error
+  }
+  return result;
+}
+
+U_INTERNAL int32_t U_EXPORT2
+unum_formatUFormattable(const UNumberFormat* fmt,
+                        const UFormattable *number,
+                        UChar *result,
+                        int32_t resultLength,
+                        UFieldPosition *pos, /* ignored if 0 */
+                        UErrorCode *status) {
+    if (U_FAILURE(*status)) {
+      return 0;
+    }
+    if (fmt == NULL || number==NULL ||
+        (result==NULL ? resultLength!=0 : resultLength<0)) {
+      *status = U_ILLEGAL_ARGUMENT_ERROR;
+      return 0;
+    }
+    UnicodeString res(result, 0, resultLength);
+
+    FieldPosition fp;
+
+    if(pos != 0)
+        fp.setField(pos->field);
+
+    ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status);
+
+    if(pos != 0) {
+        pos->beginIndex = fp.getBeginIndex();
+        pos->endIndex = fp.getEndIndex();
+    }
+
+    return res.extract(result, resultLength, *status);
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */