ICU 77.1  77.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
messageformat2_data_model.h
1 // © 2024 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 
4 #include "unicode/utypes.h"
5 
6 #ifndef MESSAGEFORMAT_DATA_MODEL_H
7 #define MESSAGEFORMAT_DATA_MODEL_H
8 
9 #if U_SHOW_CPLUSPLUS_API
10 
11 #if !UCONFIG_NO_NORMALIZATION
12 
13 #if !UCONFIG_NO_FORMATTING
14 
15 #if !UCONFIG_NO_MF2
16 
17 #include "unicode/localpointer.h"
18 #include "unicode/messageformat2_data_model_names.h"
19 
20 #ifndef U_HIDE_DEPRECATED_API
21 
22 #include <algorithm>
23 #include <cstddef>
24 #include <iterator>
25 #include <optional>
26 #include <variant>
27 #include <vector>
28 
29 U_NAMESPACE_BEGIN
30 
31 class UVector;
32 
33 // Helpers
34 
35 // Note: this _must_ be declared `inline` or else gcc will generate code
36 // for its instantiations, which needs to be avoided because it returns
37 // a std::vector
38 template<typename T>
39 static inline std::vector<T> toStdVector(const T* arr, int32_t len) {
40  std::vector<T> result;
41  for (int32_t i = 0; i < len; i++) {
42  result.push_back(arr[i]);
43  }
44  return result;
45 }
46 
47 #if defined(U_REAL_MSVC)
48 #pragma warning(push)
49 // Ignore warning 4251 as these templates are instantiated later in this file,
50 // after the classes used to instantiate them have been defined.
51 #pragma warning(disable: 4251)
52 #endif
53 
54 namespace message2 {
55  class Checker;
56  class MFDataModel;
57  class MessageFormatter;
58  class Parser;
59  class Serializer;
60 
61 
62  namespace data_model {
63  class Binding;
64  class Literal;
65  class Operator;
66 
78  class U_I18N_API Literal : public UObject {
79  public:
97  const UnicodeString& unquoted() const;
107  UBool isQuoted() const { return thisIsQuoted; }
119  Literal(UBool q, const UnicodeString& s) : thisIsQuoted(q), contents(s) {}
126  Literal(const Literal& other) : thisIsQuoted(other.thisIsQuoted), contents(other.contents) {}
135  friend inline void swap(Literal& l1, Literal& l2) noexcept {
136  using std::swap;
137 
138  swap(l1.thisIsQuoted, l2.thisIsQuoted);
139  swap(l1.contents, l2.contents);
140  }
155  Literal() = default;
171  bool operator<(const Literal& other) const;
187  bool operator==(const Literal& other) const;
194  virtual ~Literal();
195 
196  private:
197  /* const */ bool thisIsQuoted = false;
198  /* const */ UnicodeString contents;
199  };
200  } // namespace data_model
201 } // namespace message2
202 
204 // Export an explicit template instantiation of the LocalPointer that is used as a
205 // data member of various MFDataModel classes.
206 // (When building DLLs for Windows this is required.)
207 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
208 // for similar examples.)
209 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
212 #endif
213 #if defined(U_REAL_MSVC)
214 #pragma warning(pop)
215 #endif
217 
218 U_NAMESPACE_END
219 
221 // Export an explicit template instantiation of the std::variants and std::optionals
222 // that are used as a data member of various MFDataModel classes.
223 // (When building DLLs for Windows this is required.)
224 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
225 // for similar examples.)
226 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
227 #if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION)
228 struct U_I18N_API std::_Nontrivial_dummy_type;
229 template class U_I18N_API std::_Variant_storage_<false, icu::UnicodeString, icu::message2::data_model::Literal>;
230 #endif
231 template class U_I18N_API std::variant<icu::UnicodeString, icu::message2::data_model::Literal>;
232 template class U_I18N_API std::optional<std::variant<icu::UnicodeString, icu::message2::data_model::Literal>>;
233 template class U_I18N_API std::optional<icu::message2::data_model::Literal>;
234 #endif
236 
237 U_NAMESPACE_BEGIN
238 
239 namespace message2 {
240  namespace data_model {
241 
256  class U_I18N_API Operand : public UObject {
257  public:
266  UBool isVariable() const;
275  UBool isLiteral() const;
284  virtual UBool isNull() const;
294  const UnicodeString& asVariable() const;
304  const Literal& asLiteral() const;
312  Operand() : contents(std::nullopt) {}
322  explicit Operand(const UnicodeString& v) : contents(VariableName(v)) {}
332  explicit Operand(const Literal& l) : contents(l) {}
341  friend inline void swap(Operand& o1, Operand& o2) noexcept {
342  using std::swap;
343  (void) o1;
344  (void) o2;
345  swap(o1.contents, o2.contents);
346  }
353  virtual Operand& operator=(Operand) noexcept;
360  Operand(const Operand&);
367  virtual ~Operand();
368  private:
369  std::optional<std::variant<VariableName, Literal>> contents;
370  }; // class Operand
371 
387  class U_I18N_API Key : public UObject {
388  public:
397  UBool isWildcard() const { return !contents.has_value(); }
407  const Literal& asLiteral() const;
414  Key(const Key& other) : contents(other.contents) {}
422  Key() : contents(std::nullopt) {}
432  explicit Key(const Literal& lit) : contents(lit) {}
441  friend inline void swap(Key& k1, Key& k2) noexcept {
442  using std::swap;
443 
444  swap(k1.contents, k2.contents);
445  }
452  Key& operator=(Key) noexcept;
466  bool operator<(const Key& other) const;
480  bool operator==(const Key& other) const;
487  virtual ~Key();
488  private:
489  /* const */ std::optional<Literal> contents;
490  }; // class Key
491  } // namespace data_model
492 } // namespace message2
493 
495 // Export an explicit template instantiation of the LocalPointer that is used as a
496 // data member of various MFDataModel classes.
497 // (When building DLLs for Windows this is required.)
498 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
499 // for similar examples.)
500 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
503 #endif
505 
506 namespace message2 {
507  namespace data_model {
518  class U_I18N_API SelectorKeys : public UObject {
519  public:
530  std::vector<Key> getKeys() const {
531  return toStdVector<Key>(keys.getAlias(), len);
532  }
542  class U_I18N_API Builder : public UMemory {
543  private:
544  friend class SelectorKeys;
545  UVector* keys; // This is a raw pointer and not a LocalPointer<UVector> to avoid undefined behavior warnings,
546  // since UVector is forward-declared
547  // The vector owns its elements
548  public:
559  Builder& add(Key&& key, UErrorCode& status) noexcept;
572  SelectorKeys build(UErrorCode& status) const;
582  Builder(UErrorCode& status);
589  virtual ~Builder();
590  Builder(const Builder&) = delete;
591  Builder& operator=(const Builder&) = delete;
592  Builder(Builder&&) = delete;
593  Builder& operator=(Builder&&) = delete;
594  }; // class SelectorKeys::Builder
609  bool operator<(const SelectorKeys& other) const;
617  SelectorKeys() : len(0) {}
626  friend inline void swap(SelectorKeys& s1, SelectorKeys& s2) noexcept {
627  using std::swap;
628 
629  swap(s1.len, s2.len);
630  swap(s1.keys, s2.keys);
631  }
638  SelectorKeys(const SelectorKeys& other);
652  virtual ~SelectorKeys();
653  private:
654  friend class Builder;
655  friend class message2::Checker;
656  friend class message2::MessageFormatter;
657  friend class message2::Serializer;
658 
659  /* const */ LocalArray<Key> keys;
660  /* const */ int32_t len;
661 
662  const Key* getKeysInternal() const;
663  SelectorKeys(const UVector& ks, UErrorCode& status);
664  }; // class SelectorKeys
665 
666 
667  } // namespace data_model
668 
669 
670  namespace data_model {
671  class Operator;
672 
681  class U_I18N_API Option : public UObject {
682  public:
691  const Operand& getValue() const { return rand; }
700  const UnicodeString& getName() const { return name; }
711  Option(const UnicodeString& n, Operand&& r) : name(n), rand(std::move(r)) {}
719  Option() {}
728  friend inline void swap(Option& o1, Option& o2) noexcept {
729  using std::swap;
730 
731  swap(o1.name, o2.name);
732  swap(o1.rand, o2.rand);
733  }
740  Option(const Option& other);
747  Option& operator=(Option other) noexcept;
754  virtual ~Option();
755  private:
756  /* const */ UnicodeString name;
757  /* const */ Operand rand;
758  }; // class Option
759  } // namespace data_model
760 } // namespace message2
761 
763 // Export an explicit template instantiation of the LocalPointer that is used as a
764 // data member of various MFDataModel classes.
765 // (When building DLLs for Windows this is required.)
766 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
767 // for similar examples.)
768 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
771 #endif
773 
774 namespace message2 {
775  namespace data_model {
776  // Internal only
777  #ifndef U_IN_DOXYGEN
778  // Options
779  // This is a wrapper class around a vector of options that provides lookup operations
780  class U_I18N_API OptionMap : public UObject {
781  public:
782  int32_t size() const;
783  // Needs to take an error code b/c an earlier copy might have failed
784  const Option& getOption(int32_t, UErrorCode&) const;
785  friend inline void swap(OptionMap& m1, OptionMap& m2) noexcept {
786  using std::swap;
787 
788  swap(m1.bogus, m2.bogus);
789  swap(m1.options, m2.options);
790  swap(m1.len, m2.len);
791  }
792  OptionMap() : len(0) {}
793  OptionMap(const OptionMap&);
794  OptionMap& operator=(OptionMap);
795  std::vector<Option> getOptions() const {
796  return toStdVector<Option>(options.getAlias(), len);
797  }
798  OptionMap(const UVector&, UErrorCode&);
799  OptionMap(Option*, int32_t);
800  virtual ~OptionMap();
801 
802  class U_I18N_API Builder : public UObject {
803  private:
804  UVector* options;
805  bool checkDuplicates = true;
806  public:
807  Builder& add(Option&& opt, UErrorCode&);
808  Builder(UErrorCode&);
809  static Builder attributes(UErrorCode&);
810  // As this class is private, build() is destructive
811  OptionMap build(UErrorCode&);
812  friend inline void swap(Builder& m1, Builder& m2) noexcept {
813  using std::swap;
814 
815  swap(m1.options, m2.options);
816  swap(m1.checkDuplicates, m2.checkDuplicates);
817  }
818  Builder(Builder&&);
819  Builder(const Builder&) = delete;
820  Builder& operator=(Builder) noexcept;
821  virtual ~Builder();
822  }; // class OptionMap::Builder
823  private:
824  friend class message2::Serializer;
825 
826  bool bogus = false;
827  LocalArray<Option> options;
828  int32_t len;
829  }; // class OptionMap
830  #endif
831 
832  } // namespace data_model
833 } // namespace message2
834 
835 U_NAMESPACE_END
836 
837 U_NAMESPACE_BEGIN
838 
839 namespace message2 {
840  namespace data_model {
854  class U_I18N_API Operator : public UObject {
855  public:
873  std::vector<Option> getOptions() const {
874  return options.getOptions();
875  }
885  class U_I18N_API Builder : public UMemory {
886  private:
887  friend class Operator;
888  FunctionName functionName;
889  OptionMap::Builder options;
890  public:
914  Builder& addOption(const UnicodeString &key, Operand&& value, UErrorCode& status) noexcept;
940  Builder(UErrorCode& status);
947  virtual ~Builder();
948  Builder(const Builder&) = delete;
949  Builder& operator=(const Builder&) = delete;
950  Builder(Builder&&) = delete;
951  Builder& operator=(Builder&&) = delete;
952  }; // class Operator::Builder
959  Operator(const Operator& other) noexcept;
968  friend inline void swap(Operator& o1, Operator& o2) noexcept {
969  using std::swap;
970 
971  swap(o1.name, o2.name);
972  swap(o1.options, o2.options);
973  }
988  Operator() {}
995  virtual ~Operator();
996  private:
997  friend class Binding;
998  friend class Builder;
999  friend class message2::Checker;
1000  friend class message2::MessageFormatter;
1001  friend class message2::Serializer;
1002 
1003  // Function call constructor
1004  Operator(const FunctionName& f, const UVector& options, UErrorCode&);
1005 
1006  const OptionMap& getOptionsInternal() const;
1007  Operator(const FunctionName&, const OptionMap&);
1008 
1009  /* const */ FunctionName name;
1010  /* const */ OptionMap options;
1011  }; // class Operator
1012  } // namespace data_model
1013 } // namespace message2
1014 
1015 U_NAMESPACE_END
1016 
1018 // Export an explicit template instantiation of the std::optional that is used as a
1019 // data member of various MFDataModel classes.
1020 // (When building DLLs for Windows this is required.)
1021 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
1022 // for similar examples.)
1023 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1024 template class U_I18N_API std::optional<icu::message2::data_model::Operator>;
1025 #endif
1027 
1028 U_NAMESPACE_BEGIN
1029 
1030 namespace message2 {
1031  namespace data_model {
1032  // Internal only
1033  typedef enum UMarkupType {
1034  UMARKUP_OPEN = 0,
1035  UMARKUP_CLOSE,
1036  UMARKUP_STANDALONE,
1037  UMARKUP_COUNT
1038  } UMarkupType;
1039 
1050  class U_I18N_API Markup : public UObject {
1051  public:
1060  UBool isOpen() const { return (type == UMARKUP_OPEN); }
1069  UBool isClose() const { return (type == UMARKUP_CLOSE); }
1078  UBool isStandalone() const { return (type == UMARKUP_STANDALONE); }
1087  const UnicodeString& getName() const { return name; }
1096  std::vector<Option> getOptions() const { return options.getOptions(); }
1105  std::vector<Option> getAttributes() const { return attributes.getOptions(); }
1113  Markup() {}
1120  virtual ~Markup();
1130  class U_I18N_API Builder : public UMemory {
1131  private:
1132  friend class Markup;
1133 
1134  UnicodeString name;
1135  OptionMap::Builder options;
1136  OptionMap::Builder attributes;
1137  UMarkupType type = UMARKUP_COUNT;
1138  public:
1148  Builder& setName(const UnicodeString& n) { name = n; return *this; }
1157  Builder& setOpen() { type = UMARKUP_OPEN; return *this; }
1166  Builder& setClose() { type = UMARKUP_CLOSE; return *this; }
1175  Builder& setStandalone() { type = UMARKUP_STANDALONE; return *this; }
1187  Builder& addOption(const UnicodeString &key, Operand&& value, UErrorCode& status);
1199  Builder& addAttribute(const UnicodeString &key, Operand&& value, UErrorCode& status);
1234  virtual ~Builder();
1235  Builder(const Builder&) = delete;
1236  Builder& operator=(const Builder&) = delete;
1237  Builder(Builder&&) = delete;
1238  Builder& operator=(Builder&&) = delete;
1239  }; // class Markup::Builder
1240 
1241  private:
1242  friend class Builder;
1243  friend class message2::Serializer;
1244 
1245  UMarkupType type;
1246  UnicodeString name;
1247  OptionMap options;
1248  OptionMap attributes;
1249  const OptionMap& getOptionsInternal() const { return options; }
1250  const OptionMap& getAttributesInternal() const { return attributes; }
1251  Markup(UMarkupType, UnicodeString, OptionMap&&, OptionMap&&);
1252  }; // class Markup
1253 
1267  class U_I18N_API Expression : public UObject {
1268  public:
1304  const Operator* getOperator(UErrorCode& status) const;
1314  const Operand& getOperand() const;
1323  std::vector<Option> getAttributes() const { return attributes.getOptions(); }
1333  class U_I18N_API Builder : public UMemory {
1334  private:
1335  friend class Expression;
1336 
1337  bool hasOperand = false;
1338  bool hasOperator = false;
1339  Operand rand;
1340  Operator rator;
1341  OptionMap::Builder attributes;
1342  public:
1374  Builder& addAttribute(const UnicodeString &key, Operand&& value, UErrorCode& status);
1409  virtual ~Builder();
1410  Builder(const Builder&) = delete;
1411  Builder& operator=(const Builder&) = delete;
1412  Builder(Builder&&) = delete;
1413  Builder& operator=(Builder&&) = delete;
1414  }; // class Expression::Builder
1423  friend inline void swap(Expression& e1, Expression& e2) noexcept {
1424  using std::swap;
1425 
1426  swap(e1.rator, e2.rator);
1427  swap(e1.rand, e2.rand);
1428  swap(e1.attributes, e2.attributes);
1429  }
1436  Expression(const Expression& other);
1458  virtual ~Expression();
1459  private:
1460  friend class message2::Serializer;
1461 
1462  /*
1463  Internally, an expression is represented as the application of an optional operator to an operand.
1464  The operand is always present; for function calls with no operand, it's represented
1465  as an operand for which `isNull()` is true.
1466 
1467  Operator | Operand
1468  --------------------------------
1469  { |42| :fun opt=value } => (FunctionName=fun, | Literal(quoted=true, contents="42")
1470  options={opt: value})
1471  { abcd } => null | Literal(quoted=false, contents="abcd")
1472  { : fun opt=value } => (FunctionName=fun,
1473  options={opt: value}) | NullOperand()
1474  */
1475 
1476  Expression(const Operator &rAtor, const Operand &rAnd, const OptionMap& attrs) : rator(rAtor), rand(rAnd), attributes(attrs) {}
1477  Expression(const Operand &rAnd, const OptionMap& attrs) : rator(std::nullopt), rand(Operand(rAnd)), attributes(attrs) {}
1478  Expression(const Operator &rAtor, const OptionMap& attrs) : rator(rAtor), rand(), attributes(attrs) {}
1479  /* const */ std::optional<Operator> rator;
1480  /* const */ Operand rand;
1481  /* const */ OptionMap attributes;
1482  const OptionMap& getAttributesInternal() const { return attributes; }
1483  }; // class Expression
1484  } // namespace data_model
1485 } // namespace message2
1486 
1488 // Export an explicit template instantiation of the LocalPointer that is used as a
1489 // data member of various MFDataModel classes.
1490 // (When building DLLs for Windows this is required.)
1491 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
1492 // for similar examples.)
1493 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1494 template class U_I18N_API LocalPointerBase<message2::data_model::Expression>;
1495 template class U_I18N_API LocalArray<message2::data_model::Expression>;
1496 #endif
1498 
1499 namespace message2 {
1500  namespace data_model {
1501 
1502  class Pattern;
1503 
1504  // Despite the comments, `PatternPart` is internal-only
1515  class PatternPart : public UObject {
1516  public:
1525  UBool isText() const { return std::holds_alternative<UnicodeString>(piece); }
1534  UBool isMarkup() const { return std::holds_alternative<Markup>(piece); }
1543  UBool isExpression() const { return std::holds_alternative<Expression>(piece); }
1553  const Expression& contents() const;
1563  const Markup& asMarkup() const;
1573  const UnicodeString& asText() const;
1582  friend inline void swap(PatternPart& p1, PatternPart& p2) noexcept {
1583  using std::swap;
1584 
1585  swap(p1.piece, p2.piece);
1586  }
1593  PatternPart(const PatternPart& other);
1607  virtual ~PatternPart();
1617  explicit PatternPart(const UnicodeString& t) : piece(t) {}
1627  explicit PatternPart(Expression&& e) : piece(e) {}
1637  explicit PatternPart(Markup&& m) : piece(m) {}
1645  PatternPart() = default;
1646  private:
1647  friend class Pattern;
1648 
1649  std::variant<UnicodeString, Expression, Markup> piece;
1650  }; // class PatternPart
1651  } // namespace data_model
1652 } // namespace message2
1653 
1655 // Export an explicit template instantiation of the LocalPointer that is used as a
1656 // data member of various MFDataModel classes.
1657 // (When building DLLs for Windows this is required.)
1658 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
1659 // for similar examples.)
1660 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1663 #endif
1665 
1666 namespace message2 {
1667  namespace data_model {
1678  class U_I18N_API Pattern : public UObject {
1679  private:
1680  friend class PatternPart;
1681 
1682  public:
1683  struct Iterator;
1693  Iterator begin() const {
1694  return Iterator(this, 0);
1695  }
1705  Iterator end() const {
1706  return Iterator(this, len);
1707  }
1717  class U_I18N_API Builder : public UMemory {
1718  private:
1719  friend class Pattern;
1720 
1721  UVector* parts; // Not a LocalPointer for the same reason as in `SelectorKeys::Builder`
1722 
1723  public:
1734  Builder& add(Expression&& part, UErrorCode& status) noexcept;
1745  Builder& add(Markup&& part, UErrorCode& status) noexcept;
1756  Builder& add(UnicodeString&& part, UErrorCode& status) noexcept;
1769  Pattern build(UErrorCode& status) const noexcept;
1786  virtual ~Builder();
1787  Builder(const Builder&) = delete;
1788  Builder& operator=(const Builder&) = delete;
1789  Builder(Builder&&) = delete;
1790  Builder& operator=(Builder&&) = delete;
1791  }; // class Pattern::Builder
1792 
1800  Pattern() : parts(LocalArray<PatternPart>()) {}
1809  friend inline void swap(Pattern& p1, Pattern& p2) noexcept {
1810  using std::swap;
1811 
1812  swap(p1.bogus, p2.bogus);
1813  swap(p1.len, p2.len);
1814  swap(p1.parts, p2.parts);
1815  }
1822  Pattern(const Pattern& other);
1836  virtual ~Pattern();
1837 
1848  private:
1849  using iterator_category = std::forward_iterator_tag;
1850  using difference_type = std::ptrdiff_t;
1851  using value_type = std::variant<UnicodeString, Expression, Markup>;
1852  using pointer = value_type*;
1853  using reference = const value_type&;
1854 
1855  friend class Pattern;
1856  Iterator(const Pattern* p, int32_t i) : pos(i), pat(p) {}
1857  friend bool operator== (const Iterator& a, const Iterator& b) { return (a.pat == b.pat && a.pos == b.pos); }
1858 
1859  int32_t pos;
1860  const Pattern* pat;
1861 
1862  public:
1869  reference operator*() const {
1870  const PatternPart& part = pat->parts[pos];
1871  return patternContents(part);
1872  }
1879  Iterator operator++() { pos++; return *this; }
1886  friend bool operator!= (const Iterator& a, const Iterator& b) { return !(a == b); }
1887  }; // struct Iterator
1888 
1889  private:
1890  friend class Builder;
1891  friend class message2::MessageFormatter;
1892  friend class message2::Serializer;
1893 
1894  // Set to true if a copy constructor fails;
1895  // needed in order to distinguish an uninitialized
1896  // Pattern from a 0-length pattern
1897  bool bogus = false;
1898 
1899  // Possibly-empty array of parts
1900  int32_t len = 0;
1902 
1903  Pattern(const UVector& parts, UErrorCode& status);
1904  // Helper
1905  static void initParts(Pattern&, const Pattern&);
1906 
1915  int32_t numParts() const;
1926  const PatternPart& getPart(int32_t i) const;
1927 
1928  // Gets around not being able to declare Pattern::Iterator as a friend
1929  // in PatternPart
1930  static const std::variant<UnicodeString, Expression, Markup>&
1931  patternContents(const PatternPart& p) { return p.piece; }
1932  }; // class Pattern
1933 
1944  class U_I18N_API Variant : public UObject {
1945  public:
1954  const Pattern& getPattern() const { return p; }
1963  const SelectorKeys& getKeys() const { return k; }
1975  Variant(const SelectorKeys& keys, Pattern&& pattern) : k(keys), p(std::move(pattern)) {}
1984  friend inline void swap(Variant& v1, Variant& v2) noexcept {
1985  using std::swap;
1986 
1987  swap(v1.k, v2.k);
1988  swap(v1.p, v2.p);
1989  }
1996  Variant& operator=(Variant other) noexcept;
2004  Variant() = default;
2011  Variant(const Variant&);
2018  virtual ~Variant();
2019  private:
2020  /* const */ SelectorKeys k;
2021  /* const */ Pattern p;
2022  }; // class Variant
2023  } // namespace data_model
2024 
2025  namespace data_model {
2036  class U_I18N_API Binding : public UObject {
2037  public:
2046  const Expression& getValue() const;
2055  const VariableName& getVariable() const { return var; }
2070  static Binding input(UnicodeString&& variableName, Expression&& rhs, UErrorCode& errorCode);
2078  UBool isLocal() const { return local; }
2088  Binding(const VariableName& v, Expression&& e) : var(v), expr(std::move(e)), local(true), annotation(nullptr) {}
2097  friend inline void swap(Binding& b1, Binding& b2) noexcept {
2098  using std::swap;
2099 
2100  swap(b1.var, b2.var);
2101  swap(b1.expr, b2.expr);
2102  swap(b1.local, b2.local);
2103  b1.updateAnnotation();
2104  b2.updateAnnotation();
2105  }
2112  Binding(const Binding& other);
2127  Binding() : local(true) {}
2134  virtual ~Binding();
2135  private:
2136  friend class message2::Checker;
2137  friend class message2::MessageFormatter;
2138  friend class message2::Parser;
2139  friend class message2::Serializer;
2140 
2141  /* const */ VariableName var;
2142  /* const */ Expression expr;
2143  /* const */ bool local;
2144 
2145  // The following field is always nullptr for a local
2146  // declaration, and possibly nullptr for an .input declaration
2147  // If non-null, the referent is a member of `expr` so
2148  // its lifetime is the same as the lifetime of the enclosing Binding
2149  // (as long as there's no mutation)
2150  const Operator* annotation = nullptr;
2151 
2152  const OptionMap& getOptionsInternal() const;
2153 
2154  bool hasAnnotation() const { return !local && (annotation != nullptr); }
2155  void updateAnnotation();
2156  }; // class Binding
2157  } // namespace data_model
2158 } // namespace message2
2159 
2161 // Export an explicit template instantiation of the LocalPointer that is used as a
2162 // data member of various MFDataModel classes.
2163 // (When building DLLs for Windows this is required.)
2164 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
2165 // for similar examples.)
2166 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
2167 template class U_I18N_API LocalPointerBase<message2::data_model::Variant>;
2168 template class U_I18N_API LocalPointerBase<message2::data_model::Binding>;
2169 template class U_I18N_API LocalArray<message2::data_model::Variant>;
2170 template class U_I18N_API LocalArray<message2::data_model::Binding>;
2171 #endif
2173 
2174 namespace message2 {
2175  using namespace data_model;
2176 
2177 
2178  // Internal only
2179 
2180  class MFDataModel;
2181 
2182  #ifndef U_IN_DOXYGEN
2183  class Matcher : public UObject {
2184  public:
2185  Matcher& operator=(Matcher);
2186  Matcher(const Matcher&);
2195  friend inline void swap(Matcher& m1, Matcher& m2) noexcept {
2196  using std::swap;
2197 
2198  if (m1.bogus) {
2199  m2.bogus = true;
2200  return;
2201  }
2202  if (m2.bogus) {
2203  m1.bogus = true;
2204  return;
2205  }
2206  swap(m1.selectors, m2.selectors);
2207  swap(m1.numSelectors, m2.numSelectors);
2208  swap(m1.variants, m2.variants);
2209  swap(m1.numVariants, m2.numVariants);
2210  }
2211  virtual ~Matcher();
2212  private:
2213 
2214  friend class MFDataModel;
2215 
2216  Matcher(VariableName* ss, int32_t ns, Variant* vs, int32_t nv);
2217  Matcher() {}
2218 
2219  // A Matcher may have numSelectors=0 and numVariants=0
2220  // (this is a data model error, but it's representable).
2221  // So we have to keep a separate flag to track failed copies.
2222  bool bogus = false;
2223 
2224  // The variables that are being matched on.
2225  LocalArray<VariableName> selectors;
2226  // The number of selectors
2227  int32_t numSelectors = 0;
2228  // The list of `when` clauses (case arms).
2229  LocalArray<Variant> variants;
2230  // The number of variants
2231  int32_t numVariants = 0;
2232  }; // class Matcher
2233  #endif
2234 } // namespace message2
2235 
2236 U_NAMESPACE_END
2237 
2239 // Export an explicit template instantiation of the std::variant that is used as a
2240 // data member of various MFDataModel classes.
2241 // (When building DLLs for Windows this is required.)
2242 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
2243 // for similar examples.)
2244 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
2245 #if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION)
2246 template class U_I18N_API std::_Variant_storage_<false, icu::message2::Matcher,icu::message2::data_model::Pattern>;
2247 #endif
2248 template class U_I18N_API std::variant<icu::message2::Matcher,icu::message2::data_model::Pattern>;
2249 #endif
2251 
2252 U_NAMESPACE_BEGIN
2253 
2254 namespace message2 {
2255  // -----------------------------------------------------------------------
2256  // Public MFDataModel class
2257 
2274  class U_I18N_API MFDataModel : public UMemory {
2275  /*
2276  Classes that represent nodes in the data model are nested inside the
2277  `MFDataModel` class.
2278 
2279  Classes such as `Expression`, `Pattern` and `VariantMap` are immutable and
2280  are constructed using the builder pattern.
2281 
2282  Most classes representing nodes have copy constructors. This is because builders
2283  contain immutable data that must be copied when calling `build()`, since the builder
2284  could go out of scope before the immutable result of the builder does. Copying is
2285  also necessary to prevent unexpected mutation if intermediate builders are saved
2286  and mutated again after calling `build()`.
2287 
2288  The copy constructors perform a deep copy, for example by copying the entire
2289  list of options for an `Operator` (and copying the entire underlying vector.)
2290  Some internal fields should be `const`, but are declared as non-`const` to make
2291  the copy constructor simpler to implement. (These are noted throughout.) In
2292  other words, those fields are `const` except during the execution of a copy
2293  constructor.
2294 
2295  On the other hand, intermediate `Builder` methods that return a `Builder&`
2296  mutate the state of the builder, so in code like:
2297 
2298  Expression::Builder& exprBuilder = Expression::builder()-> setOperand(foo);
2299  Expression::Builder& exprBuilder2 = exprBuilder.setOperator(bar);
2300 
2301  the call to `setOperator()` would mutate `exprBuilder`, since `exprBuilder`
2302  and `exprBuilder2` are references to the same object.
2303 
2304  An alternate choice would be to make `build()` destructive, so that copying would
2305  be unnecessary. Or, both copying and moving variants of `build()` could be
2306  provided. Copying variants of the intermediate `Builder` methods could be
2307  provided as well, if this proved useful.
2308  */
2309  public:
2318  std::vector<Binding> getLocalVariables() const {
2319  std::vector<Binding> result;
2320  if (!bogus) {
2321  return toStdVector<Binding>(bindings.getAlias(), bindingsLen);
2322  }
2323  return {};
2324  }
2333  std::vector<VariableName> getSelectors() const {
2334  if (std::holds_alternative<Pattern>(body)) {
2335  return {};
2336  }
2337  const Matcher* match = std::get_if<Matcher>(&body);
2338  // match must be non-null, given the previous check
2339  return toStdVector<VariableName>(match->selectors.getAlias(), match->numSelectors);
2340  }
2349  std::vector<Variant> getVariants() const {
2350  // Return empty vector if no variants
2351  if (std::holds_alternative<Pattern>(body)) {
2352  return {};
2353  }
2354  const Matcher* match = std::get_if<Matcher>(&body);
2355  // match must be non-null, given the previous check
2356  return toStdVector<Variant>(match->variants.getAlias(), match->numVariants);
2357  return {};
2358  }
2368  const Pattern& getPattern() const;
2369 
2377  class U_I18N_API Builder;
2378 
2395  friend inline void swap(MFDataModel& m1, MFDataModel& m2) noexcept {
2396  using std::swap;
2397 
2398  if (m1.bogus) {
2399  m2.bogus = true;
2400  return;
2401  }
2402  if (m2.bogus) {
2403  m1.bogus = true;
2404  return;
2405  }
2406  swap(m1.body, m2.body);
2407  swap(m1.bindings, m2.bindings);
2408  swap(m1.bindingsLen, m2.bindingsLen);
2409  }
2423  MFDataModel(const MFDataModel& other);
2430  virtual ~MFDataModel();
2431 
2439  class U_I18N_API Builder : public UMemory {
2440  private:
2441  friend class MFDataModel;
2442 
2443  void checkDuplicate(const VariableName&, UErrorCode&) const;
2444  void buildSelectorsMessage(UErrorCode&);
2445  bool hasPattern = true;
2446  bool hasSelectors = false;
2447  Pattern pattern;
2448  // The following members are not LocalPointers for the same reason as in SelectorKeys::Builder
2449  UVector* selectors = nullptr;
2450  UVector* variants = nullptr;
2451  UVector* bindings = nullptr;
2452  public:
2477  Builder& addSelector(VariableName&& selector, UErrorCode& errorCode);
2490  Builder& addVariant(SelectorKeys&& keys, Pattern&& pattern, UErrorCode& errorCode) noexcept;
2522  MFDataModel build(UErrorCode& status) const noexcept;
2542  virtual ~Builder();
2543  Builder(const Builder&) = delete;
2544  Builder& operator=(const Builder&) = delete;
2545  Builder(Builder&&) = delete;
2546  Builder& operator=(Builder&&) = delete;
2547  }; // class Builder
2548 
2549  private:
2550  friend class Checker;
2551  friend class MessageFormatter;
2552  friend class Serializer;
2553 
2554  Pattern empty; // Provided so that `getPattern()` can return a result
2555  // if called on a selectors message
2556  bool hasPattern() const { return std::holds_alternative<Pattern>(body); }
2557 
2558  bool bogus = false; // Set if a copy constructor fails
2559 
2560  // A message body is either a matcher (selector list and variant list),
2561  // or a single pattern
2562  std::variant<Matcher, Pattern> body;
2563 
2564  // Bindings for local variables
2565  /* const */ LocalArray<Binding> bindings;
2566  int32_t bindingsLen = 0;
2567 
2568  const Binding* getLocalVariablesInternal() const;
2569  const VariableName* getSelectorsInternal() const;
2570  const Variant* getVariantsInternal() const;
2571 
2572  int32_t numSelectors() const {
2573  const Matcher* matcher = std::get_if<Matcher>(&body);
2574  return (matcher == nullptr ? 0 : matcher->numSelectors);
2575  }
2576  int32_t numVariants() const {
2577  const Matcher* matcher = std::get_if<Matcher>(&body);
2578  return (matcher == nullptr ? 0 : matcher->numVariants);
2579  }
2580 
2581  // Helper
2582  void initBindings(const Binding*);
2583 
2584  MFDataModel(const Builder& builder, UErrorCode&) noexcept;
2585  }; // class MFDataModel
2586 
2587 } // namespace message2
2588 
2589 U_NAMESPACE_END
2590 
2591 #endif // U_HIDE_DEPRECATED_API
2592 
2593 #endif /* #if !UCONFIG_NO_MF2 */
2594 
2595 #endif /* #if !UCONFIG_NO_FORMATTING */
2596 
2597 #endif /* #if !UCONFIG_NO_NORMALIZATION */
2598 
2599 #endif /* U_SHOW_CPLUSPLUS_API */
2600 
2601 #endif // MESSAGEFORMAT_DATA_MODEL_H
2602 
2603 // eof
2604 
"Smart pointer" class, deletes objects via the C++ array delete[] operator.
Definition: localpointer.h:366
"Smart pointer" base class; do not use directly: use LocalPointer etc.
Definition: localpointer.h:68
UMemory is the common ICU base class.
Definition: uobject.h:115
UObject is the common ICU "boilerplate" class.
Definition: uobject.h:223
UnicodeString is a string class that stores Unicode characters directly and provides similar function...
Definition: unistr.h:296
The mutable MFDataModel::Builder class allows the data model to be constructed incrementally.
Builder(UErrorCode &status)
Default constructor.
Builder & setPattern(Pattern &&pattern)
Sets the body of the message as a pattern.
Builder & addVariant(SelectorKeys &&keys, Pattern &&pattern, UErrorCode &errorCode) noexcept
Adds a single variant.
MFDataModel build(UErrorCode &status) const noexcept
Constructs a new immutable data model.
Builder & addSelector(VariableName &&selector, UErrorCode &errorCode)
Adds a selector variable.
Builder & addBinding(Binding &&b, UErrorCode &status)
Adds a binding, There must not already be a binding with the same name.
The MFDataModel class describes a parsed representation of the text of a message.
std::vector< VariableName > getSelectors() const
Accesses the selectors.
virtual ~MFDataModel()
Destructor.
std::vector< Variant > getVariants() const
Accesses the variants.
MFDataModel & operator=(MFDataModel) noexcept
Assignment operator.
MFDataModel()
Default constructor.
friend void swap(MFDataModel &m1, MFDataModel &m2) noexcept
Non-member swap function.
std::vector< Binding > getLocalVariables() const
Accesses the local variable declarations for this data model.
MFDataModel(const MFDataModel &other)
Copy constructor.
A Binding pairs a variable name with an expression.
Binding & operator=(Binding) noexcept
Copy assignment operator.
UBool isLocal() const
Returns true if and only if this binding represents a local declaration.
Binding(const Binding &other)
Copy constructor.
const Expression & getValue() const
Accesses the right-hand side of a binding.
const VariableName & getVariable() const
Accesses the left-hand side of the binding.
static Binding input(UnicodeString &&variableName, Expression &&rhs, UErrorCode &errorCode)
Constructor for input binding.
Binding(const VariableName &v, Expression &&e)
Constructor.
friend void swap(Binding &b1, Binding &b2) noexcept
Non-member swap function.
The mutable Expression::Builder class allows the operator to be constructed incrementally.
Expression build(UErrorCode &status)
Constructs a new immutable Expression using the operand and operator that were previously set.
Builder & addAttribute(const UnicodeString &key, Operand &&value, UErrorCode &status)
Adds a single attribute.
Builder & setOperator(Operator &&rAtor)
Sets the operator of this expression.
Builder & setOperand(Operand &&rAnd)
Sets the operand of this expression.
Builder(UErrorCode &status)
Default constructor.
The Expression class corresponds to the expression nonterminal in the MessageFormat 2 grammar and the...
Expression & operator=(Expression) noexcept
Assignment operator.
const Operator * getOperator(UErrorCode &status) const
Accesses the function annotating this expression.
UBool isFunctionCall() const
Checks if this expression has a function annotation (with or without an operand).
std::vector< Option > getAttributes() const
Gets the attributes of this expression.
UBool isStandaloneAnnotation() const
Checks if this expression is an annotation with no operand.
const Operand & getOperand() const
Accesses the operand of this expression.
Expression(const Expression &other)
Copy constructor.
friend void swap(Expression &e1, Expression &e2) noexcept
Non-member swap function.
The Key class corresponds to the key nonterminal in the MessageFormat 2 grammar, https://github....
Key(const Key &other)
Copy constructor.
UBool isWildcard() const
Determines if this is a wildcard key.
Key & operator=(Key) noexcept
Assignment operator.
const Literal & asLiteral() const
Returns the contents of this key as a literal.
virtual ~Key()
Destructor.
Key(const Literal &lit)
Literal key constructor.
Key()
Wildcard constructor; constructs a Key representing the catchall or wildcard key, '*'.
bool operator<(const Key &other) const
Less than operator.
bool operator==(const Key &other) const
Equality operator.
friend void swap(Key &k1, Key &k2) noexcept
Non-member swap function.
The Literal class corresponds to the literal nonterminal in the MessageFormat 2 grammar,...
UBool isQuoted() const
Determines if this literal appeared as a quoted literal in the message.
friend void swap(Literal &l1, Literal &l2) noexcept
Non-member swap function.
Literal(UBool q, const UnicodeString &s)
Literal constructor.
const UnicodeString & unquoted() const
Returns the parsed string contents of this literal.
UnicodeString quoted() const
Returns the quoted representation of this literal (enclosed in '|' characters)
Literal()=default
Default constructor.
bool operator<(const Literal &other) const
Less than operator.
Literal & operator=(Literal) noexcept
Assignment operator.
Literal(const Literal &other)
Copy constructor.
bool operator==(const Literal &other) const
Equality operator.
The mutable Markup::Builder class allows the markup to be constructed incrementally.
Builder & setName(const UnicodeString &n)
Sets the name of this markup.
Builder & setStandalone()
Sets this to be a standalone markup.
Builder(UErrorCode &status)
Default constructor.
Builder & setOpen()
Sets this to be an opening markup.
Builder & addOption(const UnicodeString &key, Operand &&value, UErrorCode &status)
Adds a single option.
Builder & setClose()
Sets this to be an closing markup.
Markup build(UErrorCode &status)
Constructs a new immutable Markup using the name and type and (optionally) options and attributes tha...
Builder & addAttribute(const UnicodeString &key, Operand &&value, UErrorCode &status)
Adds a single attribute.
The Markup class corresponds to the markup nonterminal in the MessageFormat 2 grammar and the markup ...
std::vector< Option > getAttributes() const
Gets the attributes of this markup.
UBool isOpen() const
Checks if this markup is an opening tag.
UBool isClose() const
Checks if this markup is an closing tag.
virtual ~Markup()
Destructor.
std::vector< Option > getOptions() const
Gets the options of this markup.
const UnicodeString & getName() const
Gets the name of this markup.
UBool isStandalone() const
Checks if this markup is an standalone tag.
The Operand class corresponds to the operand nonterminal in the MessageFormat 2 grammar,...
virtual UBool isNull() const
Determines if this operand is the null operand.
const UnicodeString & asVariable() const
Returns a reference to this operand's variable name.
const Literal & asLiteral() const
Returns a reference to this operand's literal contents.
friend void swap(Operand &o1, Operand &o2) noexcept
Non-member swap function.
Operand(const Literal &l)
Literal operand constructor.
UBool isVariable() const
Determines if this operand represents a variable.
UBool isLiteral() const
Determines if this operand represents a literal.
Operand(const UnicodeString &v)
Variable operand constructor.
Operand(const Operand &)
Copy constructor.
virtual Operand & operator=(Operand) noexcept
Assignment operator.
The mutable Operator::Builder class allows the operator to be constructed incrementally.
Operator build(UErrorCode &status)
Constructs a new immutable Operator using the function name and options that were previously set.
Builder & setFunctionName(FunctionName &&func)
Sets this operator to be a function annotation and sets its name to func.
Builder & addOption(const UnicodeString &key, Operand &&value, UErrorCode &status) noexcept
Sets this operator to be a function annotation and adds a single option.
Builder(UErrorCode &status)
Default constructor.
The Operator class corresponds to the FunctionRef type in the Expression interface defined in https:/...
Operator(const Operator &other) noexcept
Copy constructor.
Operator & operator=(Operator) noexcept
Assignment operator.
friend void swap(Operator &o1, Operator &o2) noexcept
Non-member swap function.
const FunctionName & getFunctionName() const
Accesses the function name.
std::vector< Option > getOptions() const
Accesses function options.
An Option pairs an option name with an Operand.
const UnicodeString & getName() const
Accesses the left-hand side of the option.
Option & operator=(Option other) noexcept
Assignment operator.
const Operand & getValue() const
Accesses the right-hand side of the option.
Option(const Option &other)
Copy constructor.
virtual ~Option()
Destructor.
Option(const UnicodeString &n, Operand &&r)
Constructor.
friend void swap(Option &o1, Option &o2) noexcept
Non-member swap function.
A PatternPart is a single element (text or expression) in a Pattern.
UBool isExpression() const
Checks if the part is an expression part.
PatternPart(const UnicodeString &t)
Text part constructor.
PatternPart(Expression &&e)
Expression part constructor.
PatternPart & operator=(PatternPart) noexcept
Assignment operator.
PatternPart()=default
Default constructor.
PatternPart(Markup &&m)
Markup part constructor.
UBool isMarkup() const
Checks if the part is a markup part.
UBool isText() const
Checks if the part is a text part.
const Markup & asMarkup() const
Accesses the expression of the part.
const Expression & contents() const
Accesses the expression of the part.
const UnicodeString & asText() const
Accesses the text contents of the part.
PatternPart(const PatternPart &other)
Copy constructor.
friend void swap(PatternPart &p1, PatternPart &p2) noexcept
Non-member swap function.
The mutable Pattern::Builder class allows the pattern to be constructed one part at a time.
Pattern build(UErrorCode &status) const noexcept
Constructs a new immutable Pattern using the list of parts set with previous add() calls.
Builder(UErrorCode &status)
Default constructor.
Builder & add(UnicodeString &&part, UErrorCode &status) noexcept
Adds a single text part to the pattern.
Builder & add(Expression &&part, UErrorCode &status) noexcept
Adds a single expression part to the pattern.
Builder & add(Markup &&part, UErrorCode &status) noexcept
Adds a single markup part to the pattern.
A Pattern is a sequence of formattable parts.
Iterator end() const
Returns a special value to mark the end of iteration.
Pattern & operator=(Pattern) noexcept
Assignment operator.
Pattern(const Pattern &other)
Copy constructor.
friend void swap(Pattern &p1, Pattern &p2) noexcept
Non-member swap function.
Iterator begin() const
Returns the parts of this pattern.
The mutable SelectorKeys::Builder class allows the key list to be constructed one key at a time.
Builder & add(Key &&key, UErrorCode &status) noexcept
Adds a single key to the list.
Builder(UErrorCode &status)
Default constructor.
SelectorKeys build(UErrorCode &status) const
Constructs a new immutable SelectorKeys using the list of keys set with previous add() calls.
The SelectorKeys class represents the key list for a single variant.
friend void swap(SelectorKeys &s1, SelectorKeys &s2) noexcept
Non-member swap function.
SelectorKeys & operator=(SelectorKeys other) noexcept
Assignment operator.
bool operator<(const SelectorKeys &other) const
Less than operator.
std::vector< Key > getKeys() const
Returns the underlying list of keys.
SelectorKeys(const SelectorKeys &other)
Copy constructor.
A Variant pairs a list of keys with a pattern It corresponds to the Variant interface defined in http...
Variant(const Variant &)
Copy constructor.
Variant(const SelectorKeys &keys, Pattern &&pattern)
Constructor.
friend void swap(Variant &v1, Variant &v2) noexcept
Non-member swap function.
Variant & operator=(Variant other) noexcept
Assignment operator.
const SelectorKeys & getKeys() const
Accesses the keys of the variant.
Variant()=default
Default constructor.
const Pattern & getPattern() const
Accesses the pattern of the variant.
C++ API: "Smart pointers" for use with and in ICU4C C++ code.
U_EXPORT UBool operator==(const StringPiece &x, const StringPiece &y)
Global operator == for StringPiece.
bool operator!=(const StringPiece &x, const StringPiece &y)
Global operator != for StringPiece.
Definition: stringpiece.h:346
The Pattern::Iterator class provides an iterator over the formattable parts of a pattern.
reference operator*() const
Dereference operator (gets the element at the current iterator position)
Iterator operator++()
Increment operator (advances to the next iterator position)
int8_t UBool
The ICU boolean type, a signed-byte integer.
Definition: umachine.h:247
Basic definitions for ICU, for both C and C++ APIs.
UErrorCode
Standard ICU4C error code type, a substitute for exceptions.
Definition: utypes.h:430
#define U_I18N_API
Set to export library symbols from inside the i18n library, and to import them from outside.
Definition: utypes.h:316