]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/unum.cpp
ICU-64260.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / unum.cpp
index e39ac880a1ec0c6ab7798128e64e1afe154842ed..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-2003, 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"
-U_NAMESPACE_USE
-/*
-U_CAPI UNumberFormat*
-unum_open(    UNumberFormatStyle    style,
-        const   char*        locale,
-        UErrorCode*        status)
-{
-  if(U_FAILURE(*status))
-    return 0;
-  UNumberFormat *retVal = 0;
-  
-  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_SPELLOUT:
-    // Todo: TBD: Add spellout support
-    //retVal = (UNumberFormat*)new NumberSpelloutFormat();
-    //break;
-    *status = U_UNSUPPORTED_ERROR;
-    return 0;
-
-  default:
-    *status = U_UNSUPPORTED_ERROR;
-    return 0;
-  }
+#include "cstring.h"
 
-  if(retVal == 0) {
-    *status = U_MEMORY_ALLOCATION_ERROR;
-    return 0;
-  }
 
-  return retVal;
-}
-
-U_CAPI UNumberFormat*
-unum_openPattern(    const    UChar*            pattern,
-            int32_t            patternLength,
-            const    char*        locale,
-            UErrorCode*        status)
-{
-    UParseError parseError;
-    return unum_openPatternWithError( pattern,patternLength,locale,&parseError,status);
-}*/
+U_NAMESPACE_USE
 
 
 U_CAPI UNumberFormat* U_EXPORT2
@@ -97,155 +43,180 @@ unum_open(  UNumberFormatStyle    style,
             int32_t            patternLength,
             const    char*     locale,
             UParseError*       parseErr,
-            UErrorCode*        status)
-{
+            UErrorCode*        status) {
+    if(U_FAILURE(*status)) {
+        return NULL;
+    }
 
-  if(U_FAILURE(*status))
-  { 
-      return 0;
-  }
-  if(style!=UNUM_IGNORE){
-       UNumberFormat *retVal = 0;
-  
-      switch(style) {
-      case UNUM_DECIMAL:
-        if(locale == 0)
-          retVal = (UNumberFormat*)NumberFormat::createInstance(*status);
-        else
-          retVal = (UNumberFormat*)NumberFormat::createInstance(Locale(locale),
-                                    *status);
+    NumberFormat *retVal = NULL;
+
+    switch(style) {
+    case UNUM_DECIMAL:
+    case UNUM_CURRENCY:
+    case UNUM_PERCENT:
+    case UNUM_SCIENTIFIC:
+    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_CURRENCY:
-        if(locale == 0)
-          retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(*status);
-        else
-          retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(Locale(locale),
-                                        *status);
+    case UNUM_PATTERN_DECIMAL: {
+        UParseError tErr;
+        /* UnicodeString can handle the case when patternLength = -1. */
+        const UnicodeString pat(pattern, patternLength);
+
+        if(parseErr==NULL){
+            parseErr = &tErr;
+        }
+
+        DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status);
+        if(syms == NULL) {
+            *status = U_MEMORY_ALLOCATION_ERROR;
+            return NULL;
+        }
+        if (U_FAILURE(*status)) {
+            delete syms;
+            return NULL;
+        }
+
+        retVal = new DecimalFormat(pat, syms, *parseErr, *status);
+        if(retVal == NULL) {
+            delete syms;
+        }
+    } break;
+
+#if U_HAVE_RBNF
+    case UNUM_PATTERN_RULEBASED: {
+        UParseError tErr;
+        /* UnicodeString can handle the case when patternLength = -1. */
+        const UnicodeString pat(pattern, patternLength);
+        
+        if(parseErr==NULL){
+            parseErr = &tErr;
+        }
+        
+        retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status);
+    } break;
+
+    case UNUM_SPELLOUT:
+        retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
         break;
 
-      case UNUM_PERCENT:
-        if(locale == 0)
-          retVal = (UNumberFormat*)NumberFormat::createPercentInstance(*status);
-        else
-          retVal = (UNumberFormat*)NumberFormat::createPercentInstance(Locale(locale),
-                                    *status);
+    case UNUM_ORDINAL:
+        retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, 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_DURATION:
+        retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
         break;
 
-      case UNUM_SPELLOUT:
-#if U_HAVE_RBNF
-        return (UNumberFormat*)new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
-#else
-        // fall through
+    case UNUM_NUMBERING_SYSTEM:
+        retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status);
+        break;
 #endif
-      default:
-        *status = U_UNSUPPORTED_ERROR;
-        return 0;
-      }
 
-      if(retVal == 0) {
-        *status = U_MEMORY_ALLOCATION_ERROR;
-        return 0;
-      }
+    case UNUM_DECIMAL_COMPACT_SHORT:
+        retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_SHORT, *status);
+        break;
 
