ICU4C 79
Loading...
Searching...
No Matches
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
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
29U_NAMESPACE_BEGIN
30
31class 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
38template<typename T>
39static 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
54namespace message2 {
55 class Checker;
56 class MessageFormatter;
57 class Parser;
58 class Serializer;
59
60
61 namespace data_model {
62 class Binding;
63 class Literal;
64 class Operator;
65 class MFDataModel;
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 }
141
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
216 public:
243 U_I18N_API virtual UBool isNull() const;
271 U_I18N_API Operand() : contents(std::nullopt) {}
281 U_I18N_API explicit Operand(const UnicodeString& v) : contents(VariableName(v)) {}
291 U_I18N_API explicit Operand(const Literal& l) : contents(l) {}
300 U_I18N_API friend inline void swap(Operand& o1, Operand& o2) noexcept {
301 using std::swap;
302 (void) o1;
303 (void) o2;
304 swap(o1.contents, o2.contents);
305 }
306
327 private:
328 std::optional<std::variant<VariableName, Literal>> contents;
329 }; // class Operand
330
346 class U_I18N_API_CLASS Key : public UObject {
347 public:
356 U_I18N_API UBool isWildcard() const { return !contents.has_value(); }
373 U_I18N_API Key(const Key& other) : contents(other.contents) {}
381 U_I18N_API Key() : contents(std::nullopt) {}
391 U_I18N_API explicit Key(const Literal& lit) : contents(lit) {}
400 U_I18N_API friend inline void swap(Key& k1, Key& k2) noexcept {
401 using std::swap;
402
403 swap(k1.contents, k2.contents);
404 }
405
425 U_I18N_API bool operator<(const Key& other) const;
439 U_I18N_API bool operator==(const Key& other) const;
446 U_I18N_API virtual ~Key();
447 private:
448 /* const */ std::optional<Literal> contents;
449 }; // class Key
450
462 public:
473 U_I18N_API std::vector<Key> getKeys() const {
474 return toStdVector<Key>(keys.getAlias(), len);
475 }
476
485 class U_I18N_API Builder : public UMemory {
486 private:
487 friend class SelectorKeys;
488 UVector* keys; // This is a raw pointer and not a LocalPointer<UVector> to avoid undefined behavior warnings,
489 // since UVector is forward-declared
490 // The vector owns its elements
491 public:
502 Builder& add(Key&& key, UErrorCode& status) noexcept;
515 SelectorKeys build(UErrorCode& status) const;
532 virtual ~Builder();
533 Builder(const Builder&) = delete;
534 Builder& operator=(const Builder&) = delete;
535 Builder(Builder&&) = delete;
536 Builder& operator=(Builder&&) = delete;
537 }; // class SelectorKeys::Builder
538
552 U_I18N_API bool operator<(const SelectorKeys& other) const;
569 U_I18N_API friend inline void swap(SelectorKeys& s1, SelectorKeys& s2) noexcept {
570 using std::swap;
571
572 swap(s1.len, s2.len);
573 swap(s1.keys, s2.keys);
574 }
575
596 private:
597 friend class Builder;
598 friend class message2::Checker;
599 friend class message2::MessageFormatter;
600 friend class message2::Serializer;
601
602 /* const */ LocalArray<Key> keys;
603 /* const */ int32_t len;
604
605 const Key* getKeysInternal() const;
606 SelectorKeys(const UVector& ks, UErrorCode& status);
607 }; // class SelectorKeys
608
609 class Operator;
610
619 class U_I18N_API Option : public UObject {
620 public:
629 const Operand& getValue() const { return rand; }
638 const UnicodeString& getName() const { return name; }
649 Option(const UnicodeString& n, Operand&& r) : name(n), rand(std::move(r)) {}
666 friend inline void swap(Option& o1, Option& o2) noexcept {
667 using std::swap;
668
669 swap(o1.name, o2.name);
670 swap(o1.rand, o2.rand);
671 }
672
678 Option(const Option& other);
685 Option& operator=(Option other) noexcept;
692 virtual ~Option();
693 private:
694 /* const */ UnicodeString name;
695 /* const */ Operand rand;
696 }; // class Option
697
698 // Internal only
699 #ifndef U_IN_DOXYGEN
700 // Options
701 // This is a wrapper class around a vector of options that provides lookup operations
702 class U_I18N_API_CLASS OptionMap : public UObject {
703 public:
704 U_I18N_API int32_t size() const;
705 // Needs to take an error code b/c an earlier copy might have failed
706 U_I18N_API const Option& getOption(int32_t, UErrorCode&) const;
707 U_I18N_API friend inline void swap(OptionMap& m1, OptionMap& m2) noexcept {
708 using std::swap;
709
710 swap(m1.bogus, m2.bogus);
711 swap(m1.options, m2.options);
712 swap(m1.len, m2.len);
713 }
714 U_I18N_API OptionMap() : len(0) {}
715 U_I18N_API OptionMap(const OptionMap&);
716 U_I18N_API OptionMap& operator=(OptionMap);
717 U_I18N_API std::vector<Option> getOptions() const {
718 return toStdVector<Option>(options.getAlias(), len);
719 }
720 U_I18N_API OptionMap(const UVector&, UErrorCode&);
721 U_I18N_API OptionMap(Option*, int32_t);
722 U_I18N_API virtual ~OptionMap();
723
724 class U_I18N_API Builder : public UObject {
725 private:
726 UVector* options;
727 bool checkDuplicates = true;
728 public:
729 Builder& add(Option&& opt, UErrorCode&);
730 Builder(UErrorCode&);
731 static Builder attributes(UErrorCode&);
732 // As this class is private, build() is destructive
733 OptionMap build(UErrorCode&);
734 friend inline void swap(Builder& m1, Builder& m2) noexcept {
735 using std::swap;
736
737 swap(m1.options, m2.options);
738 swap(m1.checkDuplicates, m2.checkDuplicates);
739 }
740 Builder(Builder&&);
741 Builder(const Builder&) = delete;
742 Builder& operator=(Builder) noexcept;
743 virtual ~Builder();
744 }; // class OptionMap::Builder
745 private:
746 friend class message2::MessageFormatter;
747 friend class message2::Serializer;
748
749 bool bogus = false;
750 LocalArray<Option> options;
751 int32_t len;
752 }; // class OptionMap
753 #endif
754
768 class U_I18N_API Operator : public UObject {
769 public:
778 const FunctionName& getFunctionName() const;
787 std::vector<Option> getOptions() const {
788 return options.getOptions();
789 }
790
799 class U_I18N_API Builder : public UMemory {
800 private:
801 friend class Operator;
802 FunctionName functionName;
803 OptionMap::Builder options;
804 public:
815 Builder& setFunctionName(FunctionName&& func);
828 Builder& addOption(const UnicodeString &key, Operand&& value, UErrorCode& status) noexcept;
844 Operator build(UErrorCode& status);
861 virtual ~Builder();
862 Builder(const Builder&) = delete;
863 Builder& operator=(const Builder&) = delete;
864 Builder(Builder&&) = delete;
865 Builder& operator=(Builder&&) = delete;
866 }; // class Operator::Builder
867
873 Operator(const Operator& other) noexcept;
882 friend inline void swap(Operator& o1, Operator& o2) noexcept {
883 using std::swap;
884
885 swap(o1.name, o2.name);
886 swap(o1.options, o2.options);
887 }
888
909 virtual ~Operator();
910 private:
911 friend class Binding;
912 friend class Builder;
913 friend class message2::Checker;
914 friend class message2::MessageFormatter;
915 friend class message2::Serializer;
916
917 // Function call constructor
918 Operator(const FunctionName& f, const UVector& options, UErrorCode&);
919
920 const OptionMap& getOptionsInternal() const;
921 Operator(const FunctionName&, const OptionMap&);
922
923 /* const */ FunctionName name;
924 /* const */ OptionMap options;
925 }; // class Operator
926
927 // Internal only
928 typedef enum UMarkupType {
929 UMARKUP_OPEN = 0,
930 UMARKUP_CLOSE,
931 UMARKUP_STANDALONE,
932 UMARKUP_COUNT
933 } UMarkupType;
934
945 class U_I18N_API Markup : public UObject {
946 public:
955 UBool isOpen() const { return (type == UMARKUP_OPEN); }
964 UBool isClose() const { return (type == UMARKUP_CLOSE); }
973 UBool isStandalone() const { return (type == UMARKUP_STANDALONE); }
982 const UnicodeString& getName() const { return name; }
991 std::vector<Option> getOptions() const { return options.getOptions(); }
1000 std::vector<Option> getAttributes() const { return attributes.getOptions(); }
1015 virtual ~Markup();
1025 class U_I18N_API Builder : public UMemory {
1026 private:
1027 friend class Markup;
1028
1029 UnicodeString name;
1030 OptionMap::Builder options;
1031 OptionMap::Builder attributes;
1032 UMarkupType type = UMARKUP_COUNT;
1033 public:
1043 Builder& setName(const UnicodeString& n) { name = n; return *this; }
1052 Builder& setOpen() { type = UMARKUP_OPEN; return *this; }
1061 Builder& setClose() { type = UMARKUP_CLOSE; return *this; }
1070 Builder& setStandalone() { type = UMARKUP_STANDALONE; return *this; }
1082 Builder& addOption(const UnicodeString &key, Operand&& value, UErrorCode& status);
1094 Builder& addAttribute(const UnicodeString &key, Operand&& value, UErrorCode& status);
1112 Markup build(UErrorCode& status);
1129 virtual ~Builder();
1130 Builder(const Builder&) = delete;
1131 Builder& operator=(const Builder&) = delete;
1132 Builder(Builder&&) = delete;
1133 Builder& operator=(Builder&&) = delete;
1134 }; // class Markup::Builder
1135
1136 private:
1137 friend class Builder;
1138 friend class message2::MessageFormatter;
1139 friend class message2::Serializer;
1140
1141 UMarkupType type;
1142 UnicodeString name;
1143 OptionMap options;
1144 OptionMap attributes;
1145 const OptionMap& getOptionsInternal() const { return options; }
1146 const OptionMap& getAttributesInternal() const { return attributes; }
1147 Markup(UMarkupType, UnicodeString, OptionMap&&, OptionMap&&);
1148 }; // class Markup
1149
1164 public:
1219 U_I18N_API std::vector<Option> getAttributes() const { return attributes.getOptions(); }
1229 class U_I18N_API Builder : public UMemory {
1230 private:
1231 friend class Expression;
1232
1233 bool hasOperand = false;
1234 bool hasOperator = false;
1235 Operand rand;
1236 Operator rator;
1237 OptionMap::Builder attributes;
1238 public:
1270 Builder& addAttribute(const UnicodeString &key, Operand&& value, UErrorCode& status);
1288 Expression build(UErrorCode& status);
1305 virtual ~Builder();
1306 Builder(const Builder&) = delete;
1307 Builder& operator=(const Builder&) = delete;
1308 Builder(Builder&&) = delete;
1309 Builder& operator=(Builder&&) = delete;
1310 }; // class Expression::Builder
1311
1319 U_I18N_API friend inline void swap(Expression& e1, Expression& e2) noexcept {
1320 using std::swap;
1321
1322 swap(e1.rator, e2.rator);
1323 swap(e1.rand, e2.rand);
1324 swap(e1.attributes, e2.attributes);
1325 }
1326
1355 private:
1356 friend class message2::Serializer;
1357
1358 /*
1359 Internally, an expression is represented as the application of an optional operator to an operand.
1360 The operand is always present; for function calls with no operand, it's represented
1361 as an operand for which `isNull()` is true.
1362
1363 Operator | Operand
1364 --------------------------------
1365 { |42| :fun opt=value } => (FunctionName=fun, | Literal(quoted=true, contents="42")
1366 options={opt: value})
1367 { abcd } => null | Literal(quoted=false, contents="abcd")
1368 { : fun opt=value } => (FunctionName=fun,
1369 options={opt: value}) | NullOperand()
1370 */
1371
1372 Expression(const Operator &rAtor, const Operand &rAnd, const OptionMap& attrs) : rator(rAtor), rand(rAnd), attributes(attrs) {}
1373 Expression(const Operand &rAnd, const OptionMap& attrs) : rator(std::nullopt), rand(Operand(rAnd)), attributes(attrs) {}
1374 Expression(const Operator &rAtor, const OptionMap& attrs) : rator(rAtor), rand(), attributes(attrs) {}
1375 /* const */ std::optional<Operator> rator;
1376 /* const */ Operand rand;
1377 /* const */ OptionMap attributes;
1378 const OptionMap& getAttributesInternal() const { return attributes; }
1379 }; // class Expression
1380
1381 class Pattern;
1382
1383 // Despite the comments, `PatternPart` is internal-only
1395 public:
1404 U_I18N_API UBool isText() const { return std::holds_alternative<UnicodeString>(piece); }
1413 U_I18N_API UBool isMarkup() const { return std::holds_alternative<Markup>(piece); }
1422 U_I18N_API UBool isExpression() const { return std::holds_alternative<Expression>(piece); }
1461 U_I18N_API friend inline void swap(PatternPart& p1, PatternPart& p2) noexcept {
1462 using std::swap;
1463
1464 swap(p1.piece, p2.piece);
1465 }
1466
1496 U_I18N_API explicit PatternPart(const UnicodeString& t) : piece(t) {}
1506 U_I18N_API explicit PatternPart(Expression&& e) : piece(e) {}
1516 U_I18N_API explicit PatternPart(Markup&& m) : piece(m) {}
1525 private:
1526 friend class Pattern;
1527
1528 std::variant<UnicodeString, Expression, Markup> piece;
1529 }; // class PatternPart
1530
1542 private:
1543 friend class PatternPart;
1544
1545 public:
1546 #ifndef U_IN_DOXYGEN
1547 struct U_I18N_API Iterator;
1548 #endif
1559 return Iterator(this, 0);
1560 }
1561
1571 return Iterator(this, len);
1572 }
1573
1582 class U_I18N_API Builder : public UMemory {
1583 private:
1584 friend class Pattern;
1585
1586 UVector* parts; // Not a LocalPointer for the same reason as in `SelectorKeys::Builder`
1587
1588 public:
1599 Builder& add(Expression&& part, UErrorCode& status) noexcept;
1610 Builder& add(Markup&& part, UErrorCode& status) noexcept;
1621 Builder& add(UnicodeString&& part, UErrorCode& status) noexcept;
1634 Pattern build(UErrorCode& status) const noexcept;
1651 virtual ~Builder();
1652 Builder(const Builder&) = delete;
1653 Builder& operator=(const Builder&) = delete;
1654 Builder(Builder&&) = delete;
1655 Builder& operator=(Builder&&) = delete;
1656 }; // class Pattern::Builder
1657
1665 U_I18N_API Pattern() : parts(LocalArray<PatternPart>()) {}
1674 U_I18N_API friend inline void swap(Pattern& p1, Pattern& p2) noexcept {
1675 using std::swap;
1676
1677 swap(p1.bogus, p2.bogus);
1678 swap(p1.len, p2.len);
1679 swap(p1.parts, p2.parts);
1680 }
1681
1702
1712 struct U_I18N_API Iterator {
1713 private:
1714 using iterator_category = std::forward_iterator_tag;
1715 using difference_type = std::ptrdiff_t;
1716 using value_type = std::variant<UnicodeString, Expression, Markup>;
1717 using pointer = value_type*;
1718 using reference = const value_type&;
1719
1720 friend class Pattern;
1721 Iterator(const Pattern* p, int32_t i) : pos(i), pat(p) {}
1722 friend bool operator== (const Iterator& a, const Iterator& b) { return (a.pat == b.pat && a.pos == b.pos); }
1723
1724 int32_t pos;
1725 const Pattern* pat;
1726
1727 public:
1734 reference operator*() const {
1735 const PatternPart& part = pat->parts[pos];
1736 return patternContents(part);
1737 }
1738
1744 Iterator operator++() { pos++; return *this; }
1751 friend bool operator!= (const Iterator& a, const Iterator& b) { return !(a == b); }
1752 }; // struct Iterator
1753
1754 private:
1755 friend class Builder;
1756 friend class message2::MessageFormatter;
1757 friend class message2::Serializer;
1758
1759 // Set to true if a copy constructor fails;
1760 // needed in order to distinguish an uninitialized
1761 // Pattern from a 0-length pattern
1762 bool bogus = false;
1763
1764 // Possibly-empty array of parts
1765 int32_t len = 0;
1767
1768 Pattern(const UVector& parts, UErrorCode& status);
1769 // Helper
1770 static void initParts(Pattern&, const Pattern&);
1771
1780 int32_t numParts() const;
1791 const PatternPart& getPart(int32_t i) const;
1792
1793 // Gets around not being able to declare Pattern::Iterator as a friend
1794 // in PatternPart
1795 static const std::variant<UnicodeString, Expression, Markup>&
1796 patternContents(const PatternPart& p) { return p.piece; }
1797 }; // class Pattern
1798
1809 class U_I18N_API Variant : public UObject {
1810 public:
1819 const Pattern& getPattern() const { return p; }
1828 const SelectorKeys& getKeys() const { return k; }
1840 Variant(const SelectorKeys& keys, Pattern&& pattern) : k(keys), p(std::move(pattern)) {}
1849 friend inline void swap(Variant& v1, Variant& v2) noexcept {
1850 using std::swap;
1851
1852 swap(v1.k, v2.k);
1853 swap(v1.p, v2.p);
1854 }
1855
1861 Variant& operator=(Variant other) noexcept;
1869 Variant() = default;
1883 virtual ~Variant();
1884 private:
1885 /* const */ SelectorKeys k;
1886 /* const */ Pattern p;
1887 }; // class Variant
1888
1899 class U_I18N_API Binding : public UObject {
1900 public:
1909 const Expression& getValue() const;
1918 const VariableName& getVariable() const { return var; }
1933 static Binding input(UnicodeString&& variableName, Expression&& rhs, UErrorCode& errorCode);
1943 UBool isLocal() const { return local; }
1953 Binding(const VariableName& v, Expression&& e) : var(v), expr(std::move(e)), local(true), annotation(nullptr) {}
1962 friend inline void swap(Binding& b1, Binding& b2) noexcept {
1963 using std::swap;
1964
1965 swap(b1.var, b2.var);
1966 swap(b1.expr, b2.expr);
1967 swap(b1.local, b2.local);
1968 b1.updateAnnotation();
1969 b2.updateAnnotation();
1970 }
1971
1977 Binding(const Binding& other);
1992 Binding() : local(true) {}
1999 virtual ~Binding();
2000 private:
2001 friend class message2::Checker;
2002 friend class message2::MessageFormatter;
2003 friend class message2::Parser;
2004 friend class message2::Serializer;
2005
2006 /* const */ VariableName var;
2007 /* const */ Expression expr;
2008 /* const */ bool local;
2009
2010 // The following field is always nullptr for a local
2011 // declaration, and possibly nullptr for an .input declaration
2012 // If non-null, the referent is a member of `expr` so
2013 // its lifetime is the same as the lifetime of the enclosing Binding
2014 // (as long as there's no mutation)
2015 const Operator* annotation = nullptr;
2016
2017 const OptionMap& getOptionsInternal() const;
2018
2019 bool hasAnnotation() const { return !local && (annotation != nullptr); }
2020 void updateAnnotation();
2021 }; // class Binding
2022
2023 // Internal only
2024
2025 #ifndef U_IN_DOXYGEN
2026 class U_I18N_API_CLASS Matcher : public UObject {
2027 public:
2028 U_I18N_API Matcher& operator=(Matcher);
2029 U_I18N_API Matcher(const Matcher&);
2038 U_I18N_API friend inline void swap(Matcher& m1, Matcher& m2) noexcept {
2039 using std::swap;
2040
2041 if (m1.bogus) {
2042 m2.bogus = true;
2043 return;
2044 }
2045 if (m2.bogus) {
2046 m1.bogus = true;
2047 return;
2048 }
2049 swap(m1.selectors, m2.selectors);
2050 swap(m1.numSelectors, m2.numSelectors);
2051 swap(m1.variants, m2.variants);
2052 swap(m1.numVariants, m2.numVariants);
2053 }
2054 U_I18N_API virtual ~Matcher();
2055 private:
2056
2057 friend class MFDataModel;
2058
2059 Matcher(VariableName* ss, int32_t ns, Variant* vs, int32_t nv);
2060 Matcher() {}
2061
2062 // A Matcher may have numSelectors=0 and numVariants=0
2063 // (this is a data model error, but it's representable).
2064 // So we have to keep a separate flag to track failed copies.
2065 bool bogus = false;
2066
2067 // The variables that are being matched on.
2068 LocalArray<VariableName> selectors;
2069 // The number of selectors
2070 int32_t numSelectors = 0;
2071 // The list of `when` clauses (case arms).
2072 LocalArray<Variant> variants;
2073 // The number of variants
2074 int32_t numVariants = 0;
2075 }; // class Matcher
2076 #endif
2077
2078 // -----------------------------------------------------------------------
2079 // Public MFDataModel class
2080
2098 /*
2099 Classes that represent nodes in the data model are nested inside the
2100 `MFDataModel` class.
2101
2102 Classes such as `Expression`, `Pattern` and `VariantMap` are immutable and
2103 are constructed using the builder pattern.
2104
2105 Most classes representing nodes have copy constructors. This is because builders
2106 contain immutable data that must be copied when calling `build()`, since the builder
2107 could go out of scope before the immutable result of the builder does. Copying is
2108 also necessary to prevent unexpected mutation if intermediate builders are saved
2109 and mutated again after calling `build()`.
2110
2111 The copy constructors perform a deep copy, for example by copying the entire
2112 list of options for an `Operator` (and copying the entire underlying vector.)
2113 Some internal fields should be `const`, but are declared as non-`const` to make
2114 the copy constructor simpler to implement. (These are noted throughout.) In
2115 other words, those fields are `const` except during the execution of a copy
2116 constructor.
2117
2118 On the other hand, intermediate `Builder` methods that return a `Builder&`
2119 mutate the state of the builder, so in code like:
2120
2121 Expression::Builder& exprBuilder = Expression::builder()-> setOperand(foo);
2122 Expression::Builder& exprBuilder2 = exprBuilder.setOperator(bar);
2123
2124 the call to `setOperator()` would mutate `exprBuilder`, since `exprBuilder`
2125 and `exprBuilder2` are references to the same object.
2126
2127 An alternate choice would be to make `build()` destructive, so that copying would
2128 be unnecessary. Or, both copying and moving variants of `build()` could be
2129 provided. Copying variants of the intermediate `Builder` methods could be
2130 provided as well, if this proved useful.
2131 */
2132 public:
2141 U_I18N_API std::vector<Binding> getLocalVariables() const {
2142 std::vector<Binding> result;
2143 if (!bogus) {
2144 return toStdVector<Binding>(bindings.getAlias(), bindingsLen);
2145 }
2146 return {};
2147 }
2148
2156 U_I18N_API std::vector<VariableName> getSelectors() const {
2157 if (std::holds_alternative<Pattern>(body)) {
2158 return {};
2159 }
2160 const Matcher* match = std::get_if<Matcher>(&body);
2161 // match must be non-null, given the previous check
2162 return toStdVector<VariableName>(match->selectors.getAlias(), match->numSelectors);
2163 }
2164
2172 U_I18N_API std::vector<Variant> getVariants() const {
2173 // Return empty vector if no variants
2174 if (std::holds_alternative<Pattern>(body)) {
2175 return {};
2176 }
2177 const Matcher* match = std::get_if<Matcher>(&body);
2178 // match must be non-null, given the previous check
2179 return toStdVector<Variant>(match->variants.getAlias(), match->numVariants);
2180 return {};
2181 }
2182
2216 U_I18N_API friend inline void swap(MFDataModel& m1, MFDataModel& m2) noexcept {
2217 using std::swap;
2218
2219 if (m1.bogus) {
2220 m2.bogus = true;
2221 return;
2222 }
2223 if (m2.bogus) {
2224 m1.bogus = true;
2225 return;
2226 }
2227 swap(m1.body, m2.body);
2228 swap(m1.bindings, m2.bindings);
2229 swap(m1.bindingsLen, m2.bindingsLen);
2230 }
2231
2252
2260 class U_I18N_API Builder : public UMemory {
2261 private:
2262 friend class MFDataModel;
2263
2264 void checkDuplicate(const VariableName&, UErrorCode&) const;
2265 void buildSelectorsMessage(UErrorCode&);
2266 bool hasPattern = true;
2267 bool hasSelectors = false;
2268 Pattern pattern;
2269 // The following members are not LocalPointers for the same reason as in SelectorKeys::Builder
2270 UVector* selectors = nullptr;
2271 UVector* variants = nullptr;
2272 UVector* bindings = nullptr;
2273 public:
2298 Builder& addSelector(VariableName&& selector, UErrorCode& errorCode);
2311 Builder& addVariant(SelectorKeys&& keys, Pattern&& pattern, UErrorCode& errorCode) noexcept;
2343 MFDataModel build(UErrorCode& status) const noexcept;
2363 virtual ~Builder();
2364 Builder(const Builder&) = delete;
2365 Builder& operator=(const Builder&) = delete;
2366 Builder(Builder&&) = delete;
2367 Builder& operator=(Builder&&) = delete;
2368 }; // class Builder
2369
2370 private:
2371 friend class message2::Checker;
2372 friend class message2::MessageFormatter;
2373 friend class message2::Serializer;
2374
2375 Pattern empty; // Provided so that `getPattern()` can return a result
2376 // if called on a selectors message
2377 bool hasPattern() const { return std::holds_alternative<Pattern>(body); }
2378
2379 bool bogus = false; // Set if a copy constructor fails
2380
2381 // A message body is either a matcher (selector list and variant list),
2382 // or a single pattern
2383 std::variant<Matcher, Pattern> body;
2384
2385 // Bindings for local variables
2386 /* const */ LocalArray<Binding> bindings;
2387 int32_t bindingsLen = 0;
2388
2389 const Binding* getLocalVariablesInternal() const;
2390 const VariableName* getSelectorsInternal() const;
2391 const Variant* getVariantsInternal() const;
2392
2393 int32_t numSelectors() const {
2394 const Matcher* matcher = std::get_if<Matcher>(&body);
2395 return (matcher == nullptr ? 0 : matcher->numSelectors);
2396 }
2397 int32_t numVariants() const {
2398 const Matcher* matcher = std::get_if<Matcher>(&body);
2399 return (matcher == nullptr ? 0 : matcher->numVariants);
2400 }
2401
2402 // Helper
2403 void initBindings(const Binding*);
2404
2405 MFDataModel(const Builder& builder, UErrorCode&) noexcept;
2406 }; // class MFDataModel
2407 } // namespace data_model
2408} // namespace message2
2409
2410U_NAMESPACE_END
2411
2412#if defined(U_REAL_MSVC)
2413#pragma warning(pop)
2414#endif
2415
2416#endif // U_HIDE_DEPRECATED_API
2417
2418#endif /* #if !UCONFIG_NO_MF2 */
2419
2420#endif /* #if !UCONFIG_NO_FORMATTING */
2421
2422#endif /* #if !UCONFIG_NO_NORMALIZATION */
2423
2424#endif /* U_SHOW_CPLUSPLUS_API */
2425
2426#endif // MESSAGEFORMAT_DATA_MODEL_H
2427
2428// eof
2429
"Smart pointer" class, deletes objects via the C++ array delete[] operator.
UMemory is the common ICU base class.
Definition uobject.h:115
UObject is the common ICU "boilerplate" class.
Definition uobject.h:222
UnicodeString is a string class that stores Unicode characters directly and provides similar function...
Definition unistr.h:303
A Binding pairs a variable name with an expression.
UBool isLocal() const
Returns true if and only if this binding represents a local declaration.
Binding(const Binding &other)
Copy constructor.
const VariableName & getVariable() const
Accesses the left-hand side of the binding.
Binding & operator=(Binding) noexcept
Copy assignment operator.
static Binding input(UnicodeString &&variableName, Expression &&rhs, UErrorCode &errorCode)
Constructor for input binding.
const Expression & getValue() const
Accesses the right-hand side of a binding.
Binding(const VariableName &v, Expression &&e)
Constructor.
friend void swap(Binding &b1, Binding &b2) noexcept
Non-member swap function.
Builder & addAttribute(const UnicodeString &key, Operand &&value, UErrorCode &status)
Adds a single attribute.
Expression build(UErrorCode &status)
Constructs a new immutable Expression using the operand and operator that were previously set.
Builder & setOperand(Operand &&rAnd)
Sets the operand of this expression.
Builder & setOperator(Operator &&rAtor)
Sets the operator of this expression.
Builder(UErrorCode &status)
Default constructor.
The Expression class corresponds to the expression nonterminal in the MessageFormat 2 grammar and the...
U_I18N_API std::vector< Option > getAttributes() const
Gets the attributes of this expression.
U_I18N_API Expression()
Default constructor.
U_I18N_API friend void swap(Expression &e1, Expression &e2) noexcept
Non-member swap function.
U_I18N_API const Operator * getOperator(UErrorCode &status) const
Accesses the function annotating this expression.
U_I18N_API const Operand & getOperand() const
Accesses the operand of this expression.
U_I18N_API Expression & operator=(Expression) noexcept
Assignment operator.
virtual U_I18N_API ~Expression()
Destructor.
U_I18N_API UBool isStandaloneAnnotation() const
Checks if this expression is an annotation with no operand.
U_I18N_API UBool isFunctionCall() const
Checks if this expression has a function annotation (with or without an operand).
U_I18N_API Expression(const Expression &other)
Copy constructor.
The Key class corresponds to the key nonterminal in the MessageFormat 2 grammar, https://github....
U_I18N_API const Literal & asLiteral() const
Returns the contents of this key as a literal.
U_I18N_API bool operator==(const Key &other) const
Equality operator.
U_I18N_API bool operator<(const Key &other) const
Less than operator.
virtual U_I18N_API ~Key()
Destructor.
U_I18N_API UBool isWildcard() const
Determines if this is a wildcard key.
U_I18N_API Key(const Literal &lit)
Literal key constructor.
U_I18N_API Key(const Key &other)
Copy constructor.
U_I18N_API friend void swap(Key &k1, Key &k2) noexcept
Non-member swap function.
U_I18N_API Key & operator=(Key) noexcept
Assignment operator.
U_I18N_API Key()
Wildcard constructor; constructs a Key representing the catchall or wildcard key, '*'.
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.
const UnicodeString & unquoted() const
Returns the parsed string contents of this literal.
friend void swap(Literal &l1, Literal &l2) noexcept
Non-member swap function.
Literal(UBool q, const UnicodeString &s)
Literal constructor.
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(const Literal &other)
Copy constructor.
Literal & operator=(Literal) noexcept
Assignment operator.
bool operator==(const Literal &other) const
Equality operator.
The mutable MFDataModel::Builder class allows the data model to be constructed incrementally.
Builder & addVariant(SelectorKeys &&keys, Pattern &&pattern, UErrorCode &errorCode) noexcept
Adds a single variant.
Builder(UErrorCode &status)
Default constructor.
Builder & addSelector(VariableName &&selector, UErrorCode &errorCode)
Adds a selector variable.
MFDataModel build(UErrorCode &status) const noexcept
Constructs a new immutable data model.
Builder & setPattern(Pattern &&pattern)
Sets the body of the message as a pattern.
Builder & addBinding(Binding &&b, UErrorCode &status)
Adds a binding, There must not already be a binding with the same name.
U_I18N_API std::vector< Binding > getLocalVariables() const
Accesses the local variable declarations for this data model.
U_I18N_API MFDataModel(const MFDataModel &other)
Copy constructor.
U_I18N_API MFDataModel & operator=(MFDataModel) noexcept
Assignment operator.
virtual U_I18N_API ~MFDataModel()
Destructor.
U_I18N_API friend void swap(MFDataModel &m1, MFDataModel &m2) noexcept
Non-member swap function.
U_I18N_API std::vector< Variant > getVariants() const
Accesses the variants.
U_I18N_API std::vector< VariableName > getSelectors() const
Accesses the selectors.
U_I18N_API MFDataModel()
Default constructor.
U_I18N_API const Pattern & getPattern() const
Accesses the pattern (in a message without selectors).
The mutable Markup::Builder class allows the markup to be constructed incrementally.
Builder & setStandalone()
Sets this to be a standalone markup.
Builder & addOption(const UnicodeString &key, Operand &&value, UErrorCode &status)
Adds a single option.
Builder(UErrorCode &status)
Default constructor.
Builder & addAttribute(const UnicodeString &key, Operand &&value, UErrorCode &status)
Adds a single attribute.
Builder & setClose()
Sets this to be an closing markup.
Builder & setName(const UnicodeString &n)
Sets the name of this markup.
Markup build(UErrorCode &status)
Constructs a new immutable Markup using the name and type and (optionally) options and attributes tha...
Builder & setOpen()
Sets this to be an opening markup.
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.
std::vector< Option > getOptions() const
Gets the options of this markup.
UBool isClose() const
Checks if this markup is an closing tag.
virtual ~Markup()
Destructor.
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 U_I18N_API UBool isNull() const
Determines if this operand is the null operand.
U_I18N_API const UnicodeString & asVariable() const
Returns a reference to this operand's variable name.
U_I18N_API const Literal & asLiteral() const
Returns a reference to this operand's literal contents.
U_I18N_API Operand(const Operand &)
Copy constructor.
U_I18N_API UBool isLiteral() const
Determines if this operand represents a literal.
U_I18N_API friend void swap(Operand &o1, Operand &o2) noexcept
Non-member swap function.
U_I18N_API Operand(const UnicodeString &v)
Variable operand constructor.
U_I18N_API UBool isVariable() const
Determines if this operand represents a variable.
U_I18N_API Operand(const Literal &l)
Literal operand constructor.
virtual U_I18N_API Operand & operator=(Operand) noexcept
Assignment operator.
virtual U_I18N_API ~Operand()
Destructor.
U_I18N_API Operand()
Default constructor.
The mutable Operator::Builder class allows the operator to be constructed incrementally.
Builder & setFunctionName(FunctionName &&func)
Sets this operator to be a function annotation and sets its name to func.
Operator build(UErrorCode &status)
Constructs a new immutable Operator using the function name and options that were previously set.
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:/...
std::vector< Option > getOptions() const
Accesses function options.
Operator(const Operator &other) noexcept
Copy constructor.
const FunctionName & getFunctionName() const
Accesses the function name.
friend void swap(Operator &o1, Operator &o2) noexcept
Non-member swap function.
Operator & operator=(Operator) noexcept
Assignment operator.
An Option pairs an option name with an Operand.
Option(const Option &other)
Copy constructor.
virtual ~Option()
Destructor.
Option & operator=(Option other) noexcept
Assignment operator.
Option(const UnicodeString &n, Operand &&r)
Constructor.
const UnicodeString & getName() const
Accesses the left-hand side of the option.
const Operand & getValue() const
Accesses the right-hand side of the option.
friend void swap(Option &o1, Option &o2) noexcept
Non-member swap function.
A PatternPart is a single element (text or expression) in a Pattern.
U_I18N_API UBool isMarkup() const
Checks if the part is a markup part.
U_I18N_API PatternPart(const PatternPart &other)
Copy constructor.
virtual U_I18N_API ~PatternPart()
Destructor.
U_I18N_API const UnicodeString & asText() const
Accesses the text contents of the part.
U_I18N_API UBool isExpression() const
Checks if the part is an expression part.
U_I18N_API PatternPart(const UnicodeString &t)
Text part constructor.
U_I18N_API friend void swap(PatternPart &p1, PatternPart &p2) noexcept
Non-member swap function.
U_I18N_API const Expression & contents() const
Accesses the expression of the part.
U_I18N_API PatternPart(Markup &&m)
Markup part constructor.
U_I18N_API const Markup & asMarkup() const
Accesses the expression of the part.
U_I18N_API UBool isText() const
Checks if the part is a text part.
U_I18N_API PatternPart()=default
Default constructor.
U_I18N_API PatternPart(Expression &&e)
Expression part constructor.
U_I18N_API PatternPart & operator=(PatternPart) noexcept
Assignment operator.
Builder & add(UnicodeString &&part, UErrorCode &status) noexcept
Adds a single text part to the pattern.
Builder & add(Markup &&part, UErrorCode &status) noexcept
Adds a single markup part to the pattern.
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(Expression &&part, UErrorCode &status) noexcept
Adds a single expression part to the pattern.
A Pattern is a sequence of formattable parts.
U_I18N_API Iterator begin() const
Returns the parts of this pattern.
U_I18N_API friend void swap(Pattern &p1, Pattern &p2) noexcept
Non-member swap function.
U_I18N_API Pattern & operator=(Pattern) noexcept
Assignment operator.
virtual U_I18N_API ~Pattern()
Destructor.
U_I18N_API Iterator end() const
Returns a special value to mark the end of iteration.
U_I18N_API Pattern(const Pattern &other)
Copy constructor.
U_I18N_API Pattern()
Default constructor.
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.
U_I18N_API SelectorKeys(const SelectorKeys &other)
Copy constructor.
U_I18N_API friend void swap(SelectorKeys &s1, SelectorKeys &s2) noexcept
Non-member swap function.
U_I18N_API SelectorKeys()
Default constructor.
U_I18N_API bool operator<(const SelectorKeys &other) const
Less than operator.
U_I18N_API std::vector< Key > getKeys() const
Returns the underlying list of keys.
U_I18N_API SelectorKeys & operator=(SelectorKeys other) noexcept
Assignment operator.
virtual U_I18N_API ~SelectorKeys()
Destructor.
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 & operator=(Variant other) noexcept
Assignment operator.
Variant(const SelectorKeys &keys, Pattern &&pattern)
Constructor.
const Pattern & getPattern() const
Accesses the pattern of the variant.
friend void swap(Variant &v1, Variant &v2) noexcept
Non-member swap function.
const SelectorKeys & getKeys() const
Accesses the keys of the variant.
Variant()=default
Default constructor.
C++ API: "Smart pointers" for use with and in ICU4C C++ code.
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:269
Basic definitions for ICU, for both C and C++ APIs.
UErrorCode
Standard ICU4C error code type, a substitute for exceptions.
Definition utypes.h:509
#define U_I18N_API_CLASS
Set to export library symbols from inside the i18n library, and to import them from outside,...
Definition utypes.h:457
#define U_I18N_API
Set to export library symbols from inside the i18n library, and to import them from outside.
Definition utypes.h:316