number_patternmodifier.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // © 2017 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_PATTERNMODIFIER_H__
  6. #define __NUMBER_PATTERNMODIFIER_H__
  7. #include "standardplural.h"
  8. #include "unicode/numberformatter.h"
  9. #include "number_patternstring.h"
  10. #include "number_types.h"
  11. #include "number_modifiers.h"
  12. #include "number_utils.h"
  13. #include "number_currencysymbols.h"
  14. U_NAMESPACE_BEGIN
  15. // Export an explicit template instantiation of the LocalPointer that is used as a
  16. // data member of AdoptingModifierStore.
  17. // (When building DLLs for Windows this is required.)
  18. #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
  19. #if defined(_MSC_VER)
  20. // Ignore warning 4661 as LocalPointerBase does not use operator== or operator!=
  21. #pragma warning(push)
  22. #pragma warning(disable : 4661)
  23. #endif
  24. template class U_I18N_API LocalPointerBase<number::impl::AdoptingModifierStore>;
  25. template class U_I18N_API LocalPointer<number::impl::AdoptingModifierStore>;
  26. #if defined(_MSC_VER)
  27. #pragma warning(pop)
  28. #endif
  29. #endif
  30. namespace number {
  31. namespace impl {
  32. // Forward declaration
  33. class MutablePatternModifier;
  34. // Exported as U_I18N_API because it is needed for the unit test PatternModifierTest
  35. class U_I18N_API ImmutablePatternModifier : public MicroPropsGenerator, public UMemory {
  36. public:
  37. ~ImmutablePatternModifier() override = default;
  38. void processQuantity(DecimalQuantity&, MicroProps& micros, UErrorCode& status) const override;
  39. void applyToMicros(MicroProps& micros, const DecimalQuantity& quantity, UErrorCode& status) const;
  40. const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const;
  41. // Non-const method:
  42. void addToChain(const MicroPropsGenerator* parent);
  43. private:
  44. ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules);
  45. const LocalPointer<AdoptingModifierStore> pm;
  46. const PluralRules* rules;
  47. const MicroPropsGenerator* parent;
  48. friend class MutablePatternModifier;
  49. };
  50. /**
  51. * This class is a {@link Modifier} that wraps a decimal format pattern. It applies the pattern's affixes in
  52. * {@link Modifier#apply}.
  53. *
  54. * <p>
  55. * In addition to being a Modifier, this class contains the business logic for substituting the correct locale symbols
  56. * into the affixes of the decimal format pattern.
  57. *
  58. * <p>
  59. * In order to use this class, create a new instance and call the following four setters: {@link #setPatternInfo},
  60. * {@link #setPatternAttributes}, {@link #setSymbols}, and {@link #setNumberProperties}. After calling these four
  61. * setters, the instance will be ready for use as a Modifier.
  62. *
  63. * <p>
  64. * This is a MUTABLE, NON-THREAD-SAFE class designed for performance. Do NOT save references to this or attempt to use
  65. * it from multiple threads! Instead, you can obtain a safe, immutable decimal format pattern modifier by calling
  66. * {@link MutablePatternModifier#createImmutable}, in effect treating this instance as a builder for the immutable
  67. * variant.
  68. */
  69. class U_I18N_API MutablePatternModifier
  70. : public MicroPropsGenerator,
  71. public Modifier,
  72. public SymbolProvider,
  73. public UMemory {
  74. public:
  75. ~MutablePatternModifier() override = default;
  76. /**
  77. * @param isStrong
  78. * Whether the modifier should be considered strong. For more information, see
  79. * {@link Modifier#isStrong()}. Most of the time, decimal format pattern modifiers should be considered
  80. * as non-strong.
  81. */
  82. explicit MutablePatternModifier(bool isStrong);
  83. /**
  84. * Sets a reference to the parsed decimal format pattern, usually obtained from
  85. * {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of {@link AffixPatternProvider} is
  86. * accepted.
  87. *
  88. * @param field
  89. * Which field to use for literal characters in the pattern.
  90. */
  91. void setPatternInfo(const AffixPatternProvider *patternInfo, Field field);
  92. /**
  93. * Sets attributes that imply changes to the literal interpretation of the pattern string affixes.
  94. *
  95. * @param signDisplay
  96. * Whether to force a plus sign on positive numbers.
  97. * @param perMille
  98. * Whether to substitute the percent sign in the pattern with a permille sign.
  99. * @param approximately
  100. * Whether to prepend approximately to the sign
  101. */
  102. void setPatternAttributes(UNumberSignDisplay signDisplay, bool perMille, bool approximately);
  103. /**
  104. * Sets locale-specific details that affect the symbols substituted into the pattern string affixes.
  105. *
  106. * @param symbols
  107. * The desired instance of DecimalFormatSymbols.
  108. * @param currency
  109. * The currency to be used when substituting currency values into the affixes.
  110. * @param unitWidth
  111. * The width used to render currencies.
  112. * @param rules
  113. * Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be determined from the
  114. * convenience method {@link #needsPlurals()}.
  115. * @param status
  116. * Set if an error occurs while loading currency data.
  117. */
  118. void setSymbols(const DecimalFormatSymbols* symbols, const CurrencyUnit& currency,
  119. UNumberUnitWidth unitWidth, const PluralRules* rules, UErrorCode& status);
  120. /**
  121. * Sets attributes of the current number being processed.
  122. *
  123. * @param signum
  124. * -1 if negative; +1 if positive; or 0 if zero.
  125. * @param plural
  126. * The plural form of the number, required only if the pattern contains the triple
  127. * currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
  128. */
  129. void setNumberProperties(Signum signum, StandardPlural::Form plural);
  130. /**
  131. * Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize.
  132. * This is currently true only if there is a currency long name placeholder in the pattern ("¤¤¤").
  133. */
  134. bool needsPlurals() const;
  135. /** Creates a quantity-dependent Modifier for the specified plural form. */
  136. AdoptingSignumModifierStore createImmutableForPlural(StandardPlural::Form plural, UErrorCode& status);
  137. /**
  138. * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable
  139. * and can be saved for future use. The number properties in the current instance are mutated; all other properties
  140. * are left untouched.
  141. *
  142. * <p>
  143. * The resulting modifier cannot be used in a QuantityChain.
  144. *
  145. * <p>
  146. * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP.
  147. *
  148. * @return An immutable that supports both positive and negative numbers.
  149. */
  150. ImmutablePatternModifier *createImmutable(UErrorCode &status);
  151. MicroPropsGenerator &addToChain(const MicroPropsGenerator *parent);
  152. void processQuantity(DecimalQuantity &, MicroProps &micros, UErrorCode &status) const override;
  153. int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
  154. UErrorCode &status) const override;
  155. int32_t getPrefixLength() const override;
  156. int32_t getCodePointCount() const override;
  157. bool isStrong() const override;
  158. bool containsField(Field field) const override;
  159. void getParameters(Parameters& output) const override;
  160. bool semanticallyEquivalent(const Modifier& other) const override;
  161. /**
  162. * Returns the string that substitutes a given symbol type in a pattern.
  163. */
  164. UnicodeString getSymbol(AffixPatternType type) const override;
  165. /**
  166. * Returns the currency symbol for the unit width specified in setSymbols()
  167. */
  168. UnicodeString getCurrencySymbolForUnitWidth(UErrorCode& status) const;
  169. UnicodeString toUnicodeString() const;
  170. private:
  171. // Modifier details (initialized in constructor)
  172. const bool fStrong;
  173. // Pattern details (initialized in setPatternInfo and setPatternAttributes)
  174. const AffixPatternProvider *fPatternInfo;
  175. Field fField;
  176. UNumberSignDisplay fSignDisplay;
  177. bool fPerMilleReplacesPercent;
  178. bool fApproximately;
  179. // Symbol details (initialized in setSymbols)
  180. const DecimalFormatSymbols *fSymbols;
  181. UNumberUnitWidth fUnitWidth;
  182. CurrencySymbols fCurrencySymbols;
  183. const PluralRules *fRules;
  184. // Number details (initialized in setNumberProperties)
  185. Signum fSignum;
  186. StandardPlural::Form fPlural;
  187. // QuantityChain details (initialized in addToChain)
  188. const MicroPropsGenerator *fParent;
  189. // Transient fields for rendering
  190. UnicodeString currentAffix;
  191. /**
  192. * Uses the current properties to create a single {@link ConstantMultiFieldModifier} with currency spacing support
  193. * if required.
  194. *
  195. * <p>
  196. * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP.
  197. *
  198. * @param a
  199. * A working FormattedStringBuilder object; passed from the outside to prevent the need to create many new
  200. * instances if this method is called in a loop.
  201. * @param b
  202. * Another working FormattedStringBuilder object.
  203. * @return The constant modifier object.
  204. */
  205. ConstantMultiFieldModifier *createConstantModifier(UErrorCode &status);
  206. int32_t insertPrefix(FormattedStringBuilder &sb, int position, UErrorCode &status);
  207. int32_t insertSuffix(FormattedStringBuilder &sb, int position, UErrorCode &status);
  208. void prepareAffix(bool isPrefix);
  209. };
  210. } // namespace impl
  211. } // namespace number
  212. U_NAMESPACE_END
  213. #endif //__NUMBER_PATTERNMODIFIER_H__
  214. #endif /* #if !UCONFIG_NO_FORMATTING */