number_capi.cpp (13321B)
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 "number_decnum.h" 17 #include "unicode/numberformatter.h" 18 #include "unicode/unumberformatter.h" 19 #include "unicode/simplenumberformatter.h" 20 #include "unicode/usimplenumberformatter.h" 21 22 using namespace icu; 23 using namespace icu::number; 24 using namespace icu::number::impl; 25 26 27 U_NAMESPACE_BEGIN 28 namespace number::impl { 29 30 /** 31 * Implementation class for UNumberFormatter. Wraps a LocalizedNumberFormatter. 32 */ 33 struct UNumberFormatterData : public UMemory, 34 // Magic number as ASCII == "NFR" (NumberFormatteR) 35 public IcuCApiHelper<UNumberFormatter, UNumberFormatterData, 0x4E465200> { 36 LocalizedNumberFormatter fFormatter; 37 }; 38 39 /** 40 * Implementation class for USimpleNumber. Wraps a SimpleNumberFormatter. 41 */ 42 struct USimpleNumberData : public UMemory, 43 // Magic number as ASCII == "SNM" (SimpleNuMber) 44 public IcuCApiHelper<USimpleNumber, USimpleNumberData, 0x534E4D00> { 45 SimpleNumber fNumber; 46 }; 47 48 /** 49 * Implementation class for USimpleNumberFormatter. Wraps a SimpleNumberFormatter. 50 */ 51 struct USimpleNumberFormatterData : public UMemory, 52 // Magic number as ASCII == "SNF" (SimpleNumberFormatter) 53 public IcuCApiHelper<USimpleNumberFormatter, USimpleNumberFormatterData, 0x534E4600> { 54 SimpleNumberFormatter fFormatter; 55 }; 56 57 struct UFormattedNumberImpl; 58 59 // Magic number as ASCII == "FDN" (FormatteDNumber) 60 typedef IcuCApiHelper<UFormattedNumber, UFormattedNumberImpl, 0x46444E00> UFormattedNumberApiHelper; 61 62 struct UFormattedNumberImpl : public UFormattedValueImpl, public UFormattedNumberApiHelper { 63 UFormattedNumberImpl(); 64 ~UFormattedNumberImpl(); 65 66 FormattedNumber fImpl; 67 UFormattedNumberData fData; 68 69 void setTo(FormattedNumber value); 70 }; 71 72 UFormattedNumberImpl::UFormattedNumberImpl() 73 : fImpl(&fData) { 74 fFormattedValue = &fImpl; 75 } 76 77 UFormattedNumberImpl::~UFormattedNumberImpl() { 78 // Disown the data from fImpl so it doesn't get deleted twice 79 fImpl.fData = nullptr; 80 } 81 82 void UFormattedNumberImpl::setTo(FormattedNumber value) { 83 fData = std::move(*value.fData); 84 } 85 86 } // namespace number::impl 87 U_NAMESPACE_END 88 89 90 UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL( 91 UFormattedNumber, 92 UFormattedNumberImpl, 93 UFormattedNumberApiHelper, 94 unumf) 95 96 97 const DecimalQuantity* icu::number::impl::validateUFormattedNumberToDecimalQuantity( 98 const UFormattedNumber* uresult, UErrorCode& status) { 99 const auto* result = UFormattedNumberApiHelper::validate(uresult, status); 100 if (U_FAILURE(status)) { 101 return nullptr; 102 } 103 return &result->fData.quantity; 104 } 105 106 107 108 U_CAPI UNumberFormatter* U_EXPORT2 109 unumf_openForSkeletonAndLocale(const char16_t* skeleton, int32_t skeletonLen, const char* locale, 110 UErrorCode* ec) { 111 auto* impl = new UNumberFormatterData(); 112 if (impl == nullptr) { 113 *ec = U_MEMORY_ALLOCATION_ERROR; 114 return nullptr; 115 } 116 // Readonly-alias constructor (first argument is whether we are NUL-terminated) 117 UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen); 118 impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, *ec).locale(locale); 119 return impl->exportForC(); 120 } 121 122 U_CAPI UNumberFormatter* U_EXPORT2 123 unumf_openForSkeletonAndLocaleWithError(const char16_t* skeleton, int32_t skeletonLen, const char* locale, 124 UParseError* perror, UErrorCode* ec) { 125 auto* impl = new UNumberFormatterData(); 126 if (impl == nullptr) { 127 *ec = U_MEMORY_ALLOCATION_ERROR; 128 return nullptr; 129 } 130 // Readonly-alias constructor (first argument is whether we are NUL-terminated) 131 UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen); 132 UParseError tempParseError; 133 impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, (perror == nullptr) ? tempParseError : *perror, *ec).locale(locale); 134 return impl->exportForC(); 135 } 136 137 U_CAPI void U_EXPORT2 138 unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult, 139 UErrorCode* ec) { 140 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec); 141 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec); 142 if (U_FAILURE(*ec)) { return; } 143 144 result->fData.resetString(); 145 result->fData.quantity.clear(); 146 result->fData.quantity.setToLong(value); 147 formatter->fFormatter.formatImpl(&result->fData, *ec); 148 } 149 150 U_CAPI void U_EXPORT2 151 unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult, 152 UErrorCode* ec) { 153 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec); 154 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec); 155 if (U_FAILURE(*ec)) { return; } 156 157 result->fData.resetString(); 158 result->fData.quantity.clear(); 159 result->fData.quantity.setToDouble(value); 160 formatter->fFormatter.formatImpl(&result->fData, *ec); 161 } 162 163 U_CAPI void U_EXPORT2 164 unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen, 165 UFormattedNumber* uresult, UErrorCode* ec) { 166 const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec); 167 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec); 168 if (U_FAILURE(*ec)) { return; } 169 170 result->fData.resetString(); 171 result->fData.quantity.clear(); 172 result->fData.quantity.setToDecNumber({value, valueLen}, *ec); 173 if (U_FAILURE(*ec)) { return; } 174 formatter->fFormatter.formatImpl(&result->fData, *ec); 175 } 176 177 U_CAPI int32_t U_EXPORT2 178 unumf_resultToString(const UFormattedNumber* uresult, char16_t* buffer, int32_t bufferCapacity, 179 UErrorCode* ec) { 180 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec); 181 if (U_FAILURE(*ec)) { return 0; } 182 183 if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) { 184 *ec = U_ILLEGAL_ARGUMENT_ERROR; 185 return 0; 186 } 187 188 return result->fData.toTempString(*ec).extract(buffer, bufferCapacity, *ec); 189 } 190 191 U_CAPI UBool U_EXPORT2 192 unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec) { 193 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec); 194 if (U_FAILURE(*ec)) { return false; } 195 196 if (ufpos == nullptr) { 197 *ec = U_ILLEGAL_ARGUMENT_ERROR; 198 return false; 199 } 200 201 FieldPosition fp; 202 fp.setField(ufpos->field); 203 fp.setBeginIndex(ufpos->beginIndex); 204 fp.setEndIndex(ufpos->endIndex); 205 bool retval = result->fData.nextFieldPosition(fp, *ec); 206 ufpos->beginIndex = fp.getBeginIndex(); 207 ufpos->endIndex = fp.getEndIndex(); 208 // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool 209 return retval ? true : false; 210 } 211 212 U_CAPI void U_EXPORT2 213 unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer, 214 UErrorCode* ec) { 215 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec); 216 if (U_FAILURE(*ec)) { return; } 217 218 if (ufpositer == nullptr) { 219 *ec = U_ILLEGAL_ARGUMENT_ERROR; 220 return; 221 } 222 223 auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer); 224 FieldPositionIteratorHandler fpih(fpi, *ec); 225 result->fData.getAllFieldPositions(fpih, *ec); 226 } 227 228 U_CAPI int32_t U_EXPORT2 229 unumf_resultToDecimalNumber( 230 const UFormattedNumber* uresult, 231 char* dest, 232 int32_t destCapacity, 233 UErrorCode* ec) { 234 const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec); 235 if (U_FAILURE(*ec)) { 236 return 0; 237 } 238 DecNum decnum; 239 return result->fData.quantity 240 .toDecNum(decnum, *ec) 241 .toCharString(*ec) 242 .extract(dest, destCapacity, *ec); 243 } 244 245 U_CAPI void U_EXPORT2 246 unumf_close(UNumberFormatter* f) { 247 UErrorCode localStatus = U_ZERO_ERROR; 248 const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus); 249 delete impl; 250 } 251 252 253 ///// SIMPLE NUMBER FORMATTER ///// 254 255 U_CAPI USimpleNumber* U_EXPORT2 256 usnum_openForInt64(int64_t value, UErrorCode* ec) { 257 auto* number = new USimpleNumberData(); 258 if (number == nullptr) { 259 *ec = U_MEMORY_ALLOCATION_ERROR; 260 return nullptr; 261 } 262 number->fNumber = SimpleNumber::forInt64(value, *ec); 263 return number->exportForC(); 264 } 265 266 U_CAPI void U_EXPORT2 267 usnum_setToInt64(USimpleNumber* unumber, int64_t value, UErrorCode* ec) { 268 auto* number = USimpleNumberData::validate(unumber, *ec); 269 if (U_FAILURE(*ec)) { 270 return; 271 } 272 number->fNumber = SimpleNumber::forInt64(value, *ec); 273 } 274 275 U_CAPI void U_EXPORT2 276 usnum_multiplyByPowerOfTen(USimpleNumber* unumber, int32_t power, UErrorCode* ec) { 277 auto* number = USimpleNumberData::validate(unumber, *ec); 278 if (U_FAILURE(*ec)) { 279 return; 280 } 281 number->fNumber.multiplyByPowerOfTen(power, *ec); 282 } 283 284 U_CAPI void U_EXPORT2 285 usnum_roundTo(USimpleNumber* unumber, int32_t position, UNumberFormatRoundingMode roundingMode, UErrorCode* ec) { 286 auto* number = USimpleNumberData::validate(unumber, *ec); 287 if (U_FAILURE(*ec)) { 288 return; 289 } 290 number->fNumber.roundTo(position, roundingMode, *ec); 291 } 292 293 U_CAPI void U_EXPORT2 294 usnum_setMinimumIntegerDigits(USimpleNumber* unumber, int32_t minimumIntegerDigits, UErrorCode* ec) { 295 auto* number = USimpleNumberData::validate(unumber, *ec); 296 if (U_FAILURE(*ec)) { 297 return; 298 } 299 number->fNumber.setMinimumIntegerDigits(minimumIntegerDigits, *ec); 300 } 301 302 U_CAPI void U_EXPORT2 303 usnum_setMinimumFractionDigits(USimpleNumber* unumber, int32_t minimumFractionDigits, UErrorCode* ec) { 304 auto* number = USimpleNumberData::validate(unumber, *ec); 305 if (U_FAILURE(*ec)) { 306 return; 307 } 308 number->fNumber.setMinimumFractionDigits(minimumFractionDigits, *ec); 309 } 310 311 U_CAPI void U_EXPORT2 312 usnum_setMaximumIntegerDigits(USimpleNumber* unumber, int32_t maximumIntegerDigits, UErrorCode* ec) { 313 auto* number = USimpleNumberData::validate(unumber, *ec); 314 if (U_FAILURE(*ec)) { 315 return; 316 } 317 number->fNumber.setMaximumIntegerDigits(maximumIntegerDigits, *ec); 318 } 319 320 U_CAPI void U_EXPORT2 321 usnum_setSign(USimpleNumber* unumber, USimpleNumberSign sign, UErrorCode* ec) { 322 auto* number = USimpleNumberData::validate(unumber, *ec); 323 if (U_FAILURE(*ec)) { 324 return; 325 } 326 number->fNumber.setSign(sign, *ec); 327 } 328 329 U_CAPI USimpleNumberFormatter* U_EXPORT2 330 usnumf_openForLocale(const char* locale, UErrorCode* ec) { 331 auto* impl = new USimpleNumberFormatterData(); 332 if (impl == nullptr) { 333 *ec = U_MEMORY_ALLOCATION_ERROR; 334 return nullptr; 335 } 336 impl->fFormatter = SimpleNumberFormatter::forLocale(locale, *ec); 337 return impl->exportForC(); 338 } 339 340 U_CAPI USimpleNumberFormatter* U_EXPORT2 341 usnumf_openForLocaleAndGroupingStrategy( 342 const char* locale, UNumberGroupingStrategy groupingStrategy, UErrorCode* ec) { 343 auto* impl = new USimpleNumberFormatterData(); 344 if (impl == nullptr) { 345 *ec = U_MEMORY_ALLOCATION_ERROR; 346 return nullptr; 347 } 348 impl->fFormatter = SimpleNumberFormatter::forLocaleAndGroupingStrategy(locale, groupingStrategy, *ec); 349 return impl->exportForC(); 350 } 351 352 U_CAPI void U_EXPORT2 353 usnumf_format( 354 const USimpleNumberFormatter* uformatter, 355 USimpleNumber* unumber, 356 UFormattedNumber* uresult, 357 UErrorCode* ec) { 358 const auto* formatter = USimpleNumberFormatterData::validate(uformatter, *ec); 359 auto* number = USimpleNumberData::validate(unumber, *ec); 360 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec); 361 if (U_FAILURE(*ec)) { 362 return; 363 } 364 auto localResult = formatter->fFormatter.format(std::move(number->fNumber), *ec); 365 if (U_FAILURE(*ec)) { 366 return; 367 } 368 result->setTo(std::move(localResult)); 369 } 370 371 U_CAPI void U_EXPORT2 372 usnumf_formatInt64( 373 const USimpleNumberFormatter* uformatter, 374 int64_t value, 375 UFormattedNumber* uresult, 376 UErrorCode* ec) { 377 const auto* formatter = USimpleNumberFormatterData::validate(uformatter, *ec); 378 auto* result = UFormattedNumberApiHelper::validate(uresult, *ec); 379 if (U_FAILURE(*ec)) { 380 return; 381 } 382 auto localResult = formatter->fFormatter.formatInt64(value, *ec); 383 result->setTo(std::move(localResult)); 384 } 385 386 U_CAPI void U_EXPORT2 387 usnum_close(USimpleNumber* unumber) { 388 UErrorCode localStatus = U_ZERO_ERROR; 389 const USimpleNumberData* impl = USimpleNumberData::validate(unumber, localStatus); 390 delete impl; 391 } 392 393 U_CAPI void U_EXPORT2 394 usnumf_close(USimpleNumberFormatter* uformatter) { 395 UErrorCode localStatus = U_ZERO_ERROR; 396 const USimpleNumberFormatterData* impl = USimpleNumberFormatterData::validate(uformatter, localStatus); 397 delete impl; 398 } 399 400 401 #endif /* #if !UCONFIG_NO_FORMATTING */