-      return retVal;
-  }else{
-      /* we don't support RBNF patterns yet */
-      UParseError tErr;
-      int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
-      const UnicodeString pat((UChar*)pattern, len, len);
-      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) {
-        *status = U_MEMORY_ALLOCATION_ERROR;
-        return 0;
-      }
+    case UNUM_DECIMAL_COMPACT_LONG:
+        retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_LONG, *status);
+        break;
+
+    default:
+        *status = U_UNSUPPORTED_ERROR;
+        return NULL;
+    }
 
-      DecimalFormat *fmt = 0;
-      fmt = new DecimalFormat(pat, syms, *parseErr, *status);
-      if(fmt == 0) {
+    if(retVal == NULL && U_SUCCESS(*status)) {
         *status = U_MEMORY_ALLOCATION_ERROR;
-        delete syms;
-        return 0;
-      }
+    }
 
-      return (UNumberFormat*) fmt;
-  }
+    return reinterpret_cast<UNumberFormat *>(retVal);
 }
 
 U_CAPI void U_EXPORT2
 unum_close(UNumberFormat* fmt)
 {
-  delete (NumberFormat*) fmt;
+    delete (NumberFormat*) fmt;
 }
 
 U_CAPI UNumberFormat* U_EXPORT2
 unum_clone(const UNumberFormat *fmt,
        UErrorCode *status)
 {
-  if(U_FAILURE(*status)) return 0;
-
-  Format *res = ((DecimalFormat*)fmt)->clone();
-  
-  if(res == 0) {
-    *status = U_MEMORY_ALLOCATION_ERROR;
-    return 0;
-  }
+    if(U_FAILURE(*status))
+        return 0;
+    
+    Format *res = 0;
+    const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
+    const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
+    if (df != NULL) {
+        res = df->clone();
+    } else {
+        const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
+        U_ASSERT(rbnf != NULL);
+        res = rbnf->clone();
+    }
 
-  return (UNumberFormat*) res;
+    if(res == 0) {
+        *status = U_MEMORY_ALLOCATION_ERROR;
+        return 0;
+    }
+    
+    return (UNumberFormat*) res;
 }
 
 U_CAPI int32_t U_EXPORT2
 unum_format(    const    UNumberFormat*    fmt,
-        int32_t            number,
+        int32_t           number,
         UChar*            result,
-        int32_t            resultLength,
+        int32_t           resultLength,
         UFieldPosition    *pos,
-        UErrorCode*        status)
+        UErrorCode*       status)
 {
-  if(U_FAILURE(*status)) return -1;
+        return unum_formatInt64(fmt, number, result, resultLength, pos, status);
+}
 
-  UnicodeString res;
-  if(!(result==NULL && resultLength==0)) {
-    // NULL destination for pure preflighting: empty dummy string
-    // otherwise, alias the destination buffer
-    res.setTo(result, 0, resultLength);
-  }
+U_CAPI int32_t U_EXPORT2
+unum_formatInt64(const UNumberFormat* fmt,
+        int64_t         number,
+        UChar*          result,
+        int32_t         resultLength,
+        UFieldPosition *pos,
+        UErrorCode*     status)
+{
+    if(U_FAILURE(*status))
+        return -1;
+    
+    UnicodeString res;
+    if(!(result==NULL && resultLength==0)) {
+        // NULL destination for pure preflighting: empty dummy string
+        // otherwise, alias the destination buffer
+        res.setTo(result, 0, resultLength);
+    }
+    
+    FieldPosition fp;
+    
+    if(pos != 0)
+        fp.setField(pos->field);
+    
+    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);
+    }
 
-  FieldPosition fp;
-  
-  if(pos != 0)
-    fp.setField(pos->field);
-  
-  ((NumberFormat*)fmt)->format(number, res, fp);
-  
-  if(pos != 0) {
-    pos->beginIndex = fp.getBeginIndex();
-    pos->endIndex = fp.getEndIndex();
-  }
-  
-  return res.extract(result, resultLength, *status);
+    if(pos != 0) {
+        pos->beginIndex = fp.getBeginIndex();
+        pos->endIndex = fp.getEndIndex();
+    }
+    
+    return res.extract(result, resultLength, *status);
 }
 
 U_CAPI int32_t U_EXPORT2
