1 // © 2017 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 #include "unicode/utypes.h"
6 #if !UCONFIG_NO_FORMATTING
7 #ifndef __NUMBER_UTILS_H__
8 #define __NUMBER_UTILS_H__
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"
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
,
37 * Helper functions for dealing with the Field typedef, which stores fields
38 * in a compressed format.
42 struct CategoryFieldPair
{
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
);
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};
61 CategoryFieldPair ret
= {
65 if (ret
.category
== 0) {
66 ret
.category
= UFIELD_CATEGORY_NUMBER
;
71 static inline bool isNumericField(Field field
) {
72 int8_t category
= field
>> 4;
73 return category
== 0 || category
== UFIELD_CATEGORY_NUMBER
;
77 // Namespace for naked functions
80 inline int32_t insertDigitFromSymbols(NumberStringBuilder
& output
, int32_t index
, int8_t digit
,
81 const DecimalFormatSymbols
& symbols
, Field field
,
83 if (symbols
.getCodePointZero() != -1) {
84 return output
.insertCodePoint(index
, symbols
.getCodePointZero() + digit
, field
, status
);
86 return output
.insert(index
, symbols
.getConstDigitSymbol(digit
), field
, status
);
89 inline bool unitIsCurrency(const MeasureUnit
& unit
) {
90 return uprv_strcmp("currency", unit
.getType()) == 0;
93 inline bool unitIsNoUnit(const MeasureUnit
& unit
) {
94 return uprv_strcmp("none", unit
.getType()) == 0;
97 inline bool unitIsPercent(const MeasureUnit
& unit
) {
98 return uprv_strcmp("percent", unit
.getSubtype()) == 0;
101 inline bool unitIsPermille(const MeasureUnit
& unit
) {
102 return uprv_strcmp("permille", unit
.getSubtype()) == 0;
105 // NOTE: In Java, this method is in NumberFormat.java
107 getPatternForStyle(const Locale
& locale
, const char* nsName
, CldrPatternStyle style
, UErrorCode
& status
);
110 * Computes the plural form for this number based on the specified set of rules.
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.
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
;
122 UnicodeString ruleString
= rules
->select(fdec
);
123 return StandardPlural::orOtherFromString(ruleString
);
128 * Computes the plural form after copying the number and applying rounding rules.
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
;
141 return getStandardPlural(rules
, copy
);
147 } // namespace number
151 #endif //__NUMBER_UTILS_H__
153 #endif /* #if !UCONFIG_NO_FORMATTING */