number_mapper.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. #ifndef __NUMBER_MAPPER_H__
  6. #define __NUMBER_MAPPER_H__
  7. #include <atomic>
  8. #include "number_types.h"
  9. #include "unicode/currpinf.h"
  10. #include "standardplural.h"
  11. #include "number_patternstring.h"
  12. #include "number_currencysymbols.h"
  13. #include "numparse_impl.h"
  14. U_NAMESPACE_BEGIN
  15. namespace number {
  16. namespace impl {
  17. class AutoAffixPatternProvider;
  18. class CurrencyPluralInfoAffixProvider;
  19. class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemory {
  20. public:
  21. bool isBogus() const {
  22. return fBogus;
  23. }
  24. void setToBogus() {
  25. fBogus = true;
  26. }
  27. void setTo(const DecimalFormatProperties& properties, UErrorCode& status);
  28. // AffixPatternProvider Methods:
  29. char16_t charAt(int32_t flags, int32_t i) const override;
  30. int32_t length(int32_t flags) const override;
  31. UnicodeString getString(int32_t flags) const override;
  32. bool hasCurrencySign() const override;
  33. bool positiveHasPlusSign() const override;
  34. bool hasNegativeSubpattern() const override;
  35. bool negativeHasMinusSign() const override;
  36. bool containsSymbolType(AffixPatternType, UErrorCode&) const override;
  37. bool hasBody() const override;
  38. bool currencyAsDecimal() const override;
  39. private:
  40. UnicodeString posPrefix;
  41. UnicodeString posSuffix;
  42. UnicodeString negPrefix;
  43. UnicodeString negSuffix;
  44. bool isCurrencyPattern;
  45. bool fCurrencyAsDecimal;
  46. PropertiesAffixPatternProvider() = default; // puts instance in valid but undefined state
  47. const UnicodeString& getStringInternal(int32_t flags) const;
  48. bool fBogus{true};
  49. friend class AutoAffixPatternProvider;
  50. friend class CurrencyPluralInfoAffixProvider;
  51. };
  52. class CurrencyPluralInfoAffixProvider : public AffixPatternProvider, public UMemory {
  53. public:
  54. bool isBogus() const {
  55. return fBogus;
  56. }
  57. void setToBogus() {
  58. fBogus = true;
  59. }
  60. void setTo(const CurrencyPluralInfo& cpi, const DecimalFormatProperties& properties,
  61. UErrorCode& status);
  62. // AffixPatternProvider Methods:
  63. char16_t charAt(int32_t flags, int32_t i) const override;
  64. int32_t length(int32_t flags) const override;
  65. UnicodeString getString(int32_t flags) const override;
  66. bool hasCurrencySign() const override;
  67. bool positiveHasPlusSign() const override;
  68. bool hasNegativeSubpattern() const override;
  69. bool negativeHasMinusSign() const override;
  70. bool containsSymbolType(AffixPatternType, UErrorCode&) const override;
  71. bool hasBody() const override;
  72. bool currencyAsDecimal() const override;
  73. private:
  74. PropertiesAffixPatternProvider affixesByPlural[StandardPlural::COUNT];
  75. CurrencyPluralInfoAffixProvider() = default;
  76. bool fBogus{true};
  77. friend class AutoAffixPatternProvider;
  78. };
  79. class AutoAffixPatternProvider {
  80. public:
  81. inline AutoAffixPatternProvider() = default;
  82. inline AutoAffixPatternProvider(const DecimalFormatProperties& properties, UErrorCode& status) {
  83. setTo(properties, status);
  84. }
  85. inline void setTo(const DecimalFormatProperties& properties, UErrorCode& status) {
  86. if (properties.currencyPluralInfo.fPtr.isNull()) {
  87. propertiesAPP.setTo(properties, status);
  88. currencyPluralInfoAPP.setToBogus();
  89. } else {
  90. propertiesAPP.setToBogus();
  91. currencyPluralInfoAPP.setTo(*properties.currencyPluralInfo.fPtr, properties, status);
  92. }
  93. }
  94. inline void setTo(const AffixPatternProvider* provider, UErrorCode& status) {
  95. if (auto ptr = dynamic_cast<const PropertiesAffixPatternProvider*>(provider)) {
  96. propertiesAPP = *ptr;
  97. } else if (auto ptr = dynamic_cast<const CurrencyPluralInfoAffixProvider*>(provider)) {
  98. currencyPluralInfoAPP = *ptr;
  99. } else {
  100. status = U_INTERNAL_PROGRAM_ERROR;
  101. }
  102. }
  103. inline const AffixPatternProvider& get() const {
  104. if (!currencyPluralInfoAPP.isBogus()) {
  105. return currencyPluralInfoAPP;
  106. } else {
  107. return propertiesAPP;
  108. }
  109. }
  110. private:
  111. PropertiesAffixPatternProvider propertiesAPP;
  112. CurrencyPluralInfoAffixProvider currencyPluralInfoAPP;
  113. };
  114. /**
  115. * A struct for ownership of a few objects needed for formatting.
  116. */
  117. struct DecimalFormatWarehouse : public UMemory {
  118. AutoAffixPatternProvider affixProvider;
  119. LocalPointer<PluralRules> rules;
  120. };
  121. /**
  122. * Internal fields for DecimalFormat.
  123. * TODO: Make some of these fields by value instead of by LocalPointer?
  124. */
  125. struct DecimalFormatFields : public UMemory {
  126. DecimalFormatFields() {}
  127. DecimalFormatFields(const DecimalFormatProperties& propsToCopy)
  128. : properties(propsToCopy) {}
  129. /** The property bag corresponding to user-specified settings and settings from the pattern string. */
  130. DecimalFormatProperties properties;
  131. /** The symbols for the current locale. */
  132. LocalPointer<const DecimalFormatSymbols> symbols;
  133. /**
  134. * The pre-computed formatter object. Setters cause this to be re-computed atomically. The {@link
  135. * #format} method uses the formatter directly without needing to synchronize.
  136. */
  137. LocalizedNumberFormatter formatter;
  138. /** The lazy-computed parser for .parse() */
  139. std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicParser = {};
  140. /** The lazy-computed parser for .parseCurrency() */
  141. std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicCurrencyParser = {};
  142. /** Small object ownership warehouse for the formatter and parser */
  143. DecimalFormatWarehouse warehouse;
  144. /** The effective properties as exported from the formatter object. Used by some getters. */
  145. DecimalFormatProperties exportedProperties;
  146. // Data for fastpath
  147. bool canUseFastFormat = false;
  148. struct FastFormatData {
  149. char16_t cpZero;
  150. char16_t cpGroupingSeparator;
  151. char16_t cpMinusSign;
  152. int8_t minInt;
  153. int8_t maxInt;
  154. } fastData;
  155. };
  156. /**
  157. * Utilities for converting between a DecimalFormatProperties and a MacroProps.
  158. */
  159. class NumberPropertyMapper {
  160. public:
  161. /** Convenience method to create a NumberFormatter directly from Properties. */
  162. static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties,
  163. const DecimalFormatSymbols& symbols,
  164. DecimalFormatWarehouse& warehouse, UErrorCode& status);
  165. /** Convenience method to create a NumberFormatter directly from Properties. */
  166. static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties,
  167. const DecimalFormatSymbols& symbols,
  168. DecimalFormatWarehouse& warehouse,
  169. DecimalFormatProperties& exportedProperties,
  170. UErrorCode& status);
  171. /**
  172. * Creates a new {@link MacroProps} object based on the content of a {@link DecimalFormatProperties}
  173. * object. In other words, maps Properties to MacroProps. This function is used by the
  174. * JDK-compatibility API to call into the ICU 60 fluent number formatting pipeline.
  175. *
  176. * @param properties
  177. * The property bag to be mapped.
  178. * @param symbols
  179. * The symbols associated with the property bag.
  180. * @param exportedProperties
  181. * A property bag in which to store validated properties. Used by some DecimalFormat
  182. * getters.
  183. * @return A new MacroProps containing all of the information in the Properties.
  184. */
  185. static MacroProps oldToNew(const DecimalFormatProperties& properties,
  186. const DecimalFormatSymbols& symbols, DecimalFormatWarehouse& warehouse,
  187. DecimalFormatProperties* exportedProperties, UErrorCode& status);
  188. };
  189. } // namespace impl
  190. } // namespace numparse
  191. U_NAMESPACE_END
  192. #endif //__NUMBER_MAPPER_H__
  193. #endif /* #if !UCONFIG_NO_FORMATTING */