@@ -271,7 +242,12 @@ unum_formatDouble(    const    UNumberFormat*  fmt,
   if(pos != 0)
     fp.setField(pos->field);
   
-  ((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();
@@ -282,38 +258,166 @@ unum_formatDouble(    const    UNumberFormat*  fmt,
 }
 
 U_CAPI int32_t U_EXPORT2
-unum_parse(    const   UNumberFormat*  fmt,
-        const   UChar*          text,
-        int32_t         textLength,
-        int32_t         *parsePos /* 0 = start */,
-        UErrorCode      *status)
+unum_formatDoubleForFields(const UNumberFormat* format,
+                           double number,
+                           UChar* result,
+                           int32_t resultLength,
+                           UFieldPositionIterator* fpositer,
+                           UErrorCode* status)
 {
-  if(U_FAILURE(*status)) return 0;
+    if (U_FAILURE(*status))
+        return -1;
 
-  int32_t len = (textLength == -1 ? u_strlen(text) : textLength);
-  const UnicodeString src((UChar*)text, len, len);
-  ParsePosition pp;
-  Formattable res;
+    if (result == NULL ? resultLength != 0 : resultLength < 0) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return -1;
+    }
 
-  if(parsePos != 0)
-    pp.setIndex(*parsePos);
+    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);
 
-  ((NumberFormat*)fmt)->parse(src, res, pp);
+    return res.extract(result, resultLength, *status);
+}
+
+U_CAPI int32_t U_EXPORT2 
+unum_formatDecimal(const    UNumberFormat*  fmt,
+            const char *    number,
+            int32_t         length,
+            UChar*          result,
+            int32_t         resultLength,
+            UFieldPosition  *pos, /* 0 if ignore */
+            UErrorCode*     status) {
 
-  if(parsePos != 0) {
-    if(pp.getErrorIndex() == -1)
-      *parsePos = pp.getIndex();
-    else {
-      *parsePos = pp.getErrorIndex();
-      *status = U_PARSE_ERROR;
+    if(U_FAILURE(*status)) {
+        return -1;
     }
-  }
+    if ((result == NULL && resultLength != 0) || resultLength < 0) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return -1;
+    }
+
+    FieldPosition fp;
+    if(pos != 0) {
+        fp.setField(pos->field);
+    }
+
+    if (length < 0) {
+        length = static_cast<int32_t>(uprv_strlen(number));
+    }
+    StringPiece numSP(number, length);
+    Formattable numFmtbl(numSP, *status);
 
-  /* return the actual type of the result, cast to a long */
-  return (res.getType() == Formattable::kLong) 
-    ? res.getLong() 
-    : (int32_t) res.getDouble();
+    UnicodeString resultStr;
+    if (resultLength > 0) {
+        // Alias the destination buffer.
+        resultStr.setTo(result, 0, resultLength);
+    }
+    ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status);
+    if(pos != 0) {
+        pos->beginIndex = fp.getBeginIndex();
+        pos->endIndex = fp.getEndIndex();
+    }
+    return resultStr.extract(result, resultLength, *status);
+}
+
+
+
+
+U_CAPI int32_t U_EXPORT2 
+unum_formatDoubleCurrency(const UNumberFormat* fmt,
+                          double number,
+                          UChar* currency,
+                          UChar* result,
+                          int32_t resultLength,
+                          UFieldPosition* pos, /* ignored if 0 */
+                          UErrorCode* status) {
+    if (U_FAILURE(*status)) return -1;
+
+    UnicodeString res;
+    if (!(result==NULL && resultLength==0)) {
+        // NULL destination for pure preflighting: empty dummy string
+        // otherwise, alias the destination buffer
+        res.setTo(result, 0, resultLength);
+    }
+    
+    FieldPosition fp;
+    if (pos != 0) {
+        fp.setField(pos->field);
+    }
+    CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status);
+    // Check for null pointer.
+    if (tempCurrAmnt == NULL) {
+        *status = U_MEMORY_ALLOCATION_ERROR;
+        return -1;
+    }
+    Formattable n(tempCurrAmnt);
+    ((const NumberFormat*)fmt)->format(n, res, fp, *status);
+    
+    if (pos != 0) {
+        pos->beginIndex = fp.getBeginIndex();
+        pos->endIndex = fp.getEndIndex();
+    }
+  
+    return res.extract(result, resultLength, *status);
+}
+
+static void
+parseRes(Formattable& res,
+         const   UNumberFormat*  fmt,
+         const   UChar*          text,
+         int32_t         textLength,
+         int32_t         *parsePos /* 0 = start */,
+         UErrorCode      *status)
+{
+    if(U_FAILURE(*status))
+        return;
+    
+    const UnicodeString src((UBool)(textLength == -1), text, textLength);
+    ParsePosition pp;
+    
+    if(parsePos != 0)
+        pp.setIndex(*parsePos);
+    
+    ((const NumberFormat*)fmt)->parse(src, res, pp);
+    
+    if(pp.getErrorIndex() != -1) {
+        *status = U_PARSE_ERROR;
+        if(parsePos != 0) {
+            *parsePos = pp.getErrorIndex();
+        }
+    } else if(parsePos != 0) {
+        *parsePos = pp.getIndex();
+    }
+}
+
+U_CAPI int32_t U_EXPORT2
+unum_parse(    const   UNumberFormat*  fmt,
+        const   UChar*          text,
+        int32_t         textLength,
+        int32_t         *parsePos /* 0 = start */,
+        UErrorCode      *status)
+{
+    Formattable res;
+    parseRes(res, fmt, text, textLength, parsePos, status);
+    return res.getLong(*status);
+}
+
+U_CAPI int64_t U_EXPORT2
+unum_parseInt64(    const   UNumberFormat*  fmt,
+        const   UChar*          text,
+        int32_t         textLength,
+        int32_t         *parsePos /* 0 = start */,
+        UErrorCode      *status)
+{
+    Formattable res;
+    parseRes(res, fmt, text, textLength, parsePos, status);
+    return res.getInt64(*status);
 }
 
 U_CAPI double U_EXPORT2
