| // © 2018 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| |
| #include "unicode/utypes.h" |
| |
| #if !UCONFIG_NO_FORMATTING |
| |
| // Allow implicit conversion from char16_t* to UnicodeString for this file: |
| // Helpful in toString methods and elsewhere. |
| #define UNISTR_FROM_STRING_EXPLICIT |
| |
| #include "fphdlimp.h" |
| #include "number_utypes.h" |
| #include "numparse_types.h" |
| #include "formattedval_impl.h" |
| #include "numrange_impl.h" |
| #include "number_decnum.h" |
| #include "unicode/numberrangeformatter.h" |
| #include "unicode/unumberrangeformatter.h" |
| |
| using namespace icu; |
| using namespace icu::number; |
| using namespace icu::number::impl; |
| |
| |
| U_NAMESPACE_BEGIN |
| namespace number { |
| namespace impl { |
| |
| /** |
| * Implementation class for UNumberRangeFormatter. Wraps a LocalizedRangeNumberFormatter. |
| */ |
| struct UNumberRangeFormatterData : public UMemory, |
| // Magic number as ASCII == "NRF" (NumberRangeFormatter) |
| public IcuCApiHelper<UNumberRangeFormatter, UNumberRangeFormatterData, 0x4E524600> { |
| LocalizedNumberRangeFormatter fFormatter; |
| }; |
| |
| struct UFormattedNumberRangeImpl; |
| |
| // Magic number as ASCII == "FDN" (FormatteDNumber) |
| typedef IcuCApiHelper<UFormattedNumberRange, UFormattedNumberRangeImpl, 0x46444E00> UFormattedNumberRangeApiHelper; |
| |
| struct UFormattedNumberRangeImpl : public UFormattedValueImpl, public UFormattedNumberRangeApiHelper { |
| UFormattedNumberRangeImpl(); |
| ~UFormattedNumberRangeImpl(); |
| |
| FormattedNumberRange fImpl; |
| UFormattedNumberRangeData fData; |
| }; |
| |
| UFormattedNumberRangeImpl::UFormattedNumberRangeImpl() |
| : fImpl(&fData) { |
| fFormattedValue = &fImpl; |
| } |
| |
| UFormattedNumberRangeImpl::~UFormattedNumberRangeImpl() { |
| // Disown the data from fImpl so it doesn't get deleted twice |
| fImpl.fData = nullptr; |
| } |
| |
| } // namespace impl |
| } // namespace number |
| U_NAMESPACE_END |
| |
| |
| UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL( |
| UFormattedNumberRange, |
| UFormattedNumberRangeImpl, |
| UFormattedNumberRangeApiHelper, |
| unumrf) |
| |
| |
| const UFormattedNumberRangeData* number::impl::validateUFormattedNumberRange( |
| const UFormattedNumberRange* uresult, UErrorCode& status) { |
| auto* result = UFormattedNumberRangeApiHelper::validate(uresult, status); |
| if (U_FAILURE(status)) { |
| return nullptr; |
| } |
| return &result->fData; |
| } |
| |
| |
| U_CAPI UNumberRangeFormatter* U_EXPORT2 |
| unumrf_openForSkeletonWithCollapseAndIdentityFallback( |
| const UChar* skeleton, |
| int32_t skeletonLen, |
| UNumberRangeCollapse collapse, |
| UNumberRangeIdentityFallback identityFallback, |
| const char* locale, |
| UParseError* perror, |
| UErrorCode* ec) { |
| auto* impl = new UNumberRangeFormatterData(); |
| if (impl == nullptr) { |
| *ec = U_MEMORY_ALLOCATION_ERROR; |
| return nullptr; |
| } |
| // Readonly-alias constructor (first argument is whether we are NUL-terminated) |
| UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen); |
| impl->fFormatter = NumberRangeFormatter::withLocale(locale) |
| .numberFormatterBoth(NumberFormatter::forSkeleton(skeletonString, *perror, *ec)) |
| .collapse(collapse) |
| .identityFallback(identityFallback); |
| return impl->exportForC(); |
| } |
| |
| U_CAPI void U_EXPORT2 |
| unumrf_formatDoubleRange( |
| const UNumberRangeFormatter* uformatter, |
| double first, |
| double second, |
| UFormattedNumberRange* uresult, |
| UErrorCode* ec) { |
| const UNumberRangeFormatterData* formatter = UNumberRangeFormatterData::validate(uformatter, *ec); |
| auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec); |
| if (U_FAILURE(*ec)) { return; } |
| |
| result->fData.getStringRef().clear(); |
| result->fData.quantity1.setToDouble(first); |
| result->fData.quantity2.setToDouble(second); |
| formatter->fFormatter.formatImpl(result->fData, first == second, *ec); |
| } |
| |
| 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) { |
| const UNumberRangeFormatterData* formatter = UNumberRangeFormatterData::validate(uformatter, *ec); |
| auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec); |
| if (U_FAILURE(*ec)) { return; } |
| |
| result->fData.getStringRef().clear(); |
| result->fData.quantity1.setToDecNumber({first, firstLen}, *ec); |
| result->fData.quantity2.setToDecNumber({second, secondLen}, *ec); |
| formatter->fFormatter.formatImpl(result->fData, first == second, *ec); |
| } |
| |
| U_CAPI UNumberRangeIdentityResult U_EXPORT2 |
| unumrf_resultGetIdentityResult( |
| const UFormattedNumberRange* uresult, |
| UErrorCode* ec) { |
| auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec); |
| if (U_FAILURE(*ec)) { |
| return UNUM_IDENTITY_RESULT_COUNT; |
| } |
| return result->fData.identityResult; |
| } |
| |
| U_CAPI int32_t U_EXPORT2 |
| unumrf_resultGetFirstDecimalNumber( |
| const UFormattedNumberRange* uresult, |
| char* dest, |
| int32_t destCapacity, |
| UErrorCode* ec) { |
| const auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec); |
| if (U_FAILURE(*ec)) { |
| return 0; |
| } |
| DecNum decnum; |
| return result->fData.quantity1.toDecNum(decnum, *ec) |
| .toCharString(*ec) |
| .extract(dest, destCapacity, *ec); |
| } |
| |
| U_CAPI int32_t U_EXPORT2 |
| unumrf_resultGetSecondDecimalNumber( |
| const UFormattedNumberRange* uresult, |
| char* dest, |
| int32_t destCapacity, |
| UErrorCode* ec) { |
| const auto* result = UFormattedNumberRangeApiHelper::validate(uresult, *ec); |
| if (U_FAILURE(*ec)) { |
| return 0; |
| } |
| DecNum decnum; |
| return result->fData.quantity2 |
| .toDecNum(decnum, *ec) |
| .toCharString(*ec) |
| .extract(dest, destCapacity, *ec); |
| } |
| |
| U_CAPI void U_EXPORT2 |
| unumrf_close(UNumberRangeFormatter* f) { |
| UErrorCode localStatus = U_ZERO_ERROR; |
| const UNumberRangeFormatterData* impl = UNumberRangeFormatterData::validate(f, localStatus); |
| delete impl; |
| } |
| |
| |
| #endif /* #if !UCONFIG_NO_FORMATTING */ |