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
8 #include "unicode/numberformatter.h"
9 #include "number_patternstring.h"
13 using namespace icu::number
;
14 using namespace icu::number::impl
;
18 int16_t getMinGroupingForLocale(const Locale
& locale
) {
20 UErrorCode localStatus
= U_ZERO_ERROR
;
21 LocalUResourceBundlePointer
bundle(ures_open(NULL
, locale
.getName(), &localStatus
));
22 int32_t resultLen
= 0;
23 const char16_t* result
= ures_getStringByKeyWithFallback(
25 "NumberElements/minimumGroupingDigits",
28 // TODO: Is it safe to assume resultLen == 1? Would locales set minGrouping >= 10?
29 if (U_FAILURE(localStatus
) || resultLen
!= 1) {
32 return result
[0] - u
'0';
37 Grouper
Grouper::forStrategy(UGroupingStrategy grouping
) {
39 case UNUM_GROUPING_OFF
:
40 return {-1, -1, -2, grouping
};
41 case UNUM_GROUPING_AUTO
:
42 return {-2, -2, -2, grouping
};
43 case UNUM_GROUPING_MIN2
:
44 return {-2, -2, -3, grouping
};
45 case UNUM_GROUPING_ON_ALIGNED
:
46 return {-4, -4, 1, grouping
};
47 case UNUM_GROUPING_THOUSANDS
:
48 return {3, 3, 1, grouping
};
51 return {}; // return a value: silence compiler warning
55 Grouper
Grouper::forProperties(const DecimalFormatProperties
& properties
) {
56 if (!properties
.groupingUsed
) {
57 return forStrategy(UNUM_GROUPING_OFF
);
59 auto grouping1
= static_cast<int16_t>(properties
.groupingSize
);
60 auto grouping2
= static_cast<int16_t>(properties
.secondaryGroupingSize
);
61 auto minGrouping
= static_cast<int16_t>(properties
.minimumGroupingDigits
);
62 grouping1
= grouping1
> 0 ? grouping1
: grouping2
> 0 ? grouping2
: grouping1
;
63 grouping2
= grouping2
> 0 ? grouping2
: grouping1
;
64 return {grouping1
, grouping2
, minGrouping
, UNUM_GROUPING_COUNT
};
67 void Grouper::setLocaleData(const impl::ParsedPatternInfo
&patternInfo
, const Locale
& locale
) {
68 if (fGrouping1
!= -2 && fGrouping2
!= -4) {
71 auto grouping1
= static_cast<int16_t> (patternInfo
.positive
.groupingSizes
& 0xffff);
72 auto grouping2
= static_cast<int16_t> ((patternInfo
.positive
.groupingSizes
>> 16) & 0xffff);
73 auto grouping3
= static_cast<int16_t> ((patternInfo
.positive
.groupingSizes
>> 32) & 0xffff);
74 if (grouping2
== -1) {
75 grouping1
= fGrouping1
== -4 ? (short) 3 : (short) -1;
77 if (grouping3
== -1) {
78 grouping2
= grouping1
;
80 if (fMinGrouping
== -2) {
81 fMinGrouping
= getMinGroupingForLocale(locale
);
82 } else if (fMinGrouping
== -3) {
83 fMinGrouping
= uprv_max(2, getMinGroupingForLocale(locale
));
85 // leave fMinGrouping alone
87 fGrouping1
= grouping1
;
88 fGrouping2
= grouping2
;
91 bool Grouper::groupAtPosition(int32_t position
, const impl::DecimalQuantity
&value
) const {
92 U_ASSERT(fGrouping1
> -2);
93 if (fGrouping1
== -1 || fGrouping1
== 0) {
94 // Either -1 or 0 means "no grouping"
97 position
-= fGrouping1
;
98 return position
>= 0 && (position
% fGrouping2
) == 0
99 && value
.getUpperDisplayMagnitude() - fGrouping1
+ 1 >= fMinGrouping
;
102 int16_t Grouper::getPrimary() const {
106 int16_t Grouper::getSecondary() const {
110 #endif /* #if !UCONFIG_NO_FORMATTING */