@@ -323,104 +427,133 @@ unum_parseDouble(    const   UNumberFormat*  fmt,
             int32_t         *parsePos /* 0 = start */,
             UErrorCode      *status)
 {
-  if(U_FAILURE(*status))
-      return 0;
-
-  int32_t len = (textLength < 0 ? u_strlen(text) : textLength);
-  const UnicodeString src((UChar*)text, len, len);
-  ParsePosition pp;
-  Formattable res;
-
-  if(parsePos != 0)
-    pp.setIndex(*parsePos);
+    Formattable res;
+    parseRes(res, fmt, text, textLength, parsePos, status);
+    return res.getDouble(*status);
+}
 
-  ((NumberFormat*)fmt)->parse(src, res, pp);
+U_CAPI int32_t U_EXPORT2
+unum_parseDecimal(const UNumberFormat*  fmt,
+            const UChar*    text,
+            int32_t         textLength,
+            int32_t         *parsePos /* 0 = start */,
+            char            *outBuf,
+            int32_t         outBufLength,
+            UErrorCode      *status)
+{
+    if (U_FAILURE(*status)) {
+        return -1;
+    }
+    if ((outBuf == NULL && outBufLength != 0) || outBufLength < 0) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return -1;
+    }
+    Formattable res;
+    parseRes(res, fmt, text, textLength, parsePos, status);
+    StringPiece sp = res.getDecimalNumber(*status);
+    if (U_FAILURE(*status)) {
+       return -1;
+    } else if (sp.size() > outBufLength) {
+        *status = U_BUFFER_OVERFLOW_ERROR;
+    } else if (sp.size() == outBufLength) {
+        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();
+}
 
