numrange_capi.cpp 6.2 KB

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