xref: /aosp_15_r20/external/cronet/third_party/icu/source/i18n/numrange_capi.cpp (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // © 2018 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 
8 // Allow implicit conversion from char16_t* to UnicodeString for this file:
9 // Helpful in toString methods and elsewhere.
10 #define UNISTR_FROM_STRING_EXPLICIT
11 
12 #include "fphdlimp.h"
13 #include "number_utypes.h"
14 #include "numparse_types.h"
15 #include "formattedval_impl.h"
16 #include "numrange_impl.h"
17 #include "number_decnum.h"
18 #include "unicode/numberrangeformatter.h"
19 #include "unicode/unumberrangeformatter.h"
20 
21 using namespace icu;
22 using namespace icu::number;
23 using namespace icu::number::impl;
24 
25 
26 U_NAMESPACE_BEGIN
27 namespace number {
28 namespace impl {
29 
30 /**
31  * Implementation class for UNumberRangeFormatter. Wraps a LocalizedRangeNumberFormatter.
32  */
33 struct UNumberRangeFormatterData : public UMemory,
34         // Magic number as ASCII == "NRF" (NumberRangeFormatter)
35         public IcuCApiHelper<UNumberRangeFormatter, UNumberRangeFormatterData, 0x4E524600> {
36     LocalizedNumberRangeFormatter fFormatter;
37 };
38 
39 struct UFormattedNumberRangeImpl;
40 
41 // Magic number as ASCII == "FDN" (FormatteDNumber)
42 typedef IcuCApiHelper<UFormattedNumberRange, UFormattedNumberRangeImpl, 0x46444E00> UFormattedNumberRangeApiHelper;
43 
44 struct UFormattedNumberRangeImpl : public UFormattedValueImpl, public UFormattedNumberRangeApiHelper {
45     UFormattedNumberRangeImpl();
46     ~UFormattedNumberRangeImpl();
47 
48     FormattedNumberRange fImpl;
49     UFormattedNumberRangeData fData;
50 };
51 
UFormattedNumberRangeImpl()52 UFormattedNumberRangeImpl::UFormattedNumberRangeImpl()
53         : fImpl(&fData) {
54     fFormattedValue = &fImpl;
55 }
56 
~UFormattedNumberRangeImpl()57 UFormattedNumberRangeImpl::~UFormattedNumberRangeImpl() {
58     // Disown the data from fImpl so it doesn't get deleted twice
59     fImpl.fData = nullptr;
60 }
61 
62 } // namespace impl
63 } // namespace number
64 U_NAMESPACE_END
65 
66 
UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(UFormattedNumberRange,UFormattedNumberRangeImpl,UFormattedNumberRangeApiHelper,unumrf) const67 UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(
68     UFormattedNumberRange,
69     UFormattedNumberRangeImpl,
70     UFormattedNumberRangeApiHelper,
71     unumrf)
72 
73 
74 const UFormattedNumberRangeData* number::impl::validateUFormattedNumberRange(
75         const UFormattedNumberRange* uresult, UErrorCode& status) {
76     auto* result = UFormattedNumberRangeApiHelper::validate(uresult, status);
77     if (U_FAILURE(status)) {
78         return nullptr;
79     }
80     return &result->fData;
81 }
82 
83 
84 U_CAPI UNumberRangeFormatter* U_EXPORT2
unumrf_openForSkeletonWithCollapseAndIdentityFallback(const char16_t * skeleton,int32_t skeletonLen,UNumberRangeCollapse collapse,UNumberRangeIdentityFallback identityFallback,const char * locale,UParseError * perror,UErrorCode * ec)85 unumrf_openForSkeletonWithCollapseAndIdentityFallback(
86         const char16_t* skeleton,
87         int32_t skeletonLen,
88         UNumberRangeCollapse collapse,
89         UNumberRangeIdentityFallback identityFallback,
90         const char* locale,
91         UParseError* perror,
92         UErrorCode* ec) {
93     auto* impl = new UNumberRangeFormatterData();
94     if (impl == nullptr) {
95         *ec = U_MEMORY_ALLOCATION_ERROR;
96         return nullptr;
97     }
98     // Readonly-alias constructor (first argument is whether we are NUL-terminated)
99     UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
100     UParseError tempParseError;
101     impl->fFormatter = NumberRangeFormatter::withLocale(locale)
102         .numberFormatterBoth(NumberFormatter::forSkeleton(skeletonString, (perror == nullptr) ? tempParseError : *perror, *ec))
103         .collapse(collapse)
104         .identityFallback(identityFallback);
105     return impl->exportForC();
106 }
107 
108 U_CAPI void U_EXPORT2
unumrf_formatDoubleRange(const UNumberRangeFormatter * uformatter,double first,double second,UFormattedNumberRange * uresult,UErrorCode * ec)109 unumrf_formatDoubleRange(
110         const UNumberRangeFormatter* uformatter,
111         double first,
112         double second,
113         UFormattedNumberRange* uresult,
114         UErrorCode* ec) {
115     const UNumberRangeFormatterData* formatter = UNumberRangeFormatterData::validate(uformatter, *ec);
116     auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
117     if (U_FAILURE(*ec)) { return; }
118 
119     result->fData.resetString();
120     result->fData.quantity1.clear();
121     result->fData.quantity2.clear();
122     result->fData.quantity1.setToDouble(first);
123     result->fData.quantity2.setToDouble(second);
124     formatter->fFormatter.formatImpl(result->fData, first == second, *ec);
125 }
126 
127 U_CAPI void U_EXPORT2
unumrf_formatDecimalRange(const UNumberRangeFormatter * uformatter,const char * first,int32_t firstLen,const char * second,int32_t secondLen,UFormattedNumberRange * uresult,UErrorCode * ec)128 unumrf_formatDecimalRange(
129         const UNumberRangeFormatter* uformatter,
130         const char* first, int32_t firstLen,
131         const char* second, int32_t secondLen,
132         UFormattedNumberRange* uresult,
133         UErrorCode* ec) {
134     const UNumberRangeFormatterData* formatter = UNumberRangeFormatterData::validate(uformatter, *ec);
135     auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
136     if (U_FAILURE(*ec)) { return; }
137 
138     result->fData.resetString();
139     result->fData.quantity1.clear();
140     result->fData.quantity2.clear();
141     result->fData.quantity1.setToDecNumber({first, firstLen}, *ec);
142     result->fData.quantity2.setToDecNumber({second, secondLen}, *ec);
143     formatter->fFormatter.formatImpl(result->fData, first == second, *ec);
144 }
145 
146 U_CAPI UNumberRangeIdentityResult U_EXPORT2
unumrf_resultGetIdentityResult(const UFormattedNumberRange * uresult,UErrorCode * ec)147 unumrf_resultGetIdentityResult(
148         const UFormattedNumberRange* uresult,
149         UErrorCode* ec) {
150     auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
151     if (U_FAILURE(*ec)) {
152         return UNUM_IDENTITY_RESULT_COUNT;
153     }
154     return result->fData.identityResult;
155 }
156 
157 U_CAPI int32_t U_EXPORT2
unumrf_resultGetFirstDecimalNumber(const UFormattedNumberRange * uresult,char * dest,int32_t destCapacity,UErrorCode * ec)158 unumrf_resultGetFirstDecimalNumber(
159         const UFormattedNumberRange* uresult,
160         char* dest,
161         int32_t destCapacity,
162         UErrorCode* ec) {
163     const auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
164     if (U_FAILURE(*ec)) {
165         return 0;
166     }
167     DecNum decnum;
168     return result->fData.quantity1.toDecNum(decnum, *ec)
169         .toCharString(*ec)
170         .extract(dest, destCapacity, *ec);
171 }
172 
173 U_CAPI int32_t U_EXPORT2
unumrf_resultGetSecondDecimalNumber(const UFormattedNumberRange * uresult,char * dest,int32_t destCapacity,UErrorCode * ec)174 unumrf_resultGetSecondDecimalNumber(
175         const UFormattedNumberRange* uresult,
176         char* dest,
177         int32_t destCapacity,
178         UErrorCode* ec) {
179     const auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec);
180     if (U_FAILURE(*ec)) {
181         return 0;
182     }
183     DecNum decnum;
184     return result->fData.quantity2
185         .toDecNum(decnum, *ec)
186         .toCharString(*ec)
187         .extract(dest, destCapacity, *ec);
188 }
189 
190 U_CAPI void U_EXPORT2
unumrf_close(UNumberRangeFormatter * f)191 unumrf_close(UNumberRangeFormatter* f) {
192     UErrorCode localStatus = U_ZERO_ERROR;
193     const UNumberRangeFormatterData* impl = UNumberRangeFormatterData::validate(f, localStatus);
194     delete impl;
195 }
196 
197 
198 #endif /* #if !UCONFIG_NO_FORMATTING */
199