Home | History | Annotate | Download | only in i18n
      1 /*
      2 ******************************************************************************
      3 * Copyright (C) 2014-2015, International Business Machines
      4 * Corporation and others.  All Rights Reserved.
      5 ******************************************************************************
      6 * quantityformatter.cpp
      7 */
      8 
      9 #include "unicode/utypes.h"
     10 
     11 #if !UCONFIG_NO_FORMATTING
     12 
     13 #include "quantityformatter.h"
     14 #include "simplepatternformatter.h"
     15 #include "uassert.h"
     16 #include "unicode/unistr.h"
     17 #include "unicode/decimfmt.h"
     18 #include "cstring.h"
     19 #include "unicode/plurrule.h"
     20 #include "charstr.h"
     21 #include "unicode/fmtable.h"
     22 #include "unicode/fieldpos.h"
     23 #include "standardplural.h"
     24 #include "visibledigits.h"
     25 #include "uassert.h"
     26 
     27 U_NAMESPACE_BEGIN
     28 
     29 QuantityFormatter::QuantityFormatter() {
     30     for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
     31         formatters[i] = NULL;
     32     }
     33 }
     34 
     35 QuantityFormatter::QuantityFormatter(const QuantityFormatter &other) {
     36     for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
     37         if (other.formatters[i] == NULL) {
     38             formatters[i] = NULL;
     39         } else {
     40             formatters[i] = new SimplePatternFormatter(*other.formatters[i]);
     41         }
     42     }
     43 }
     44 
     45 QuantityFormatter &QuantityFormatter::operator=(
     46         const QuantityFormatter& other) {
     47     if (this == &other) {
     48         return *this;
     49     }
     50     for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
     51         delete formatters[i];
     52         if (other.formatters[i] == NULL) {
     53             formatters[i] = NULL;
     54         } else {
     55             formatters[i] = new SimplePatternFormatter(*other.formatters[i]);
     56         }
     57     }
     58     return *this;
     59 }
     60 
     61 QuantityFormatter::~QuantityFormatter() {
     62     for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
     63         delete formatters[i];
     64     }
     65 }
     66 
     67 void QuantityFormatter::reset() {
     68     for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
     69         delete formatters[i];
     70         formatters[i] = NULL;
     71     }
     72 }
     73 
     74 UBool QuantityFormatter::addIfAbsent(
     75         const char *variant,
     76         const UnicodeString &rawPattern,
     77         UErrorCode &status) {
     78     int32_t pluralIndex = StandardPlural::indexFromString(variant, status);
     79     if (U_FAILURE(status)) {
     80         return FALSE;
     81     }
     82     if (formatters[pluralIndex] != NULL) {
     83         return TRUE;
     84     }
     85     SimplePatternFormatter *newFmt = new SimplePatternFormatter(rawPattern, 0, 1, status);
     86     if (newFmt == NULL) {
     87         status = U_MEMORY_ALLOCATION_ERROR;
     88         return FALSE;
     89     }
     90     if (U_FAILURE(status)) {
     91         delete newFmt;
     92         return FALSE;
     93     }
     94     formatters[pluralIndex] = newFmt;
     95     return TRUE;
     96 }
     97 
     98 UBool QuantityFormatter::isValid() const {
     99     return formatters[StandardPlural::OTHER] != NULL;
    100 }
    101 
    102 const SimplePatternFormatter *QuantityFormatter::getByVariant(
    103         const char *variant) const {
    104     U_ASSERT(isValid());
    105     int32_t pluralIndex = StandardPlural::indexOrOtherIndexFromString(variant);
    106     const SimplePatternFormatter *pattern = formatters[pluralIndex];
    107     if (pattern == NULL) {
    108         pattern = formatters[StandardPlural::OTHER];
    109     }
    110     return pattern;
    111 }
    112 
    113 UnicodeString &QuantityFormatter::format(
    114             const Formattable &number,
    115             const NumberFormat &fmt,
    116             const PluralRules &rules,
    117             UnicodeString &appendTo,
    118             FieldPosition &pos,
    119             UErrorCode &status) const {
    120     UnicodeString formattedNumber;
    121     StandardPlural::Form p = selectPlural(number, fmt, rules, formattedNumber, pos, status);
    122     if (U_FAILURE(status)) {
    123         return appendTo;
    124     }
    125     const SimplePatternFormatter *pattern = formatters[p];
    126     if (pattern == NULL) {
    127         pattern = formatters[StandardPlural::OTHER];
    128         if (pattern == NULL) {
    129             status = U_INVALID_STATE_ERROR;
    130             return appendTo;
    131         }
    132     }
    133     return format(*pattern, formattedNumber, appendTo, pos, status);
    134 }
    135 
    136 // The following methods live here so that class PluralRules does not depend on number formatting,
    137 // and the SimplePatternFormatter does not depend on FieldPosition.
    138 
    139 StandardPlural::Form QuantityFormatter::selectPlural(
    140             const Formattable &number,
    141             const NumberFormat &fmt,
    142             const PluralRules &rules,
    143             UnicodeString &formattedNumber,
    144             FieldPosition &pos,
    145             UErrorCode &status) {
    146     if (U_FAILURE(status)) {
    147         return StandardPlural::OTHER;
    148     }
    149     UnicodeString pluralKeyword;
    150     VisibleDigitsWithExponent digits;
    151     const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt);
    152     if (decFmt != NULL) {
    153         decFmt->initVisibleDigitsWithExponent(number, digits, status);
    154         if (U_FAILURE(status)) {
    155             return StandardPlural::OTHER;
    156         }
    157         pluralKeyword = rules.select(digits);
    158         decFmt->format(digits, formattedNumber, pos, status);
    159     } else {
    160         if (number.getType() == Formattable::kDouble) {
    161             pluralKeyword = rules.select(number.getDouble());
    162         } else if (number.getType() == Formattable::kLong) {
    163             pluralKeyword = rules.select(number.getLong());
    164         } else if (number.getType() == Formattable::kInt64) {
    165             pluralKeyword = rules.select((double) number.getInt64());
    166         } else {
    167             status = U_ILLEGAL_ARGUMENT_ERROR;
    168             return StandardPlural::OTHER;
    169         }
    170         fmt.format(number, formattedNumber, pos, status);
    171     }
    172     return StandardPlural::orOtherFromString(pluralKeyword);
    173 }
    174 
    175 UnicodeString &QuantityFormatter::format(
    176             const SimplePatternFormatter &pattern,
    177             const UnicodeString &value,
    178             UnicodeString &appendTo,
    179             FieldPosition &pos,
    180             UErrorCode &status) {
    181     if (U_FAILURE(status)) {
    182         return appendTo;
    183     }
    184     const UnicodeString *param = &value;
    185     int32_t offset;
    186     pattern.formatAndAppend(&param, 1, appendTo, &offset, 1, status);
    187     if (pos.getBeginIndex() != 0 || pos.getEndIndex() != 0) {
    188         if (offset >= 0) {
    189             pos.setBeginIndex(pos.getBeginIndex() + offset);
    190             pos.setEndIndex(pos.getEndIndex() + offset);
    191         } else {
    192             pos.setBeginIndex(0);
    193             pos.setEndIndex(0);
    194         }
    195     }
    196     return appendTo;
    197 }
    198 
    199 U_NAMESPACE_END
    200 
    201 #endif /* #if !UCONFIG_NO_FORMATTING */
    202