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