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