-  if(parsePos != 0) {
-    if(pp.getErrorIndex() == -1)
-      *parsePos = pp.getIndex();
-    else {
-      *parsePos = pp.getErrorIndex();
-      *status = U_PARSE_ERROR;
+U_CAPI double U_EXPORT2
+unum_parseDoubleCurrency(const UNumberFormat* fmt,
+                         const UChar* text,
+                         int32_t textLength,
+                         int32_t* parsePos, /* 0 = start */
+                         UChar* currency,
+                         UErrorCode* status) {
+    double doubleVal = 0.0;
+    currency[0] = 0;
+    if (U_FAILURE(*status)) {
+        return doubleVal;
     }
-  }
-  
-  /* return the actual type of the result, cast to a double */
-  return (res.getType() == Formattable::kDouble) 
-    ? res.getDouble() 
-    : (double) res.getLong();
+    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
 unum_getAvailable(int32_t index)
 {
-  return uloc_getAvailable(index);
+    return uloc_getAvailable(index);
 }
 
 U_CAPI int32_t U_EXPORT2
 unum_countAvailable()
 {
-  return uloc_countAvailable();
+    return uloc_countAvailable();
 }
 
 U_CAPI int32_t U_EXPORT2
 unum_getAttribute(const UNumberFormat*          fmt,
           UNumberFormatAttribute  attr)
 {
-  switch(attr) {
-  case UNUM_PARSE_INT_ONLY:
-    return ((NumberFormat*)fmt)->isParseIntegerOnly();
-    
-  case UNUM_GROUPING_USED:
-    return ((NumberFormat*)fmt)->isGroupingUsed();
-    
-  case UNUM_DECIMAL_ALWAYS_SHOWN:
-    return ((DecimalFormat*)fmt)->isDecimalSeparatorAlwaysShown();    
-    
-  case UNUM_MAX_INTEGER_DIGITS:
-    return ((NumberFormat*)fmt)->getMaximumIntegerDigits();
-    
-  case UNUM_MIN_INTEGER_DIGITS:
-    return ((NumberFormat*)fmt)->getMinimumIntegerDigits();
-    
-  case UNUM_INTEGER_DIGITS:
-    // TBD: what should this return?
-    return ((NumberFormat*)fmt)->getMinimumIntegerDigits();
-    
-  case UNUM_MAX_FRACTION_DIGITS:
-    return ((NumberFormat*)fmt)->getMaximumFractionDigits();
-    
-  case UNUM_MIN_FRACTION_DIGITS:
-    return ((NumberFormat*)fmt)->getMinimumFractionDigits();
-    
-  case UNUM_FRACTION_DIGITS:
-    // TBD: what should this return?
-    return ((NumberFormat*)fmt)->getMinimumFractionDigits();
-
-  case UNUM_MULTIPLIER:
-    return ((DecimalFormat*)fmt)->getMultiplier();    
-    
-  case UNUM_GROUPING_SIZE:
-    return ((DecimalFormat*)fmt)->getGroupingSize();    
-
-  case UNUM_ROUNDING_MODE:
-    return ((DecimalFormat*)fmt)->getRoundingMode();
-
-  case UNUM_FORMAT_WIDTH:
-    return ((DecimalFormat*)fmt)->getFormatWidth();
+    const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
+    if (attr == UNUM_LENIENT_PARSE) {
+        // 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 position at which padding will take place. */
-  case UNUM_PADDING_POSITION:
-    return ((DecimalFormat*)fmt)->getPadPosition();
+    // 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);
+    }
 
-  default:
-    break;
-  }
-  return -1;
+    return -1;
 }
 
 U_CAPI void U_EXPORT2
@@ -428,87 +561,55 @@ unum_setAttribute(    UNumberFormat*          fmt,
             UNumberFormatAttribute  attr,
             int32_t                 newValue)
 {
-  switch(attr) {
-  case UNUM_PARSE_INT_ONLY:
-    ((NumberFormat*)fmt)->setParseIntegerOnly((UBool)newValue);
-    break;
-
-  case UNUM_GROUPING_USED:
-    ((NumberFormat*)fmt)->setGroupingUsed((UBool)newValue);
-    break;
-
-  case UNUM_DECIMAL_ALWAYS_SHOWN:
-    ((DecimalFormat*)fmt)->setDecimalSeparatorAlwaysShown((UBool)newValue);
-    break;
-
-  case UNUM_MAX_INTEGER_DIGITS:
-    ((NumberFormat*)fmt)->setMaximumIntegerDigits(newValue);
-    break;
-
-  case UNUM_MIN_INTEGER_DIGITS:
-    ((NumberFormat*)fmt)->setMinimumIntegerDigits(newValue);
-    break;
-
-  case UNUM_INTEGER_DIGITS:
-    ((NumberFormat*)fmt)->setMinimumIntegerDigits(newValue);
-    ((NumberFormat*)fmt)->setMaximumIntegerDigits(newValue);
-    break;
-
-  case UNUM_MAX_FRACTION_DIGITS:
-    ((NumberFormat*)fmt)->setMaximumFractionDigits(newValue);
-    break;
-
-  case UNUM_MIN_FRACTION_DIGITS:
-    ((NumberFormat*)fmt)->setMinimumFractionDigits(newValue);
-    break;
-
-  case UNUM_FRACTION_DIGITS:
-    ((NumberFormat*)fmt)->setMinimumFractionDigits(newValue);
-    ((NumberFormat*)fmt)->setMaximumFractionDigits(newValue);
-    break;
-
-  case UNUM_MULTIPLIER:
-    ((DecimalFormat*)fmt)->setMultiplier(newValue);    
-    break;
-
-  case UNUM_GROUPING_SIZE:
-    ((DecimalFormat*)fmt)->setGroupingSize(newValue);    
-    break;
-
-  case UNUM_ROUNDING_MODE:
-      ((DecimalFormat*)fmt)->setRoundingMode((DecimalFormat::ERoundingMode)newValue);
-    break;
-
-  case UNUM_FORMAT_WIDTH:
-    ((DecimalFormat*)fmt)->setFormatWidth(newValue);
-    break;
-
-  /** The position at which padding will take place. */
-  case UNUM_PADDING_POSITION:
-      ((DecimalFormat*)fmt)->setPadPosition((DecimalFormat::EPadPosition)newValue);
-    break;
-
-  case UNUM_SECONDARY_GROUPING_SIZE:
-      ((DecimalFormat*)fmt)->setSecondaryGroupingSize(newValue);
-    break;
-
-  default:
-    /* Shouldn't get here anyway */
-    break;
-  }
+    NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
+    if (attr == UNUM_LENIENT_PARSE) {
+        // 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
 unum_getDoubleAttribute(const UNumberFormat*          fmt,
           UNumberFormatAttribute  attr)
 {
-  if (attr == UNUM_ROUNDING_INCREMENT) {
-    return ((DecimalFormat*)fmt)->getRoundingIncrement();
-  } else {
-    return -1.0;
-  }
+    const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
+    const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
+    if (df != NULL &&  attr == UNUM_ROUNDING_INCREMENT) {
+        return df->getRoundingIncrement();
+    } else {
+        return -1.0;
+    }
 }
 
 U_CAPI void U_EXPORT2
@@ -516,10 +617,11 @@ unum_setDoubleAttribute(    UNumberFormat*          fmt,
             UNumberFormatAttribute  attr,
             double                 newValue)
 {
-  if (attr == UNUM_ROUNDING_INCREMENT) {   
-    ((DecimalFormat*)fmt)->setRoundingIncrement(newValue);
-  }
+    NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
+    DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
+    if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) {   
+        df->setRoundingIncrement(newValue);
+    }
 }
 
 U_CAPI int32_t U_EXPORT2
@@ -529,48 +631,66 @@ unum_getTextAttribute(const UNumberFormat*  fmt,
             int32_t                         resultLength,
             UErrorCode*                     status)
 {
-  if(U_FAILURE(*status))
-      return -1;
-
-  UnicodeString res;
-  if(!(result==NULL && resultLength==0)) {
-    // NULL destination for pure preflighting: empty dummy string
-    // otherwise, alias the destination buffer
-    res.setTo(result, 0, resultLength);
-  }
-
-  switch(tag) {
-  case UNUM_POSITIVE_PREFIX:
-    ((DecimalFormat*)fmt)->getPositivePrefix(res);
-    break;
-
-  case UNUM_POSITIVE_SUFFIX:
-    ((DecimalFormat*)fmt)->getPositiveSuffix(res);
-    break;
-
-  case UNUM_NEGATIVE_PREFIX:
-    ((DecimalFormat*)fmt)->getNegativePrefix(res);
-    break;
-
-  case UNUM_NEGATIVE_SUFFIX:
-    ((DecimalFormat*)fmt)->getNegativeSuffix(res);
-    break;
-
-  case UNUM_PADDING_CHARACTER:
-    res = ((DecimalFormat*)fmt)->getPadCharacterString();
-    break;
-
-  case UNUM_CURRENCY_CODE:
-    res = UnicodeString(((DecimalFormat*)fmt)->getCurrency());
-    break;
+    if(U_FAILURE(*status))
+        return -1;
+
+    UnicodeString res;
+    if(!(result==NULL && resultLength==0)) {
+        // NULL destination for pure preflighting: empty dummy string
+        // otherwise, alias the destination buffer
+        res.setTo(result, 0, resultLength);
+    }
 
-  default:
-    *status = U_UNSUPPORTED_ERROR;
-    return -1;
-  }
+    const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
+    const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
+    if (df != NULL) {
+        switch(tag) {
+        case UNUM_POSITIVE_PREFIX:
+            df->getPositivePrefix(res);
+            break;
+
+        case UNUM_POSITIVE_SUFFIX:
+            df->getPositiveSuffix(res);
+            break;
+
+        case UNUM_NEGATIVE_PREFIX:
+            df->getNegativePrefix(res);
+            break;
+
+        case UNUM_NEGATIVE_SUFFIX:
+            df->getNegativeSuffix(res);
+            break;
+
+        case UNUM_PADDING_CHARACTER:
+            res = df->getPadCharacterString();
+            break;
+
+        case UNUM_CURRENCY_CODE:
+            res = UnicodeString(df->getCurrency());
+            break;
+
+        default:
+            *status = U_UNSUPPORTED_ERROR;
+            return -1;
+        }
+    } else {
+        const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
+        U_ASSERT(rbnf != NULL);
+        if (tag == UNUM_DEFAULT_RULESET) {
+            res = rbnf->getDefaultRuleSetName();
+        } else if (tag == UNUM_PUBLIC_RULESETS) {
+            int32_t count = rbnf->getNumberOfRuleSetNames();
+            for (int i = 0; i < count; ++i) {
+                res += rbnf->getRuleSetName(i);
+                res += (UChar)0x003b; // semicolon
+            }
+        } else {
+            *status = U_UNSUPPORTED_ERROR;
+            return -1;
+        }
+    }
 
-  return res.extract(result, resultLength, *status);
+    return res.extract(result, resultLength, *status);
 }
 
 U_CAPI void U_EXPORT2
@@ -580,41 +700,51 @@ unum_setTextAttribute(    UNumberFormat*                    fmt,
             int32_t                            newValueLength,
             UErrorCode                        *status)
 {
-  if(U_FAILURE(*status)) return;
-
-  int32_t len = (newValueLength == -1 ? u_strlen(newValue) : newValueLength);
-  const UnicodeString val((UChar*)newValue, len, len);
-  
-  switch(tag) {
-  case UNUM_POSITIVE_PREFIX:
-    ((DecimalFormat*)fmt)->setPositivePrefix(val);
-    break;
-
-  case UNUM_POSITIVE_SUFFIX:
-    ((DecimalFormat*)fmt)->setPositiveSuffix(val);
-    break;
-
-  case UNUM_NEGATIVE_PREFIX:
-    ((DecimalFormat*)fmt)->setNegativePrefix(val);
-    break;
-
-  case UNUM_NEGATIVE_SUFFIX:
-    ((DecimalFormat*)fmt)->setNegativeSuffix(val);
-    break;
-
-  case UNUM_PADDING_CHARACTER:
-    ((DecimalFormat*)fmt)->setPadCharacter(*newValue);
-    break;
-
-  case UNUM_CURRENCY_CODE:
-      ((DecimalFormat*)fmt)->setCurrency(newValue);
-      break;
-
-  default:
-    *status = U_UNSUPPORTED_ERROR;
-    break;
-  }
+    if(U_FAILURE(*status))
+        return;
+
+    UnicodeString val(newValue, newValueLength);
+    NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
+    DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
+    if (df != NULL) {
+      switch(tag) {
+      case UNUM_POSITIVE_PREFIX:
+        df->setPositivePrefix(val);
+        break;
+        
+      case UNUM_POSITIVE_SUFFIX:
+        df->setPositiveSuffix(val);
+        break;
+        
+      case UNUM_NEGATIVE_PREFIX:
+        df->setNegativePrefix(val);
+        break;
+        
+      case UNUM_NEGATIVE_SUFFIX:
+        df->setNegativeSuffix(val);
+        break;
+        
+      case UNUM_PADDING_CHARACTER:
+        df->setPadCharacter(val);
+        break;
+        
+      case UNUM_CURRENCY_CODE:
+        df->setCurrency(val.getTerminatedBuffer(), *status);
+        break;
+        
+      default:
+        *status = U_UNSUPPORTED_ERROR;
+        break;
+      }
+    } else {
+      RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf);
+      U_ASSERT(rbnf != NULL);
+      if (tag == UNUM_DEFAULT_RULESET) {
+        rbnf->setDefaultRuleSet(val, *status);
+      } else {
+        *status = U_UNSUPPORTED_ERROR;
+      }
+    }
 }
 
 U_CAPI int32_t U_EXPORT2
@@ -624,42 +754,53 @@ unum_toPattern(    const    UNumberFormat*          fmt,
         int32_t                 resultLength,
         UErrorCode*             status)
 {
-  if(U_FAILURE(*status)) return -1;
-
-  UnicodeString pat;
-  if(!(result==NULL && resultLength==0)) {
-    // NULL destination for pure preflighting: empty dummy string
-    // otherwise, alias the destination buffer
-    pat.setTo(result, 0, resultLength);
-  }
-
-  if(isPatternLocalized)
-    ((DecimalFormat*)fmt)->toLocalizedPattern(pat);
-  else
-    ((DecimalFormat*)fmt)->toPattern(pat);
+    if(U_FAILURE(*status))
+        return -1;
+    
+    UnicodeString pat;
+    if(!(result==NULL && resultLength==0)) {
+        // NULL destination for pure preflighting: empty dummy string
+        // otherwise, alias the destination buffer
+        pat.setTo(result, 0, resultLength);
+    }
 
-  return pat.extract(result, resultLength, *status);
+    const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
+    const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
+    if (df != NULL) {
+      if(isPatternLocalized)
+        df->toLocalizedPattern(pat);
+      else
+        df->toPattern(pat);
+    } else {
+      const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
+      U_ASSERT(rbnf != NULL);
+      pat = rbnf->getRules();
+    }
+    return pat.extract(result, resultLength, *status);
 }
 
 U_CAPI int32_t U_EXPORT2
-unum_getSymbol(UNumberFormat *fmt,
+unum_getSymbol(const UNumberFormat *fmt,
                UNumberFormatSymbol symbol,
                UChar *buffer,
                int32_t size,
-               UErrorCode *status) {
-  if(status==NULL || U_FAILURE(*status)) {
-    return 0;
-  }
-
-  if(fmt==NULL || (uint16_t)symbol>=UNUM_FORMAT_SYMBOL_COUNT) {
-    *status=U_ILLEGAL_ARGUMENT_ERROR;
-    return 0;
-  }
+               UErrorCode *status)
+{
+    if(status==NULL || U_FAILURE(*status)) {
+        return 0;
+    }
+    if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) {
+        *status=U_ILLEGAL_ARGUMENT_ERROR;
+        return 0;
+    }
+    const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt);
+    const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf);
+    if (dcf == NULL) {
+      *status = U_UNSUPPORTED_ERROR;
+      return 0;
+    }
 
-  return
-    ((const DecimalFormat *)fmt)->
+    return dcf->
       getDecimalFormatSymbols()->
         getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol).
           extract(buffer, size, *status);
