]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/unum.cpp
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / unum.cpp
index 61d8e46ccf239d938a58e07b61e0f2933caaef24..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-2012, 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"
@@ -51,6 +55,11 @@ unum_open(  UNumberFormatStyle    style,
     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;
 
@@ -109,6 +118,14 @@ unum_open(  UNumberFormatStyle    style,
         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 NULL;
@@ -187,7 +204,12 @@ unum_formatInt64(const UNumberFormat* fmt,
     if(pos != 0)
         fp.setField(pos->field);
     
-    ((const NumberFormat*)fmt)->format(number, res, fp, *status);
+    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();
@@ -220,7 +242,12 @@ unum_formatDouble(    const    UNumberFormat*  fmt,
   if(pos != 0)
     fp.setField(pos->field);
   
-  ((const NumberFormat*)fmt)->format(number, res, fp, *status);
+  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();
@@ -230,6 +257,33 @@ 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_CAPI int32_t U_EXPORT2 
 unum_formatDecimal(const    UNumberFormat*  fmt,
@@ -254,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);
@@ -463,20 +517,43 @@ U_CAPI int32_t U_EXPORT2
 unum_getAttribute(const UNumberFormat*          fmt,
           UNumberFormatAttribute  attr)
 {
-  const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
-  if ( attr == UNUM_LENIENT_PARSE ) {
-    // Supported for all subclasses
-    return nf->isLenient();
-  }
+    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 remaining attributea 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 );
-  }
+    // 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
@@ -484,18 +561,42 @@ unum_setAttribute(    UNumberFormat*          fmt,
             UNumberFormatAttribute  attr,
             int32_t                 newValue)
 {
-  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);
-  }
-  // The remaining attributea are only supported for DecimalFormat
-  DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
-  if (df != NULL) {
-    UErrorCode ignoredStatus = U_ZERO_ERROR;
-    df->setAttribute(attr, newValue, ignoredStatus);
-  }
+    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
@@ -783,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 */