numrange_capi.cpp (6326B)
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 51 UFormattedNumberRangeImpl::UFormattedNumberRangeImpl() 52 : fImpl(&fData) { 53 fFormattedValue = &fImpl; 54 } 55 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 65 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 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 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 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 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 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 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 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 */