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