quantityformatter.cpp revision 0b3ec0516c035ea443fdc334025048597c740be1
1fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/* 2fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius****************************************************************************** 3c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert* Copyright (C) 2014-2015, International Business Machines 4fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Corporation and others. All Rights Reserved. 5fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius****************************************************************************** 6fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* quantityformatter.cpp 7fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*/ 88ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer 98ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer#include "unicode/utypes.h" 108ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer 118ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer#if !UCONFIG_NO_FORMATTING 128ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer 13fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "quantityformatter.h" 14fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "simplepatternformatter.h" 15fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "uassert.h" 16fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/unistr.h" 17fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/decimfmt.h" 18fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "cstring.h" 19fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/plurrule.h" 20fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "charstr.h" 21fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/fmtable.h" 22fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/fieldpos.h" 238ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer#include "resource.h" 240b3ec0516c035ea443fdc334025048597c740be1Markus Scherer#include "standardplural.h" 25c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "visibledigits.h" 268ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer#include "uassert.h" 27fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_BEGIN 29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusQuantityFormatter::QuantityFormatter() { 31f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { 32fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius formatters[i] = NULL; 33fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 34fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 35fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 36fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusQuantityFormatter::QuantityFormatter(const QuantityFormatter &other) { 37f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { 38fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (other.formatters[i] == NULL) { 39fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius formatters[i] = NULL; 40fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 41fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius formatters[i] = new SimplePatternFormatter(*other.formatters[i]); 42fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 43fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 44fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 45fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 46fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusQuantityFormatter &QuantityFormatter::operator=( 47fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const QuantityFormatter& other) { 48fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (this == &other) { 49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return *this; 50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 51f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { 52fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete formatters[i]; 53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (other.formatters[i] == NULL) { 54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius formatters[i] = NULL; 55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 56fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius formatters[i] = new SimplePatternFormatter(*other.formatters[i]); 57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return *this; 60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 62fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusQuantityFormatter::~QuantityFormatter() { 63f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { 64fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete formatters[i]; 65fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 66fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 67fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 68fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid QuantityFormatter::reset() { 69f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) { 70fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete formatters[i]; 71fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius formatters[i] = NULL; 72fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 73fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 74fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 758ce198ebe2317b05a969826d0b629cb2d0b894a2Markus SchererUBool QuantityFormatter::addIfAbsent( 76fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const char *variant, 778ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer const UnicodeString *rawPattern, 788ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer const ResourceValue *patternValue, 79fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) { 800b3ec0516c035ea443fdc334025048597c740be1Markus Scherer int32_t pluralIndex = StandardPlural::indexFromString(variant, status); 81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 83fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 848ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer if (formatters[pluralIndex] != NULL) { 858ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer return TRUE; 868ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer } 878ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer const UnicodeString &pattern = 888ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer rawPattern != NULL ? *rawPattern : patternValue->getUnicodeString(status); 898ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer SimplePatternFormatter *newFmt = new SimplePatternFormatter(pattern); 90fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (newFmt == NULL) { 91fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_MEMORY_ALLOCATION_ERROR; 92fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 93fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 94fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (newFmt->getPlaceholderCount() > 1) { 95fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete newFmt; 96fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_ILLEGAL_ARGUMENT_ERROR; 97fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 98fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 99fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius formatters[pluralIndex] = newFmt; 100fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return TRUE; 101fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 102fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 103fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUBool QuantityFormatter::isValid() const { 1040b3ec0516c035ea443fdc334025048597c740be1Markus Scherer return formatters[StandardPlural::OTHER] != NULL; 105fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 106fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 107f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusconst SimplePatternFormatter *QuantityFormatter::getByVariant( 108f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius const char *variant) const { 1098ce198ebe2317b05a969826d0b629cb2d0b894a2Markus Scherer U_ASSERT(isValid()); 1100b3ec0516c035ea443fdc334025048597c740be1Markus Scherer int32_t pluralIndex = StandardPlural::indexOrOtherIndexFromString(variant); 111f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius const SimplePatternFormatter *pattern = formatters[pluralIndex]; 112f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius if (pattern == NULL) { 1130b3ec0516c035ea443fdc334025048597c740be1Markus Scherer pattern = formatters[StandardPlural::OTHER]; 114f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius } 115f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius return pattern; 116f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius} 117f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 118fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString &QuantityFormatter::format( 119fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Formattable& quantity, 120fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const NumberFormat &fmt, 121fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const PluralRules &rules, 122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &appendTo, 123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius FieldPosition &pos, 124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 125fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 126fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 127fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 128fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString count; 129c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert VisibleDigitsWithExponent digits; 130fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt); 131fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (decFmt != NULL) { 132c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert decFmt->initVisibleDigitsWithExponent(quantity, digits, status); 133fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 134fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 135fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 136c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert count = rules.select(digits); 137fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 138fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (quantity.getType() == Formattable::kDouble) { 139fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius count = rules.select(quantity.getDouble()); 140fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else if (quantity.getType() == Formattable::kLong) { 141fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius count = rules.select(quantity.getLong()); 142fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else if (quantity.getType() == Formattable::kInt64) { 143fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius count = rules.select((double) quantity.getInt64()); 144fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 145fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_ILLEGAL_ARGUMENT_ERROR; 146fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 147fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 148fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 149fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius CharString buffer; 150fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer.appendInvariantChars(count, status); 151fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 152fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 153fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 154f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius const SimplePatternFormatter *pattern = getByVariant(buffer.data()); 155fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (pattern == NULL) { 156fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_INVALID_STATE_ERROR; 157fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 158fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 159fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString formattedNumber; 160fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius FieldPosition fpos(pos.getField()); 161c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (decFmt != NULL) { 162c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert decFmt->format(digits, formattedNumber, fpos, status); 163c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } else { 164c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert fmt.format(quantity, formattedNumber, fpos, status); 165c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 166fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString *params[1] = {&formattedNumber}; 167fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t offsets[1]; 1681b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert pattern->formatAndAppend( 1691b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert params, 1701b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UPRV_LENGTHOF(params), 1711b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert appendTo, 1721b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert offsets, 1731b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UPRV_LENGTHOF(offsets), 1741b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert status); 175fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (offsets[0] != -1) { 176fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) { 177fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pos.setBeginIndex(fpos.getBeginIndex() + offsets[0]); 178fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pos.setEndIndex(fpos.getEndIndex() + offsets[0]); 179fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 180fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 181fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 182fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 183fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 184fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_END 185fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 186fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif /* #if !UCONFIG_NO_FORMATTING */ 187