number_patternmodifier.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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() U_OVERRIDE = default;
  38. void processQuantity(DecimalQuantity&, MicroProps& micros, UErrorCode& status) const U_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() U_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. */
  100. void setPatternAttributes(UNumberSignDisplay signDisplay, bool perMille);
  101. /**
  102. * Sets locale-specific details that affect the symbols substituted into the pattern string affixes.
  103. *
  104. * @param symbols
  105. * The desired instance of DecimalFormatSymbols.
  106. * @param currency
  107. * The currency to be used when substituting currency values into the affixes.
  108. * @param unitWidth
  109. * The width used to render currencies.
  110. * @param rules
  111. * Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be determined from the
  112. * convenience method {@link #needsPlurals()}.
  113. * @param status
  114. * Set if an error occurs while loading currency data.
  115. */
  116. void setSymbols(const DecimalFormatSymbols* symbols, const CurrencyUnit& currency,
  117. UNumberUnitWidth unitWidth, const PluralRules* rules, UErrorCode& status);
  118. /**
  119. * Sets attributes of the current number being processed.
  120. *
  121. * @param signum
  122. * -1 if negative; +1 if positive; or 0 if zero.
  123. * @param plural
  124. * The plural form of the number, required only if the pattern contains the triple
  125. * currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
  126. */
  127. void setNumberProperties(Signum signum, StandardPlural::Form plural);
  128. /**
  129. * Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize.
  130. * This is currently true only if there is a currency long name placeholder in the pattern ("¤¤¤").
  131. */
  132. bool needsPlurals() const;
  133. /**
  134. * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable
  135. * and can be saved for future use. The number properties in the current instance are mutated; all other properties
  136. * are left untouched.
  137. *
  138. * <p>
  139. * The resulting modifier cannot be used in a QuantityChain.
  140. *
  141. * <p>
  142. * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP.
  143. *
  144. * @return An immutable that supports both positive and negative numbers.
  145. */
  146. ImmutablePatternModifier *createImmutable(UErrorCode &status);
  147. MicroPropsGenerator &addToChain(const MicroPropsGenerator *parent);
  148. void processQuantity(DecimalQuantity &, MicroProps &micros, UErrorCode &status) const U_OVERRIDE;
  149. int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
  150. UErrorCode &status) const U_OVERRIDE;
  151. int32_t getPrefixLength() const U_OVERRIDE;
  152. int32_t getCodePointCount() const U_OVERRIDE;
  153. bool isStrong() const U_OVERRIDE;
  154. bool containsField(Field field) const U_OVERRIDE;
  155. void getParameters(Parameters& output) const U_OVERRIDE;
  156. bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
  157. /**
  158. * Returns the string that substitutes a given symbol type in a pattern.
  159. */
  160. UnicodeString getSymbol(AffixPatternType type) const U_OVERRIDE;
  161. UnicodeString toUnicodeString() const;
  162. private:
  163. // Modifier details (initialized in constructor)
  164. const bool fStrong;
  165. // Pattern details (initialized in setPatternInfo and setPatternAttributes)
  166. const AffixPatternProvider *fPatternInfo;
  167. Field fField;
  168. UNumberSignDisplay fSignDisplay;
  169. bool fPerMilleReplacesPercent;
  170. // Symbol details (initialized in setSymbols)
  171. const DecimalFormatSymbols *fSymbols;
  172. UNumberUnitWidth fUnitWidth;
  173. CurrencySymbols fCurrencySymbols;
  174. const PluralRules *fRules;
  175. // Number details (initialized in setNumberProperties)
  176. Signum fSignum;
  177. StandardPlural::Form fPlural;
  178. // QuantityChain details (initialized in addToChain)
  179. const MicroPropsGenerator *fParent;
  180. // Transient fields for rendering
  181. UnicodeString currentAffix;
  182. /**
  183. * Uses the current properties to create a single {@link ConstantMultiFieldModifier} with currency spacing support
  184. * if required.
  185. *
  186. * <p>
  187. * CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP.
  188. *
  189. * @param a
  190. * A working FormattedStringBuilder object; passed from the outside to prevent the need to create many new
  191. * instances if this method is called in a loop.
  192. * @param b
  193. * Another working FormattedStringBuilder object.
  194. * @return The constant modifier object.
  195. */
  196. ConstantMultiFieldModifier *createConstantModifier(UErrorCode &status);
  197. int32_t insertPrefix(FormattedStringBuilder &sb, int position, UErrorCode &status);
  198. int32_t insertSuffix(FormattedStringBuilder &sb, int position, UErrorCode &status);
  199. void prepareAffix(bool isPrefix);
  200. };
  201. } // namespace impl
  202. } // namespace number
  203. U_NAMESPACE_END
  204. #endif //__NUMBER_PATTERNMODIFIER_H__
  205. #endif /* #if !UCONFIG_NO_FORMATTING */