10596faeddefbf198de137d5e893708495ab1584cFredrik Roubert// © 2016 and later: Unicode, Inc. and others. 264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html 3c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert/* 4c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Copyright (C) 2015, International Business Machines 5c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Corporation and others. All Rights Reserved. 6c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * 7c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * file name: digitaffixesandpadding.cpp 8c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 9c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 10c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "unicode/utypes.h" 11c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 12c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#if !UCONFIG_NO_FORMATTING 13c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 14c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "unicode/plurrule.h" 15c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "charstr.h" 16c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "digitaffix.h" 17c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "digitaffixesandpadding.h" 18c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "digitlst.h" 19c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "uassert.h" 20c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "valueformatter.h" 21c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include "visibledigits.h" 22c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 23c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertU_NAMESPACE_BEGIN 24c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 25c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertUBool 26c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitAffixesAndPadding::needsPluralRules() const { 27c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return ( 28c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert fPositivePrefix.hasMultipleVariants() || 29c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert fPositiveSuffix.hasMultipleVariants() || 30c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert fNegativePrefix.hasMultipleVariants() || 31c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert fNegativeSuffix.hasMultipleVariants()); 32c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 33c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 34c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertUnicodeString & 35c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitAffixesAndPadding::formatInt32( 36c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t value, 37c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const ValueFormatter &formatter, 38c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert FieldPositionHandler &handler, 39c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const PluralRules *optPluralRules, 40c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UnicodeString &appendTo, 41c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UErrorCode &status) const { 42c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (U_FAILURE(status)) { 43c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return appendTo; 44c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 45c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (optPluralRules != NULL || fWidth > 0 || !formatter.isFastFormattable(value)) { 46c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert VisibleDigitsWithExponent digits; 47c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatter.toVisibleDigitsWithExponent( 48c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert (int64_t) value, digits, status); 49c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return format( 50c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert digits, 51c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatter, 52c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert handler, 53c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert optPluralRules, 54c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert appendTo, 55c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert status); 56c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 57c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UBool bPositive = value >= 0; 58c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const DigitAffix *prefix = bPositive ? &fPositivePrefix.getOtherVariant() : &fNegativePrefix.getOtherVariant(); 59c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const DigitAffix *suffix = bPositive ? &fPositiveSuffix.getOtherVariant() : &fNegativeSuffix.getOtherVariant(); 60c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (value < 0) { 61c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert value = -value; 62c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 63c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert prefix->format(handler, appendTo); 64c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatter.formatInt32(value, handler, appendTo); 65c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return suffix->format(handler, appendTo); 66c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 67c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 68c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertstatic UnicodeString & 69c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertformatAffix( 70c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const DigitAffix *affix, 71c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert FieldPositionHandler &handler, 72c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UnicodeString &appendTo) { 73c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (affix) { 74c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert affix->format(handler, appendTo); 75c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 76c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return appendTo; 77c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 78c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 79c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertstatic int32_t 80c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertcountAffixChar32(const DigitAffix *affix) { 81c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (affix) { 82c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return affix->countChar32(); 83c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 84c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return 0; 85c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 86c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 87c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertUnicodeString & 88c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitAffixesAndPadding::format( 89c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const VisibleDigitsWithExponent &digits, 90c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const ValueFormatter &formatter, 91c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert FieldPositionHandler &handler, 92c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const PluralRules *optPluralRules, 93c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UnicodeString &appendTo, 94c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UErrorCode &status) const { 95c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (U_FAILURE(status)) { 96c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return appendTo; 97c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 98c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const DigitAffix *prefix = NULL; 99c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const DigitAffix *suffix = NULL; 100c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (!digits.isNaN()) { 101c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UBool bPositive = !digits.isNegative(); 102c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const PluralAffix *pluralPrefix = bPositive ? &fPositivePrefix : &fNegativePrefix; 103c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const PluralAffix *pluralSuffix = bPositive ? &fPositiveSuffix : &fNegativeSuffix; 104c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (optPluralRules == NULL || digits.isInfinite()) { 105c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert prefix = &pluralPrefix->getOtherVariant(); 106c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert suffix = &pluralSuffix->getOtherVariant(); 107c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } else { 108c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UnicodeString count(optPluralRules->select(digits)); 109c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert prefix = &pluralPrefix->getByCategory(count); 110c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert suffix = &pluralSuffix->getByCategory(count); 111c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 112c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 113c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (fWidth <= 0) { 114c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatAffix(prefix, handler, appendTo); 115c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatter.format(digits, handler, appendTo); 116c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return formatAffix(suffix, handler, appendTo); 117c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 118c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t codePointCount = countAffixChar32(prefix) + formatter.countChar32(digits) + countAffixChar32(suffix); 119c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t paddingCount = fWidth - codePointCount; 120c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert switch (fPadPosition) { 121c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert case kPadBeforePrefix: 122c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert appendPadding(paddingCount, appendTo); 123c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatAffix(prefix, handler, appendTo); 124c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatter.format(digits, handler, appendTo); 125c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return formatAffix(suffix, handler, appendTo); 126c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert case kPadAfterPrefix: 127c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatAffix(prefix, handler, appendTo); 128c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert appendPadding(paddingCount, appendTo); 129c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatter.format(digits, handler, appendTo); 130c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return formatAffix(suffix, handler, appendTo); 131c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert case kPadBeforeSuffix: 132c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatAffix(prefix, handler, appendTo); 133c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatter.format(digits, handler, appendTo); 134c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert appendPadding(paddingCount, appendTo); 135c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return formatAffix(suffix, handler, appendTo); 136c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert case kPadAfterSuffix: 137c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatAffix(prefix, handler, appendTo); 138c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatter.format(digits, handler, appendTo); 139c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatAffix(suffix, handler, appendTo); 140c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return appendPadding(paddingCount, appendTo); 141c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert default: 142c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert U_ASSERT(FALSE); 143c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return appendTo; 144c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 145c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 146c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 147c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertUnicodeString & 148c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitAffixesAndPadding::format( 149c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert DigitList &value, 150c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const ValueFormatter &formatter, 151c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert FieldPositionHandler &handler, 152c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert const PluralRules *optPluralRules, 153c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UnicodeString &appendTo, 154c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UErrorCode &status) const { 155c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert VisibleDigitsWithExponent digits; 156c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert formatter.toVisibleDigitsWithExponent( 157c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert value, digits, status); 158c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (U_FAILURE(status)) { 159c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return appendTo; 160c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 161c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return format( 162c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert digits, formatter, handler, optPluralRules, appendTo, status); 163c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 164c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 165c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertUnicodeString & 166c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDigitAffixesAndPadding::appendPadding(int32_t paddingCount, UnicodeString &appendTo) const { 167c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert for (int32_t i = 0; i < paddingCount; ++i) { 168c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert appendTo.append(fPadChar); 169c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 170c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert return appendTo; 171c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert} 172c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 173c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 174c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertU_NAMESPACE_END 175c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#endif /* #if !UCONFIG_NO_FORMATTING */ 176