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
23U_NAMESPACE_BEGIN
24
25UBool
26DigitAffixesAndPadding::needsPluralRules() const {
27    return (
28            fPositivePrefix.hasMultipleVariants() ||
29            fPositiveSuffix.hasMultipleVariants() ||
30            fNegativePrefix.hasMultipleVariants() ||
31            fNegativeSuffix.hasMultipleVariants());
32}
33
34UnicodeString &
35DigitAffixesAndPadding::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
68static UnicodeString &
69formatAffix(
70        const DigitAffix *affix,
71        FieldPositionHandler &handler,
72        UnicodeString &appendTo) {
73    if (affix) {
74        affix->format(handler, appendTo);
75    }
76    return appendTo;
77}
78
79static int32_t
80countAffixChar32(const DigitAffix *affix) {
81    if (affix) {
82        return affix->countChar32();
83    }
84    return 0;
85}
86
87UnicodeString &
88DigitAffixesAndPadding::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
147UnicodeString &
148DigitAffixesAndPadding::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
165UnicodeString &
166DigitAffixesAndPadding::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
174U_NAMESPACE_END
175#endif /* #if !UCONFIG_NO_FORMATTING */
176