quantityformatter.cpp revision 1b7d32f919554dda9c193b32188251337bc756f1
1/* 2****************************************************************************** 3* Copyright (C) 2014, International Business Machines 4* Corporation and others. All Rights Reserved. 5****************************************************************************** 6* quantityformatter.cpp 7*/ 8#include "quantityformatter.h" 9#include "simplepatternformatter.h" 10#include "uassert.h" 11#include "unicode/unistr.h" 12#include "unicode/decimfmt.h" 13#include "cstring.h" 14#include "plurrule_impl.h" 15#include "unicode/plurrule.h" 16#include "charstr.h" 17#include "unicode/fmtable.h" 18#include "unicode/fieldpos.h" 19 20#if !UCONFIG_NO_FORMATTING 21 22U_NAMESPACE_BEGIN 23 24// other must always be first. 25static const char * const gPluralForms[] = { 26 "other", "zero", "one", "two", "few", "many"}; 27 28static int32_t getPluralIndex(const char *pluralForm) { 29 int32_t len = UPRV_LENGTHOF(gPluralForms); 30 for (int32_t i = 0; i < len; ++i) { 31 if (uprv_strcmp(pluralForm, gPluralForms[i]) == 0) { 32 return i; 33 } 34 } 35 return -1; 36} 37 38QuantityFormatter::QuantityFormatter() { 39 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { 40 formatters[i] = NULL; 41 } 42} 43 44QuantityFormatter::QuantityFormatter(const QuantityFormatter &other) { 45 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { 46 if (other.formatters[i] == NULL) { 47 formatters[i] = NULL; 48 } else { 49 formatters[i] = new SimplePatternFormatter(*other.formatters[i]); 50 } 51 } 52} 53 54QuantityFormatter &QuantityFormatter::operator=( 55 const QuantityFormatter& other) { 56 if (this == &other) { 57 return *this; 58 } 59 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { 60 delete formatters[i]; 61 if (other.formatters[i] == NULL) { 62 formatters[i] = NULL; 63 } else { 64 formatters[i] = new SimplePatternFormatter(*other.formatters[i]); 65 } 66 } 67 return *this; 68} 69 70QuantityFormatter::~QuantityFormatter() { 71 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { 72 delete formatters[i]; 73 } 74} 75 76void QuantityFormatter::reset() { 77 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { 78 delete formatters[i]; 79 formatters[i] = NULL; 80 } 81} 82 83UBool QuantityFormatter::add( 84 const char *variant, 85 const UnicodeString &rawPattern, 86 UErrorCode &status) { 87 if (U_FAILURE(status)) { 88 return FALSE; 89 } 90 int32_t pluralIndex = getPluralIndex(variant); 91 if (pluralIndex == -1) { 92 status = U_ILLEGAL_ARGUMENT_ERROR; 93 return FALSE; 94 } 95 SimplePatternFormatter *newFmt = 96 new SimplePatternFormatter(rawPattern); 97 if (newFmt == NULL) { 98 status = U_MEMORY_ALLOCATION_ERROR; 99 return FALSE; 100 } 101 if (newFmt->getPlaceholderCount() > 1) { 102 delete newFmt; 103 status = U_ILLEGAL_ARGUMENT_ERROR; 104 return FALSE; 105 } 106 delete formatters[pluralIndex]; 107 formatters[pluralIndex] = newFmt; 108 return TRUE; 109} 110 111UBool QuantityFormatter::isValid() const { 112 return formatters[0] != NULL; 113} 114 115const SimplePatternFormatter *QuantityFormatter::getByVariant( 116 const char *variant) const { 117 int32_t pluralIndex = getPluralIndex(variant); 118 if (pluralIndex == -1) { 119 pluralIndex = 0; 120 } 121 const SimplePatternFormatter *pattern = formatters[pluralIndex]; 122 if (pattern == NULL) { 123 pattern = formatters[0]; 124 } 125 return pattern; 126} 127 128UnicodeString &QuantityFormatter::format( 129 const Formattable& quantity, 130 const NumberFormat &fmt, 131 const PluralRules &rules, 132 UnicodeString &appendTo, 133 FieldPosition &pos, 134 UErrorCode &status) const { 135 if (U_FAILURE(status)) { 136 return appendTo; 137 } 138 UnicodeString count; 139 const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt); 140 if (decFmt != NULL) { 141 FixedDecimal fd = decFmt->getFixedDecimal(quantity, status); 142 if (U_FAILURE(status)) { 143 return appendTo; 144 } 145 count = rules.select(fd); 146 } else { 147 if (quantity.getType() == Formattable::kDouble) { 148 count = rules.select(quantity.getDouble()); 149 } else if (quantity.getType() == Formattable::kLong) { 150 count = rules.select(quantity.getLong()); 151 } else if (quantity.getType() == Formattable::kInt64) { 152 count = rules.select((double) quantity.getInt64()); 153 } else { 154 status = U_ILLEGAL_ARGUMENT_ERROR; 155 return appendTo; 156 } 157 } 158 CharString buffer; 159 buffer.appendInvariantChars(count, status); 160 if (U_FAILURE(status)) { 161 return appendTo; 162 } 163 const SimplePatternFormatter *pattern = getByVariant(buffer.data()); 164 if (pattern == NULL) { 165 status = U_INVALID_STATE_ERROR; 166 return appendTo; 167 } 168 UnicodeString formattedNumber; 169 FieldPosition fpos(pos.getField()); 170 fmt.format(quantity, formattedNumber, fpos, status); 171 const UnicodeString *params[1] = {&formattedNumber}; 172 int32_t offsets[1]; 173 pattern->formatAndAppend( 174 params, 175 UPRV_LENGTHOF(params), 176 appendTo, 177 offsets, 178 UPRV_LENGTHOF(offsets), 179 status); 180 if (offsets[0] != -1) { 181 if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) { 182 pos.setBeginIndex(fpos.getBeginIndex() + offsets[0]); 183 pos.setEndIndex(fpos.getEndIndex() + offsets[0]); 184 } 185 } 186 return appendTo; 187} 188 189U_NAMESPACE_END 190 191#endif /* #if !UCONFIG_NO_FORMATTING */ 192