@@ -670,70 +811,152 @@ unum_setSymbol(UNumberFormat *fmt,
                UNumberFormatSymbol symbol,
                const UChar *value,
                int32_t length,
-               UErrorCode *status) {
-  if(status==NULL || U_FAILURE(*status)) {
-    return;
-  }
-
-  if(fmt==NULL || (uint16_t)symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) {
-    *status=U_ILLEGAL_ARGUMENT_ERROR;
-    return;
-  }
-
-  DecimalFormatSymbols symbols(*((DecimalFormat *)fmt)->getDecimalFormatSymbols());
-  symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol,
-        length>=0 ? UnicodeString(value, length) : UnicodeString(value));
-  ((DecimalFormat *)fmt)->setDecimalFormatSymbols(symbols);
-}
-
-/*
-U_CAPI void
-unum_applyPattern(            UNumberFormat     *format,
-                    UBool          localized,
-                    const   UChar           *pattern,
-                    int32_t         patternLength
-                    )
+               UErrorCode *status)
 {
-    UErrorCode status = U_ZERO_ERROR;
-    UParseError parseError;
-    unum_applyPatternWithError(format,localized,pattern,patternLength,&parseError,&status);
+    if(status==NULL || U_FAILURE(*status)) {
+        return;
+    }
+    if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) {
+        *status=U_ILLEGAL_ARGUMENT_ERROR;
+        return;
+    }
+    NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt);
+    DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf);
+    if (dcf == NULL) {
+      *status = U_UNSUPPORTED_ERROR;
+      return;
+    }
+
+    DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols());
+    symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol,
+        UnicodeString(value, length));  /* UnicodeString can handle the case when length = -1. */
+    dcf->setDecimalFormatSymbols(symbols);
 }
