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(UNumberGroupingStrategy 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
};
54 Grouper
Grouper::forProperties(const DecimalFormatProperties
& properties
) {
55 if (!properties
.groupingUsed
) {
56 return forStrategy(UNUM_GROUPING_OFF
);
58 auto grouping1
= static_cast<int16_t>(properties
.groupingSize
);
59 auto grouping2
= static_cast<int16_t>(properties
.secondaryGroupingSize
);
60 auto minGrouping
= static_cast<int16_t>(properties
.minimumGroupingDigits
);
61 grouping1
= grouping1
> 0 ? grouping1
: grouping2
> 0 ? grouping2
: grouping1
;
62 grouping2
= grouping2
> 0 ? grouping2
: grouping1
;
63 minGrouping
= minGrouping
> 0 ? minGrouping
: -2; // use locale data if not set <rdar://problem/49808819>
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) {
69 if (fMinGrouping
== -2) { // add test <rdar://problem/49808819>
70 fMinGrouping
= getMinGroupingForLocale(locale
);
74 auto grouping1
= static_cast<int16_t> (patternInfo
.positive
.groupingSizes
& 0xffff);
75 auto grouping2
= static_cast<int16_t> ((patternInfo
.positive
.groupingSizes
>> 16) & 0xffff);
76 auto grouping3
= static_cast<int16_t> ((patternInfo
.positive
.groupingSizes
>> 32) & 0xffff);
77 if (grouping2
== -1) {
78 grouping1
= fGrouping1
== -4 ? (short) 3 : (short) -1;
80 if (grouping3
== -1) {
81 grouping2
= grouping1
;
83 if (fMinGrouping
== -2) {
84 fMinGrouping
= getMinGroupingForLocale(locale
);
85 } else if (fMinGrouping
== -3) {
86 fMinGrouping
= static_cast<int16_t>(uprv_max(2, getMinGroupingForLocale(locale
)));
88 // leave fMinGrouping alone
90 fGrouping1
= grouping1
;
91 fGrouping2
= grouping2
;
94 bool Grouper::groupAtPosition(int32_t position
, const impl::DecimalQuantity
&value
) const {
95 U_ASSERT(fGrouping1
> -2);
96 if (fGrouping1
== -1 || fGrouping1
== 0) {
97 // Either -1 or 0 means "no grouping"
100 position
-= fGrouping1
;
101 return position
>= 0 && (position
% fGrouping2
) == 0
102 && value
.getUpperDisplayMagnitude() - fGrouping1
+ 1 >= fMinGrouping
;
105 int16_t Grouper::getPrimary() const {
109 int16_t Grouper::getSecondary() const {
113 #endif /* #if !UCONFIG_NO_FORMATTING */