number_modifiers.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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_MODIFIERS_H__
  6. #define __NUMBER_MODIFIERS_H__
  7. #include <algorithm>
  8. #include <cstdint>
  9. #include "unicode/uniset.h"
  10. #include "unicode/simpleformatter.h"
  11. #include "standardplural.h"
  12. #include "formatted_string_builder.h"
  13. #include "number_types.h"
  14. U_NAMESPACE_BEGIN namespace number {
  15. namespace impl {
  16. /**
  17. * The canonical implementation of {@link Modifier}, containing a prefix and suffix string.
  18. * TODO: This is not currently being used by real code and could be removed.
  19. */
  20. class U_I18N_API ConstantAffixModifier : public Modifier, public UObject {
  21. public:
  22. ConstantAffixModifier(const UnicodeString &prefix, const UnicodeString &suffix, Field field,
  23. bool strong)
  24. : fPrefix(prefix), fSuffix(suffix), fField(field), fStrong(strong) {}
  25. int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
  26. UErrorCode &status) const U_OVERRIDE;
  27. int32_t getPrefixLength() const U_OVERRIDE;
  28. int32_t getCodePointCount() const U_OVERRIDE;
  29. bool isStrong() const U_OVERRIDE;
  30. bool containsField(Field field) const U_OVERRIDE;
  31. void getParameters(Parameters& output) const U_OVERRIDE;
  32. bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
  33. private:
  34. UnicodeString fPrefix;
  35. UnicodeString fSuffix;
  36. Field fField;
  37. bool fStrong;
  38. };
  39. /**
  40. * The second primary implementation of {@link Modifier}, this one consuming a {@link SimpleFormatter}
  41. * pattern.
  42. */
  43. class U_I18N_API SimpleModifier : public Modifier, public UMemory {
  44. public:
  45. SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong);
  46. SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong,
  47. const Modifier::Parameters parameters);
  48. // Default constructor for LongNameHandler.h
  49. SimpleModifier();
  50. int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
  51. UErrorCode &status) const U_OVERRIDE;
  52. int32_t getPrefixLength() const U_OVERRIDE;
  53. int32_t getCodePointCount() const U_OVERRIDE;
  54. bool isStrong() const U_OVERRIDE;
  55. bool containsField(Field field) const U_OVERRIDE;
  56. void getParameters(Parameters& output) const U_OVERRIDE;
  57. bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
  58. /**
  59. * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because
  60. * FormattedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it.
  61. *
  62. * <p>
  63. * Formats a value that is already stored inside the StringBuilder <code>result</code> between the indices
  64. * <code>startIndex</code> and <code>endIndex</code> by inserting characters before the start index and after the
  65. * end index.
  66. *
  67. * <p>
  68. * This is well-defined only for patterns with exactly one argument.
  69. *
  70. * @param result
  71. * The StringBuilder containing the value argument.
  72. * @param startIndex
  73. * The left index of the value within the string builder.
  74. * @param endIndex
  75. * The right index of the value within the string builder.
  76. * @return The number of characters (UTF-16 code points) that were added to the StringBuilder.
  77. */
  78. int32_t
  79. formatAsPrefixSuffix(FormattedStringBuilder& result, int32_t startIndex, int32_t endIndex,
  80. UErrorCode& status) const;
  81. /**
  82. * TODO: Like above, this belongs with the rest of the SimpleFormatterImpl code.
  83. * I put it here so that the SimpleFormatter uses in FormattedStringBuilder are near each other.
  84. *
  85. * <p>
  86. * Applies the compiled two-argument pattern to the FormattedStringBuilder.
  87. *
  88. * <p>
  89. * This method is optimized for the case where the prefix and suffix are often empty, such as
  90. * in the range pattern like "{0}-{1}".
  91. */
  92. static int32_t
  93. formatTwoArgPattern(const SimpleFormatter& compiled, FormattedStringBuilder& result,
  94. int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength,
  95. Field field, UErrorCode& status);
  96. private:
  97. UnicodeString fCompiledPattern;
  98. Field fField;
  99. bool fStrong = false;
  100. int32_t fPrefixLength = 0;
  101. int32_t fSuffixOffset = -1;
  102. int32_t fSuffixLength = 0;
  103. Modifier::Parameters fParameters;
  104. };
  105. /**
  106. * An implementation of {@link Modifier} that allows for multiple types of fields in the same modifier. Constructed
  107. * based on the contents of two {@link FormattedStringBuilder} instances (one for the prefix, one for the suffix).
  108. */
  109. class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
  110. public:
  111. ConstantMultiFieldModifier(
  112. const FormattedStringBuilder &prefix,
  113. const FormattedStringBuilder &suffix,
  114. bool overwrite,
  115. bool strong,
  116. const Modifier::Parameters parameters)
  117. : fPrefix(prefix),
  118. fSuffix(suffix),
  119. fOverwrite(overwrite),
  120. fStrong(strong),
  121. fParameters(parameters) {}
  122. ConstantMultiFieldModifier(
  123. const FormattedStringBuilder &prefix,
  124. const FormattedStringBuilder &suffix,
  125. bool overwrite,
  126. bool strong)
  127. : fPrefix(prefix),
  128. fSuffix(suffix),
  129. fOverwrite(overwrite),
  130. fStrong(strong) {}
  131. int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
  132. UErrorCode &status) const U_OVERRIDE;
  133. int32_t getPrefixLength() const U_OVERRIDE;
  134. int32_t getCodePointCount() const U_OVERRIDE;
  135. bool isStrong() const U_OVERRIDE;
  136. bool containsField(Field field) const U_OVERRIDE;
  137. void getParameters(Parameters& output) const U_OVERRIDE;
  138. bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
  139. protected:
  140. // NOTE: In Java, these are stored as array pointers. In C++, the FormattedStringBuilder is stored by
  141. // value and is treated internally as immutable.
  142. FormattedStringBuilder fPrefix;
  143. FormattedStringBuilder fSuffix;
  144. bool fOverwrite;
  145. bool fStrong;
  146. Modifier::Parameters fParameters;
  147. };
  148. /** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */
  149. class U_I18N_API CurrencySpacingEnabledModifier : public ConstantMultiFieldModifier {
  150. public:
  151. /** Safe code path */
  152. CurrencySpacingEnabledModifier(
  153. const FormattedStringBuilder &prefix,
  154. const FormattedStringBuilder &suffix,
  155. bool overwrite,
  156. bool strong,
  157. const DecimalFormatSymbols &symbols,
  158. UErrorCode &status);
  159. int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
  160. UErrorCode &status) const U_OVERRIDE;
  161. /** Unsafe code path */
  162. static int32_t
  163. applyCurrencySpacing(FormattedStringBuilder &output, int32_t prefixStart, int32_t prefixLen,
  164. int32_t suffixStart, int32_t suffixLen, const DecimalFormatSymbols &symbols,
  165. UErrorCode &status);
  166. private:
  167. UnicodeSet fAfterPrefixUnicodeSet;
  168. UnicodeString fAfterPrefixInsert;
  169. UnicodeSet fBeforeSuffixUnicodeSet;
  170. UnicodeString fBeforeSuffixInsert;
  171. enum EAffix {
  172. PREFIX, SUFFIX
  173. };
  174. enum EPosition {
  175. IN_CURRENCY, IN_NUMBER
  176. };
  177. /** Unsafe code path */
  178. static int32_t applyCurrencySpacingAffix(FormattedStringBuilder &output, int32_t index, EAffix affix,
  179. const DecimalFormatSymbols &symbols, UErrorCode &status);
  180. static UnicodeSet
  181. getUnicodeSet(const DecimalFormatSymbols &symbols, EPosition position, EAffix affix,
  182. UErrorCode &status);
  183. static UnicodeString
  184. getInsertString(const DecimalFormatSymbols &symbols, EAffix affix, UErrorCode &status);
  185. };
  186. /** A Modifier that does not do anything. */
  187. class U_I18N_API EmptyModifier : public Modifier, public UMemory {
  188. public:
  189. explicit EmptyModifier(bool isStrong) : fStrong(isStrong) {}
  190. int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
  191. UErrorCode &status) const U_OVERRIDE {
  192. (void)output;
  193. (void)leftIndex;
  194. (void)rightIndex;
  195. (void)status;
  196. return 0;
  197. }
  198. int32_t getPrefixLength() const U_OVERRIDE {
  199. return 0;
  200. }
  201. int32_t getCodePointCount() const U_OVERRIDE {
  202. return 0;
  203. }
  204. bool isStrong() const U_OVERRIDE {
  205. return fStrong;
  206. }
  207. bool containsField(Field field) const U_OVERRIDE {
  208. (void)field;
  209. return false;
  210. }
  211. void getParameters(Parameters& output) const U_OVERRIDE {
  212. output.obj = nullptr;
  213. }
  214. bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE {
  215. return other.getCodePointCount() == 0;
  216. }
  217. private:
  218. bool fStrong;
  219. };
  220. /**
  221. * This implementation of ModifierStore adopts Modifer pointers.
  222. */
  223. class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory {
  224. public:
  225. virtual ~AdoptingModifierStore();
  226. static constexpr StandardPlural::Form DEFAULT_STANDARD_PLURAL = StandardPlural::OTHER;
  227. AdoptingModifierStore() = default;
  228. // No copying!
  229. AdoptingModifierStore(const AdoptingModifierStore &other) = delete;
  230. /**
  231. * Sets the Modifier with the specified signum and plural form.
  232. */
  233. void adoptModifier(Signum signum, StandardPlural::Form plural, const Modifier *mod) {
  234. U_ASSERT(mods[getModIndex(signum, plural)] == nullptr);
  235. mods[getModIndex(signum, plural)] = mod;
  236. }
  237. /**
  238. * Sets the Modifier with the specified signum.
  239. * The modifier will apply to all plural forms.
  240. */
  241. void adoptModifierWithoutPlural(Signum signum, const Modifier *mod) {
  242. U_ASSERT(mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] == nullptr);
  243. mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] = mod;
  244. }
  245. /** Returns a reference to the modifier; no ownership change. */
  246. const Modifier *getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE {
  247. const Modifier* modifier = mods[getModIndex(signum, plural)];
  248. if (modifier == nullptr && plural != DEFAULT_STANDARD_PLURAL) {
  249. modifier = mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)];
  250. }
  251. return modifier;
  252. }
  253. /** Returns a reference to the modifier; no ownership change. */
  254. const Modifier *getModifierWithoutPlural(Signum signum) const {
  255. return mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)];
  256. }
  257. private:
  258. // NOTE: mods is zero-initialized (to nullptr)
  259. const Modifier *mods[4 * StandardPlural::COUNT] = {};
  260. inline static int32_t getModIndex(Signum signum, StandardPlural::Form plural) {
  261. U_ASSERT(signum >= 0 && signum < SIGNUM_COUNT);
  262. U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT);
  263. return static_cast<int32_t>(plural) * SIGNUM_COUNT + signum;
  264. }
  265. };
  266. } // namespace impl
  267. } // namespace number
  268. U_NAMESPACE_END
  269. #endif //__NUMBER_MODIFIERS_H__
  270. #endif /* #if !UCONFIG_NO_FORMATTING */