-*/
 
 U_CAPI void U_EXPORT2
-unum_applyPattern(  UNumberFormat  *format,
+unum_applyPattern(  UNumberFormat  *fmt,
                     UBool          localized,
                     const UChar    *pattern,
                     int32_t        patternLength,
                     UParseError    *parseError,
                     UErrorCode*    status)
 {
-  UErrorCode tStatus = U_ZERO_ERROR;
-  UParseError tParseError;
-  
-  if(parseError == NULL){
-      parseError = &tParseError;
+    UErrorCode tStatus = U_ZERO_ERROR;
+    UParseError tParseError;
+    
+    if(parseError == NULL){
+        parseError = &tParseError;
+    }
+    
+    if(status==NULL){
+        status = &tStatus;
+    }
+    
+    int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
+    const UnicodeString pat((UChar*)pattern, len, len);
+
+    // Verify if the object passed is a DecimalFormat object
+    NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
+    DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
+    if (df != NULL) {
+      if(localized) {
+        df->applyLocalizedPattern(pat,*parseError, *status);
+      } else {
+        df->applyPattern(pat,*parseError, *status);
+      }
+    } else {
+      *status = U_UNSUPPORTED_ERROR;
+      return;
+    }
+}
+
+U_CAPI const char* U_EXPORT2
+unum_getLocaleByType(const UNumberFormat *fmt,
+                     ULocDataLocaleType type,
+                     UErrorCode* status)
+{
+    if (fmt == NULL) {
+        if (U_SUCCESS(*status)) {
+            *status = U_ILLEGAL_ARGUMENT_ERROR;
+        }
+        return NULL;
+    }
+    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(status==NULL){
-      status = &tStatus;
+  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;
+}
 
-  int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
-  const UnicodeString pat((UChar*)pattern, len, len);
-
-  // Verify if the object passed is a DecimalFormat object
-  if(((NumberFormat*)format)->getDynamicClassID()!= DecimalFormat::getStaticClassID()){
+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;
-  }
-  
-  if(localized)
-    ((DecimalFormat*)format)->applyLocalizedPattern(pat,*parseError, *status);
-  else
-    ((DecimalFormat*)format)->applyPattern(pat,*parseError, *status);
+      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 */