]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/number_utils.h
ICU-64260.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / number_utils.h
1 // © 2017 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3
4 #include "unicode/utypes.h"
5
6 #if !UCONFIG_NO_FORMATTING
7 #ifndef __NUMBER_UTILS_H__
8 #define __NUMBER_UTILS_H__
9
10 #include "unicode/numberformatter.h"
11 #include "number_types.h"
12 #include "number_decimalquantity.h"
13 #include "number_scientific.h"
14 #include "number_patternstring.h"
15 #include "number_modifiers.h"
16 #include "number_multiplier.h"
17 #include "number_roundingutils.h"
18 #include "decNumber.h"
19 #include "charstr.h"
20
21 U_NAMESPACE_BEGIN
22
23 namespace number {
24 namespace impl {
25
26 enum CldrPatternStyle {
27 CLDR_PATTERN_STYLE_DECIMAL,
28 CLDR_PATTERN_STYLE_CURRENCY,
29 CLDR_PATTERN_STYLE_ACCOUNTING,
30 CLDR_PATTERN_STYLE_PERCENT,
31 CLDR_PATTERN_STYLE_SCIENTIFIC,
32 CLDR_PATTERN_STYLE_COUNT,
33 };
34
35
36 /**
37 * Helper functions for dealing with the Field typedef, which stores fields
38 * in a compressed format.
39 */
40 class NumFieldUtils {
41 public:
42 struct CategoryFieldPair {
43 int32_t category;
44 int32_t field;
45 };
46
47 /** Compile-time function to construct a Field from a category and a field */
48 template <int32_t category, int32_t field>
49 static constexpr Field compress() {
50 static_assert(category != 0, "cannot use Undefined category in NumFieldUtils");
51 static_assert(category <= 0xf, "only 4 bits for category");
52 static_assert(field <= 0xf, "only 4 bits for field");
53 return static_cast<int8_t>((category << 4) | field);
54 }
55
56 /** Runtime inline function to unpack the category and field from the Field */
57 static inline CategoryFieldPair expand(Field field) {
58 if (field == UNUM_FIELD_COUNT) {
59 return {UFIELD_CATEGORY_UNDEFINED, 0};
60 }
61 CategoryFieldPair ret = {
62 (field >> 4),
63 (field & 0xf)
64 };
65 if (ret.category == 0) {
66 ret.category = UFIELD_CATEGORY_NUMBER;
67 }
68 return ret;
69 }
70
71 static inline bool isNumericField(Field field) {
72 int8_t category = field >> 4;
73 return category == 0 || category == UFIELD_CATEGORY_NUMBER;
74 }
75 };
76
77 // Namespace for naked functions
78 namespace utils {
79
80 inline int32_t insertDigitFromSymbols(NumberStringBuilder& output, int32_t index, int8_t digit,
81 const DecimalFormatSymbols& symbols, Field field,
82 UErrorCode& status) {
83 if (symbols.getCodePointZero() != -1) {
84 return output.insertCodePoint(index, symbols.getCodePointZero() + digit, field, status);
85 }
86 return output.insert(index, symbols.getConstDigitSymbol(digit), field, status);
87 }
88
89 inline bool unitIsCurrency(const MeasureUnit& unit) {
90 return uprv_strcmp("currency", unit.getType()) == 0;
91 }
92
93 inline bool unitIsNoUnit(const MeasureUnit& unit) {
94 return uprv_strcmp("none", unit.getType()) == 0;
95 }
96
97 inline bool unitIsPercent(const MeasureUnit& unit) {
98 return uprv_strcmp("percent", unit.getSubtype()) == 0;
99 }
100
101 inline bool unitIsPermille(const MeasureUnit& unit) {
102 return uprv_strcmp("permille", unit.getSubtype()) == 0;
103 }
104
105 // NOTE: In Java, this method is in NumberFormat.java
106 const char16_t*
107 getPatternForStyle(const Locale& locale, const char* nsName, CldrPatternStyle style, UErrorCode& status);
108
109 /**
110 * Computes the plural form for this number based on the specified set of rules.
111 *
112 * @param rules A {@link PluralRules} object representing the set of rules.
113 * @return The {@link StandardPlural} according to the PluralRules. If the plural form is not in
114 * the set of standard plurals, {@link StandardPlural#OTHER} is returned instead.
115 */
116 inline StandardPlural::Form getStandardPlural(const PluralRules *rules,
117 const IFixedDecimal &fdec) {
118 if (rules == nullptr) {
119 // Fail gracefully if the user didn't provide a PluralRules
120 return StandardPlural::Form::OTHER;
121 } else {
122 UnicodeString ruleString = rules->select(fdec);
123 return StandardPlural::orOtherFromString(ruleString);
124 }
125 }
126
127 /**
128 * Computes the plural form after copying the number and applying rounding rules.
129 */
130 inline StandardPlural::Form getPluralSafe(
131 const RoundingImpl& rounder,
132 const PluralRules* rules,
133 const DecimalQuantity& dq,
134 UErrorCode& status) {
135 // TODO(ICU-20500): Avoid the copy?
136 DecimalQuantity copy(dq);
137 rounder.apply(copy, status);
138 if (U_FAILURE(status)) {
139 return StandardPlural::Form::OTHER;
140 }
141 return getStandardPlural(rules, copy);
142 }
143
144 } // namespace utils
145
146 } // namespace impl
147 } // namespace number
148
149 U_NAMESPACE_END
150
151 #endif //__NUMBER_UTILS_H__
152
153 #endif /* #if !UCONFIG_NO_FORMATTING */