• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_FORMATTING
12 
13 #if !UCONFIG_NO_MF2
14 
15 #include "unicode/localpointer.h"
16 #include "unicode/messageformat2_data_model_names.h"
17 
18 #ifndef U_HIDE_DEPRECATED_API
19 
20 #include <algorithm>
21 #include <cstddef>
22 #include <iterator>
23 #include <optional>
24 #include <variant>
25 #include <vector>
26 
27 U_NAMESPACE_BEGIN
28 
29 class UVector;
30 
31 // Helpers
32 
33 // Note: this _must_ be declared `inline` or else gcc will generate code
34 // for its instantiations, which needs to be avoided because it returns
35 // a std::vector
36 template<typename T>
toStdVector(const T * arr,int32_t len)37 static inline std::vector<T> toStdVector(const T* arr, int32_t len) {
38     std::vector<T> result;
39     for (int32_t i = 0; i < len; i++) {
40         result.push_back(arr[i]);
41     }
42     return result;
43 }
44 
45 #if defined(U_REAL_MSVC)
46 #pragma warning(push)
47 // Ignore warning 4251 as these templates are instantiated later in this file,
48 // after the classes used to instantiate them have been defined.
49 #pragma warning(disable: 4251)
50 #endif
51 
52 namespace message2 {
53     class Checker;
54     class MFDataModel;
55     class MessageFormatter;
56     class Parser;
57     class Serializer;
58 
59 
60   namespace data_model {
61         class Binding;
62         class Literal;
63         class Operator;
64 
65         /**
66          * The `Reserved` class represents a `reserved` annotation, as in the `reserved` nonterminal
67          * in the MessageFormat 2 grammar or the `Reserved` interface
68          * defined in
69          * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#expressions
70          *
71          * `Reserved` is immutable, copyable and movable.
72          *
73          * @internal ICU 75 technology preview
74          * @deprecated This API is for technology preview only.
75          */
76         class U_I18N_API Reserved : public UMemory {
77         public:
78             /**
79              * A `Reserved` is a sequence of literals.
80              *
81              * @return The number of literals.
82              *
83              * @internal ICU 75 technology preview
84              * @deprecated This API is for technology preview only.
85              */
86             int32_t numParts() const;
87             /**
88              * Indexes into the sequence.
89              * Precondition: i < numParts()
90              *
91              * @param i Index of the part being accessed.
92              * @return A reference to he i'th literal in the sequence
93              *
94              * @internal ICU 75 technology preview
95              * @deprecated This API is for technology preview only.
96              */
97             const Literal& getPart(int32_t i) const;
98 
99             /**
100              * The mutable `Reserved::Builder` class allows the reserved sequence to be
101              * constructed one part at a time.
102              *
103              * Builder is not copyable or movable.
104              *
105              * @internal ICU 75 technology preview
106              * @deprecated This API is for technology preview only.
107              */
108             class U_I18N_API Builder : public UMemory {
109             private:
110                 UVector* parts; // Not a LocalPointer for the same reason as in `SelectorKeys::Builder`
111 
112             public:
113                 /**
114                  * Adds a single literal to the reserved sequence.
115                  *
116                  * @param part The literal to be added. Passed by move.
117                  * @param status Input/output error code
118                  * @return A reference to the builder.
119                  *
120                  * @internal ICU 75 technology preview
121                  * @deprecated This API is for technology preview only.
122                  */
123                 Builder& add(Literal&& part, UErrorCode& status) noexcept;
124                 /**
125                  * Constructs a new immutable `Reserved` using the list of parts
126                  * set with previous `add()` calls.
127                  *
128                  * The builder object (`this`) can still be used after calling `build()`.
129                  *
130                  * param status Input/output error code
131                  * @return          The new Reserved object
132                  *
133                  * @internal ICU 75 technology preview
134                  * @deprecated This API is for technology preview only.
135                  */
136                 Reserved build(UErrorCode& status) const noexcept;
137                 /**
138                  * Default constructor.
139                  * Returns a builder with an empty Reserved sequence.
140                  *
141                  * param status Input/output error code
142                  *
143                  * @internal ICU 75 technology preview
144                  * @deprecated This API is for technology preview only.
145                  */
146                 Builder(UErrorCode& status);
147                 /**
148                  * Destructor.
149                  *
150                  * @internal ICU 75 technology preview
151                  * @deprecated This API is for technology preview only.
152                  */
153                 virtual ~Builder();
154                 Builder(const Builder&) = delete;
155                 Builder& operator=(const Builder&) = delete;
156                 Builder(Builder&&) = delete;
157                 Builder& operator=(Builder&&) = delete;
158             }; // class Reserved::Builder
159             /**
160              * Non-member swap function.
161              * @param r1 will get r2's contents
162              * @param r2 will get r1's contents
163              *
164              * @internal ICU 75 technology preview
165              * @deprecated This API is for technology preview only.
166              */
swap(Reserved & r1,Reserved & r2)167             friend inline void swap(Reserved& r1, Reserved& r2) noexcept {
168                 using std::swap;
169 
170                 swap(r1.bogus, r2.bogus);
171                 swap(r1.parts, r2.parts);
172                 swap(r1.len, r2.len);
173             }
174             /**
175              * Copy constructor.
176              *
177              * @internal ICU 75 technology preview
178              * @deprecated This API is for technology preview only.
179              */
180             Reserved(const Reserved& other);
181             /**
182              * Assignment operator
183              *
184              * @internal ICU 75 technology preview
185              * @deprecated This API is for technology preview only.
186              */
187             Reserved& operator=(Reserved) noexcept;
188             /**
189              * Default constructor.
190              * Puts the Reserved into a valid but undefined state.
191              *
192              * @internal ICU 75 technology preview
193              * @deprecated This API is for technology preview only.
194              */
Reserved()195             Reserved() { parts = LocalArray<Literal>(); }
196             /**
197              * Destructor.
198              *
199              * @internal ICU 75 technology preview
200              * @deprecated This API is for technology preview only.
201              */
202             virtual ~Reserved();
203         private:
204             friend class Builder;
205             friend class Operator;
206 
207             // True if a copy failed; this has to be distinguished
208             // from a valid `Reserved` with empty parts
209             bool bogus = false;
210 
211             // Possibly-empty list of parts
212             // `literal` reserved as a quoted literal; `reserved-char` / `reserved-escape`
213             // strings represented as unquoted literals
214             /* const */ LocalArray<Literal> parts;
215             int32_t len = 0;
216 
217             Reserved(const UVector& parts, UErrorCode& status) noexcept;
218             // Helper
219             static void initLiterals(Reserved&, const Reserved&);
220         };
221 
222       /**
223          * The `Literal` class corresponds to the `literal` nonterminal in the MessageFormat 2 grammar,
224          * https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf and the
225          * `Literal` interface defined in
226          *   // https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#expressions
227          *
228          * `Literal` is immutable, copyable and movable.
229          *
230          * @internal ICU 75 technology preview
231          * @deprecated This API is for technology preview only.
232          */
233         class U_I18N_API Literal : public UObject {
234         public:
235             /**
236              * Returns the quoted representation of this literal (enclosed in '|' characters)
237              *
238              * @return A string representation of the literal enclosed in quote characters.
239              *
240              * @internal ICU 75 technology preview
241              * @deprecated This API is for technology preview only.
242              */
243             UnicodeString quoted() const;
244             /**
245              * Returns the parsed string contents of this literal.
246              *
247              * @return A string representation of this literal.
248              *
249              * @internal ICU 75 technology preview
250              * @deprecated This API is for technology preview only.
251              */
252             const UnicodeString& unquoted() const;
253             /**
254              * Determines if this literal appeared as a quoted literal in the message.
255              *
256              * @return true if and only if this literal appeared as a quoted literal in the
257              *         message.
258              *
259              * @internal ICU 75 technology preview
260              * @deprecated This API is for technology preview only.
261              */
isQuoted()262             UBool isQuoted() const { return thisIsQuoted; }
263             /**
264              * Literal constructor.
265              *
266              *  @param q True if and only if this literal was parsed with the `quoted` nonterminal
267              *           (appeared enclosed in '|' characters in the message text).
268              *  @param s The string contents of this literal; escape sequences are assumed to have
269              *           been interpreted already.
270              *
271              * @internal ICU 75 technology preview
272              * @deprecated This API is for technology preview only.
273              */
Literal(UBool q,const UnicodeString & s)274             Literal(UBool q, const UnicodeString& s) : thisIsQuoted(q), contents(s) {}
275             /**
276              * Copy constructor.
277              *
278              * @internal ICU 75 technology preview
279              * @deprecated This API is for technology preview only.
280              */
Literal(const Literal & other)281             Literal(const Literal& other) : thisIsQuoted(other.thisIsQuoted), contents(other.contents) {}
282             /**
283              * Non-member swap function.
284              * @param l1 will get l2's contents
285              * @param l2 will get l1's contents
286              *
287              * @internal ICU 75 technology preview
288              * @deprecated This API is for technology preview only.
289              */
swap(Literal & l1,Literal & l2)290             friend inline void swap(Literal& l1, Literal& l2) noexcept {
291                 using std::swap;
292 
293                 swap(l1.thisIsQuoted, l2.thisIsQuoted);
294                 swap(l1.contents, l2.contents);
295             }
296             /**
297              * Assignment operator.
298              *
299              * @internal ICU 75 technology preview
300              * @deprecated This API is for technology preview only.
301              */
302             Literal& operator=(Literal) noexcept;
303             /**
304              * Default constructor.
305              * Puts the Literal into a valid but undefined state.
306              *
307              * @internal ICU 75 technology preview
308              * @deprecated This API is for technology preview only.
309              */
310             Literal() = default;
311             /**
312              * Less than operator. Compares `this.stringContents()` with
313              * `other.stringContents()`. This method is used in representing
314              * the mapping from key lists to patterns in a message with variants,
315              * and is not expected to be useful otherwise.
316              *
317              * @param other The Literal to compare to this one.
318              * @return true if the parsed string corresponding to this `Literal`
319              * is less than the parsed string corresponding to the other `Literal`
320              * (according to `UnicodeString`'s less-than operator).
321              * Returns false otherwise.
322              *
323              * @internal ICU 75 technology preview
324              * @deprecated This API is for technology preview only.
325              */
326             bool operator<(const Literal& other) const;
327             /**
328              * Equality operator. Compares `this.stringContents()` with
329              * `other.stringContents()`. This method is used in representing
330              * the mapping from key lists to patterns in a message with variants,
331              * and is not expected to be useful otherwise.
332              *
333              * @param other The Literal to compare to this one.
334              * @return true if the parsed string corresponding to this `Literal`
335              * equals the parsed string corresponding to the other `Literal`
336              * (according to `UnicodeString`'s equality operator).
337              * Returns false otherwise.
338              *
339              * @internal ICU 75 technology preview
340              * @deprecated This API is for technology preview only.
341              */
342             bool operator==(const Literal& other) const;
343             /**
344              * Destructor.
345              *
346              * @internal ICU 75 technology preview
347              * @deprecated This API is for technology preview only.
348              */
349             virtual ~Literal();
350 
351         private:
352             friend class Reserved::Builder;
353 
354             /* const */ bool thisIsQuoted = false;
355             /* const */ UnicodeString contents;
356         };
357   } // namespace data_model
358 } // namespace message2
359 
360 /// @cond DOXYGEN_IGNORE
361 // Export an explicit template instantiation of the LocalPointer that is used as a
362 // data member of various MFDataModel classes.
363 // (When building DLLs for Windows this is required.)
364 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
365 // for similar examples.)
366 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
367 template class U_I18N_API LocalPointerBase<message2::data_model::Literal>;
368 template class U_I18N_API LocalArray<message2::data_model::Literal>;
369 #endif
370 #if defined(U_REAL_MSVC)
371 #pragma warning(pop)
372 #endif
373 /// @endcond
374 
375 U_NAMESPACE_END
376 
377 /// @cond DOXYGEN_IGNORE
378 // Export an explicit template instantiation of the std::variants and std::optionals
379 // that are used as a data member of various MFDataModel classes.
380 // (When building DLLs for Windows this is required.)
381 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
382 // for similar examples.)
383 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
384 #if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION)
385 struct U_I18N_API std::_Nontrivial_dummy_type;
386 template class U_I18N_API std::_Variant_storage_<false, icu::UnicodeString, icu::message2::data_model::Literal>;
387 #endif
388 template class U_I18N_API std::variant<icu::UnicodeString, icu::message2::data_model::Literal>;
389 template class U_I18N_API std::optional<std::variant<icu::UnicodeString, icu::message2::data_model::Literal>>;
390 template class U_I18N_API std::optional<icu::message2::data_model::Literal>;
391 #endif
392 /// @endcond
393 
394 U_NAMESPACE_BEGIN
395 
396 namespace message2 {
397   namespace data_model {
398 
399         /**
400          * The `Operand` class corresponds to the `operand` nonterminal in the MessageFormat 2 grammar,
401          * https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf .
402          * It represents a `Literal | VariableRef` -- see the `operand?` field of the `FunctionRef`
403          * interface defined at:
404          * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#expressions
405          * with the difference that it can also represent a null operand (the absent operand in an
406          * `annotation` with no operand).
407          *
408          * `Operand` is immutable and is copyable and movable.
409          *
410          * @internal ICU 75 technology preview
411          * @deprecated This API is for technology preview only.
412          */
413         class U_I18N_API Operand : public UObject {
414         public:
415             /**
416              * Determines if this operand represents a variable.
417              *
418              * @return True if and only if the operand is a variable.
419              *
420              * @internal ICU 75 technology preview
421              * @deprecated This API is for technology preview only.
422              */
423             UBool isVariable() const;
424             /**
425              * Determines if this operand represents a literal.
426              *
427              * @return True if and only if the operand is a literal.
428              *
429              * @internal ICU 75 technology preview
430              * @deprecated This API is for technology preview only.
431              */
432             UBool isLiteral() const;
433             /**
434              * Determines if this operand is the null operand.
435              *
436              * @return True if and only if the operand is the null operand.
437              *
438              * @internal ICU 75 technology preview
439              * @deprecated This API is for technology preview only.
440              */
441             virtual UBool isNull() const;
442             /**
443              * Returns a reference to this operand's variable name.
444              * Precondition: isVariable()
445              *
446              * @return A reference to the name of the variable
447              *
448              * @internal ICU 75 technology preview
449              * @deprecated This API is for technology preview only.
450              */
451             const UnicodeString& asVariable() const;
452             /**
453              * Returns a reference to this operand's literal contents.
454              * Precondition: isLiteral()
455              *
456              * @return A reference to the literal
457              *
458              * @internal ICU 75 technology preview
459              * @deprecated This API is for technology preview only.
460              */
461             const Literal& asLiteral() const;
462             /**
463              * Default constructor.
464              * Creates a null Operand.
465              *
466              * @internal ICU 75 technology preview
467              * @deprecated This API is for technology preview only.
468              */
Operand()469             Operand() : contents(std::nullopt) {}
470             /**
471              * Variable operand constructor.
472              *
473              * @param v The variable name; an operand corresponding
474              *        to a reference to `v` is returned.
475              *
476              * @internal ICU 75 technology preview
477              * @deprecated This API is for technology preview only.
478              */
Operand(const UnicodeString & v)479             explicit Operand(const UnicodeString& v) : contents(VariableName(v)) {}
480             /**
481              * Literal operand constructor.
482              *
483              * @param l The literal to use for this operand; an operand
484              *        corresponding to `l` is returned.
485              *
486              * @internal ICU 75 technology preview
487              * @deprecated This API is for technology preview only.
488              */
Operand(const Literal & l)489             explicit Operand(const Literal& l) : contents(l) {}
490             /**
491              * Non-member swap function.
492              * @param o1 will get o2's contents
493              * @param o2 will get o1's contents
494              *
495              * @internal ICU 75 technology preview
496              * @deprecated This API is for technology preview only.
497              */
swap(Operand & o1,Operand & o2)498             friend inline void swap(Operand& o1, Operand& o2) noexcept {
499                 using std::swap;
500                 (void) o1;
501                 (void) o2;
502                 swap(o1.contents, o2.contents);
503             }
504             /**
505              * Assignment operator.
506              *
507              * @internal ICU 75 technology preview
508              * @deprecated This API is for technology preview only.
509              */
510             virtual Operand& operator=(Operand) noexcept;
511             /**
512              * Copy constructor.
513              *
514              * @internal ICU 75 technology preview
515              * @deprecated This API is for technology preview only.
516              */
517             Operand(const Operand&);
518             /**
519              * Destructor.
520              *
521              * @internal ICU 75 technology preview
522              * @deprecated This API is for technology preview only.
523              */
524             virtual ~Operand();
525         private:
526             std::optional<std::variant<VariableName, Literal>> contents;
527         }; // class Operand
528 
529         /**
530          * The `Key` class corresponds to the `key` nonterminal in the MessageFormat 2 grammar,
531          * https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf .
532          * It also corresponds to
533          * the `Literal | CatchallKey` that is the
534          * element type of the `keys` array in the `Variant` interface
535          * defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#messages
536          *
537          * A key is either a literal or the wildcard symbol (represented in messages as '*')
538          *
539          * `Key` is immutable, copyable and movable.
540          *
541          * @internal ICU 75 technology preview
542          * @deprecated This API is for technology preview only.
543          */
544         class U_I18N_API Key : public UObject {
545         public:
546             /**
547              * Determines if this is a wildcard key
548              *
549              * @return True if and only if this is the wildcard key
550              *
551              * @internal ICU 75 technology preview
552              * @deprecated This API is for technology preview only.
553              */
isWildcard()554             UBool isWildcard() const { return !contents.has_value(); }
555             /**
556              * Returns the contents of this key as a literal.
557              * Precondition: !isWildcard()
558              *
559              * @return The literal contents of the key
560              *
561              * @internal ICU 75 technology preview
562              * @deprecated This API is for technology preview only.
563              */
564             const Literal& asLiteral() const;
565             /**
566              * Copy constructor.
567              *
568              * @internal ICU 75 technology preview
569              * @deprecated This API is for technology preview only.
570              */
Key(const Key & other)571             Key(const Key& other) : contents(other.contents) {}
572             /**
573              * Wildcard constructor; constructs a Key representing the
574              * catchall or wildcard key, '*'.
575              *
576              * @internal ICU 75 technology preview
577              * @deprecated This API is for technology preview only.
578              */
Key()579             Key() : contents(std::nullopt) {}
580             /**
581              * Literal key constructor.
582              *
583              * @param lit A Literal to use for this key. The result matches the
584              *        literal `lit`.
585              *
586              * @internal ICU 75 technology preview
587              * @deprecated This API is for technology preview only.
588              */
Key(const Literal & lit)589             explicit Key(const Literal& lit) : contents(lit) {}
590             /**
591              * Non-member swap function.
592              * @param k1 will get k2's contents
593              * @param k2 will get k1's contents
594              *
595              * @internal ICU 75 technology preview
596              * @deprecated This API is for technology preview only.
597              */
swap(Key & k1,Key & k2)598             friend inline void swap(Key& k1, Key& k2) noexcept {
599                 using std::swap;
600 
601                 swap(k1.contents, k2.contents);
602             }
603             /**
604              * Assignment operator
605              *
606              * @internal ICU 75 technology preview
607              * @deprecated This API is for technology preview only.
608              */
609             Key& operator=(Key) noexcept;
610             /**
611              * Less than operator. Compares the literal of `this` with the literal of `other`.
612              * This method is used in representing the mapping from key lists to patterns
613              * in a message with variants, and is not expected to be useful otherwise.
614              *
615              * @param other The Key to compare to this one.
616              * @return true if the two `Key`s are not wildcards and if `this.asLiteral()`
617              * < `other.asLiteral()`.
618              * Returns false otherwise.
619              *
620              * @internal ICU 75 technology preview
621              * @deprecated This API is for technology preview only.
622              */
623             bool operator<(const Key& other) const;
624             /**
625              * Equality operator. Compares the literal of `this` with the literal of `other`.
626              * This method is used in representing the mapping from key lists to patterns
627              * in a message with variants, and is not expected to be useful otherwise.
628              *
629              * @param other The Key to compare to this one.
630              * @return true if either both `Key`s are wildcards, or `this.asLiteral()`
631              * == `other.asLiteral()`.
632              * Returns false otherwise.
633              *
634              * @internal ICU 75 technology preview
635              * @deprecated This API is for technology preview only.
636              */
637             bool operator==(const Key& other) const;
638             /**
639              * Destructor.
640              *
641              * @internal ICU 75 technology preview
642              * @deprecated This API is for technology preview only.
643              */
644             virtual ~Key();
645         private:
646             /* const */ std::optional<Literal> contents;
647         }; // class Key
648   } // namespace data_model
649 } // namespace message2
650 
651 /// @cond DOXYGEN_IGNORE
652 // Export an explicit template instantiation of the LocalPointer that is used as a
653 // data member of various MFDataModel classes.
654 // (When building DLLs for Windows this is required.)
655 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
656 // for similar examples.)
657 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
658 template class U_I18N_API LocalPointerBase<message2::data_model::Key>;
659 template class U_I18N_API LocalArray<message2::data_model::Key>;
660 #endif
661 /// @endcond
662 
663 namespace message2 {
664   namespace data_model {
665         /**
666          * The `SelectorKeys` class represents the key list for a single variant.
667          * It corresponds to the `keys` array in the `Variant` interface
668          * defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#messages
669          *
670          * `SelectorKeys` is immutable, copyable and movable.
671          *
672          * @internal ICU 75 technology preview
673          * @deprecated This API is for technology preview only.
674          */
675         class U_I18N_API SelectorKeys : public UObject {
676         public:
677             /**
678              * Returns the underlying list of keys.
679              *
680              * @return The list of keys for this variant.
681              *         Returns an empty list if allocating this `SelectorKeys`
682              *         object previously failed.
683              *
684              * @internal ICU 75 technology preview
685              * @deprecated This API is for technology preview only.
686              */
getKeys()687             std::vector<Key> getKeys() const {
688                 return toStdVector<Key>(keys.getAlias(), len);
689             }
690             /**
691              * The mutable `SelectorKeys::Builder` class allows the key list to be constructed
692              * one key at a time.
693              *
694              * Builder is not copyable or movable.
695              *
696              * @internal ICU 75 technology preview
697              * @deprecated This API is for technology preview only.
698              */
699             class U_I18N_API Builder : public UMemory {
700             private:
701                 friend class SelectorKeys;
702                 UVector* keys; // This is a raw pointer and not a LocalPointer<UVector> to avoid undefined behavior warnings,
703                                // since UVector is forward-declared
704                                // The vector owns its elements
705             public:
706                 /**
707                  * Adds a single key to the list.
708                  *
709                  * @param key    The key to be added. Passed by move
710                  * @param status Input/output error code
711                  * @return A reference to the builder.
712                  *
713                  * @internal ICU 75 technology preview
714                  * @deprecated This API is for technology preview only.
715                  */
716                 Builder& add(Key&& key, UErrorCode& status) noexcept;
717                 /**
718                  * Constructs a new immutable `SelectorKeys` using the list of keys
719                  * set with previous `add()` calls.
720                  *
721                  * The builder object (`this`) can still be used after calling `build()`.
722                  *
723                  * @param status    Input/output error code
724                  * @return          The new SelectorKeys object
725                  *
726                  * @internal ICU 75 technology preview
727                  * @deprecated This API is for technology preview only.
728                  */
729                 SelectorKeys build(UErrorCode& status) const;
730                 /**
731                  * Default constructor.
732                  * Returns a Builder with an empty list of keys.
733                  *
734                  * @param status Input/output error code
735                  *
736                  * @internal ICU 75 technology preview
737                  * @deprecated This API is for technology preview only.
738                  */
739                 Builder(UErrorCode& status);
740                 /**
741                  * Destructor.
742                  *
743                  * @internal ICU 75 technology preview
744                  * @deprecated This API is for technology preview only.
745                  */
746                 virtual ~Builder();
747                 Builder(const Builder&) = delete;
748                 Builder& operator=(const Builder&) = delete;
749                 Builder(Builder&&) = delete;
750                 Builder& operator=(Builder&&) = delete;
751             }; // class SelectorKeys::Builder
752             /**
753              * Less than operator. Compares the two key lists lexicographically.
754              * This method makes it possible for a `SelectorKeys` to be used as a map
755              * key, which allows variants to be represented as a map. It is not expected
756              * to be useful otherwise.
757              *
758              * @param other The SelectorKeys to compare to this one.
759              * @return true if `this` is less than `other`, comparing the two key lists
760              * lexicographically.
761              * Returns false otherwise.
762              *
763              * @internal ICU 75 technology preview
764              * @deprecated This API is for technology preview only.
765              */
766             bool operator<(const SelectorKeys& other) const;
767             /**
768              * Default constructor.
769              * Puts the SelectorKeys into a valid but undefined state.
770              *
771              * @internal ICU 75 technology preview
772              * @deprecated This API is for technology preview only.
773              */
SelectorKeys()774             SelectorKeys() : len(0) {}
775             /**
776              * Non-member swap function.
777              * @param s1 will get s2's contents
778              * @param s2 will get s1's contents
779              *
780              * @internal ICU 75 technology preview
781              * @deprecated This API is for technology preview only.
782              */
swap(SelectorKeys & s1,SelectorKeys & s2)783             friend inline void swap(SelectorKeys& s1, SelectorKeys& s2) noexcept {
784                 using std::swap;
785 
786                 swap(s1.len, s2.len);
787                 swap(s1.keys, s2.keys);
788             }
789             /**
790              * Copy constructor.
791              *
792              * @internal ICU 75 technology preview
793              * @deprecated This API is for technology preview only.
794              */
795             SelectorKeys(const SelectorKeys& other);
796             /**
797              * Assignment operator.
798              *
799              * @internal ICU 75 technology preview
800              * @deprecated This API is for technology preview only.
801              */
802             SelectorKeys& operator=(SelectorKeys other) noexcept;
803             /**
804              * Destructor.
805              *
806              * @internal ICU 75 technology preview
807              * @deprecated This API is for technology preview only.
808              */
809             virtual ~SelectorKeys();
810         private:
811             friend class Builder;
812             friend class message2::Checker;
813             friend class message2::MessageFormatter;
814             friend class message2::Serializer;
815 
816             /* const */ LocalArray<Key> keys;
817             /* const */ int32_t len;
818 
819             const Key* getKeysInternal() const;
820             SelectorKeys(const UVector& ks, UErrorCode& status);
821         }; // class SelectorKeys
822 
823 
824     } // namespace data_model
825 
826 
827     namespace data_model {
828         class Operator;
829 
830         /**
831          *  An `Option` pairs an option name with an Operand.
832          *
833          * `Option` is immutable, copyable and movable.
834          *
835          * @internal ICU 75 technology preview
836          * @deprecated This API is for technology preview only.
837          */
838         class U_I18N_API Option : public UObject {
839         public:
840             /**
841              * Accesses the right-hand side of the option.
842              *
843              * @return A reference to the operand.
844              *
845              * @internal ICU 75 technology preview
846              * @deprecated This API is for technology preview only.
847              */
getValue()848             const Operand& getValue() const { return rand; }
849             /**
850              * Accesses the left-hand side of the option.
851              *
852              * @return A reference to the option name.
853              *
854              * @internal ICU 75 technology preview
855              * @deprecated This API is for technology preview only.
856              */
getName()857             const UnicodeString& getName() const { return name; }
858             /**
859              * Constructor. Returns an `Option` representing the
860              * named option "name=rand".
861              *
862              * @param n The name of the option.
863              * @param r The value of the option.
864              *
865              * @internal ICU 75 technology preview
866              * @deprecated This API is for technology preview only.
867              */
Option(const UnicodeString & n,Operand && r)868             Option(const UnicodeString& n, Operand&& r) : name(n), rand(std::move(r)) {}
869             /**
870              * Default constructor.
871              * Returns an Option in a valid but undefined state.
872              *
873              * @internal ICU 75 technology preview
874              * @deprecated This API is for technology preview only.
875              */
Option()876             Option() {}
877             /**
878              * Non-member swap function.
879              * @param o1 will get o2's contents
880              * @param o2 will get o1's contents
881              *
882              * @internal ICU 75 technology preview
883              * @deprecated This API is for technology preview only.
884              */
swap(Option & o1,Option & o2)885             friend inline void swap(Option& o1, Option& o2) noexcept {
886                 using std::swap;
887 
888                 swap(o1.name, o2.name);
889                 swap(o1.rand, o2.rand);
890             }
891             /**
892              * Copy constructor.
893              *
894              * @internal ICU 75 technology preview
895              * @deprecated This API is for technology preview only.
896              */
897             Option(const Option& other);
898             /**
899              * Assignment operator
900              *
901              * @internal ICU 75 technology preview
902              * @deprecated This API is for technology preview only.
903              */
904             Option& operator=(Option other) noexcept;
905             /**
906              * Destructor.
907              *
908              * @internal ICU 75 technology preview
909              * @deprecated This API is for technology preview only.
910              */
911             virtual ~Option();
912         private:
913             /* const */ UnicodeString name;
914             /* const */ Operand rand;
915         }; // class Option
916     } // namespace data_model
917 } // namespace message2
918 
919   /// @cond DOXYGEN_IGNORE
920 // Export an explicit template instantiation of the LocalPointer that is used as a
921 // data member of various MFDataModel classes.
922 // (When building DLLs for Windows this is required.)
923 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
924 // for similar examples.)
925 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
926 template class U_I18N_API LocalPointerBase<message2::data_model::Option>;
927 template class U_I18N_API LocalArray<message2::data_model::Option>;
928 #endif
929 /// @endcond
930 
931 namespace message2 {
932   namespace data_model {
933         // Internal only
934         #ifndef U_IN_DOXYGEN
935         // Options
936         // This is a wrapper class around a vector of options that provides lookup operations
937         class U_I18N_API OptionMap : public UObject {
938         public:
939             int32_t size() const;
940             // Needs to take an error code b/c an earlier copy might have failed
941             const Option& getOption(int32_t, UErrorCode&) const;
swap(OptionMap & m1,OptionMap & m2)942             friend inline void swap(OptionMap& m1, OptionMap& m2) noexcept {
943                 using std::swap;
944 
945                 swap(m1.bogus, m2.bogus);
946                 swap(m1.options, m2.options);
947                 swap(m1.len, m2.len);
948             }
OptionMap()949             OptionMap() : len(0) {}
950             OptionMap(const OptionMap&);
951             OptionMap& operator=(OptionMap);
getOptions()952             std::vector<Option> getOptions() const {
953                 return toStdVector<Option>(options.getAlias(), len);
954             }
955             OptionMap(const UVector&, UErrorCode&);
956             OptionMap(Option*, int32_t);
957             virtual ~OptionMap();
958 
959             class U_I18N_API Builder : public UObject {
960                 private:
961                     UVector* options;
962                     bool checkDuplicates = true;
963                 public:
964                     Builder& add(Option&& opt, UErrorCode&);
965                     Builder(UErrorCode&);
966                     static Builder attributes(UErrorCode&);
967                     // As this class is private, build() is destructive
968                     OptionMap build(UErrorCode&);
swap(Builder & m1,Builder & m2)969 		    friend inline void swap(Builder& m1, Builder& m2) noexcept {
970 		      using std::swap;
971 
972 		      swap(m1.options, m2.options);
973 		      swap(m1.checkDuplicates, m2.checkDuplicates);
974 		    }
975 		    Builder(Builder&&);
976 		    Builder(const Builder&) = delete;
977 		    Builder& operator=(Builder) noexcept;
978 		    virtual ~Builder();
979             }; // class OptionMap::Builder
980         private:
981             friend class message2::Serializer;
982 
983             bool bogus = false;
984             LocalArray<Option> options;
985             int32_t len;
986         }; // class OptionMap
987         #endif
988 
989       // Internal use only
990       #ifndef U_IN_DOXYGEN
991       class U_I18N_API Callable : public UObject {
992       public:
swap(Callable & c1,Callable & c2)993           friend inline void swap(Callable& c1, Callable& c2) noexcept {
994               using std::swap;
995 
996               swap(c1.name, c2.name);
997               swap(c1.options, c2.options);
998           }
getName()999           const FunctionName& getName() const { return name; }
getOptions()1000           const OptionMap& getOptions() const { return options; }
Callable(const FunctionName & f,const OptionMap & opts)1001           Callable(const FunctionName& f, const OptionMap& opts) : name(f), options(opts) {}
1002           Callable& operator=(Callable) noexcept;
1003           Callable(const Callable&);
1004           Callable() = default;
1005           virtual ~Callable();
1006       private:
1007           /* const */ FunctionName name;
1008           /* const */ OptionMap options;
1009       };
1010       #endif
1011   } // namespace data_model
1012 } // namespace message2
1013 
1014 U_NAMESPACE_END
1015 
1016 /// @cond DOXYGEN_IGNORE
1017 // Export an explicit template instantiation of the std::variant that is used as a
1018 // data member of various MFDataModel classes.
1019 // (When building DLLs for Windows this is required.)
1020 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
1021 // for similar examples.)
1022 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1023 #if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION)
1024 template class U_I18N_API std::_Variant_storage_<false, icu::message2::data_model::Reserved,icu::message2::data_model::Callable>;
1025 #endif
1026 template class U_I18N_API std::variant<icu::message2::data_model::Reserved,icu::message2::data_model::Callable>;
1027 #endif
1028 /// @endcond
1029 
1030 U_NAMESPACE_BEGIN
1031 
1032 namespace message2 {
1033   namespace data_model {
1034       /**
1035          * The `Operator` class corresponds to the `FunctionRef | Reserved` type in the
1036          * `Expression` interface defined in
1037          * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#patterns
1038          *
1039          * It represents the annotation that an expression can have: either a function name paired
1040          * with a map from option names to operands (possibly empty),
1041          * or a reserved sequence, which has no meaning and results in an error if the formatter
1042          * is invoked.
1043          *
1044          * `Operator` is immutable, copyable and movable.
1045          *
1046          * @internal ICU 75 technology preview
1047          * @deprecated This API is for technology preview only.
1048          */
1049         class U_I18N_API Operator : public UObject {
1050         public:
1051             /**
1052              * Determines if this operator is a reserved annotation.
1053              *
1054              * @return true if and only if this operator represents a reserved sequence.
1055              *
1056              * @internal ICU 75 technology preview
1057              * @deprecated This API is for technology preview only.
1058              */
isReserved()1059             UBool isReserved() const { return std::holds_alternative<Reserved>(contents); }
1060             /**
1061              * Accesses the function name.
1062              * Precondition: !isReserved()
1063              *
1064              * @return The function name of this operator.
1065              *
1066              * @internal ICU 75 technology preview
1067              * @deprecated This API is for technology preview only.
1068              */
1069             const FunctionName& getFunctionName() const;
1070             /**
1071              * Accesses the underlying reserved sequence.
1072              * Precondition: isReserved()
1073              *
1074              * @return The reserved sequence represented by this operator.
1075              *
1076              * @internal ICU 75 technology preview
1077              * @deprecated This API is for technology preview only.
1078              */
1079             const Reserved& asReserved() const;
1080             /**
1081              * Accesses function options.
1082              * Precondition: !isReserved()
1083              *
1084              * @return A vector of function options for this operator.
1085              *
1086              * @internal ICU 75 technology preview
1087              * @deprecated This API is for technology preview only.
1088              */
getOptions()1089             std::vector<Option> getOptions() const {
1090                 const Callable* f = std::get_if<Callable>(&contents);
1091                 // This case should never happen, as the precondition is !isReserved()
1092                 if (f == nullptr) { return {}; }
1093                 const OptionMap& opts = f->getOptions();
1094                 return opts.getOptions();
1095             }
1096             /**
1097              * The mutable `Operator::Builder` class allows the operator to be constructed
1098              * incrementally.
1099              *
1100              * Builder is not copyable or movable.
1101              *
1102              * @internal ICU 75 technology preview
1103              * @deprecated This API is for technology preview only.
1104              */
1105             class U_I18N_API Builder : public UMemory {
1106             private:
1107                 friend class Operator;
1108                 bool isReservedSequence = false;
1109                 bool hasFunctionName = false;
1110                 bool hasOptions = false;
1111                 Reserved asReserved;
1112                 FunctionName functionName;
1113                 OptionMap::Builder options;
1114             public:
1115                 /**
1116                  * Sets this operator to be a reserved sequence.
1117                  * If a function name and/or options were previously set,
1118                  * clears them.
1119                  *
1120                  * @param reserved The reserved sequence to set as the contents of this Operator.
1121                  *                 (Passed by move.)
1122                  * @return A reference to the builder.
1123                  *
1124                  * @internal ICU 75 technology preview
1125                  * @deprecated This API is for technology preview only.
1126                  */
1127                 Builder& setReserved(Reserved&& reserved);
1128                 /**
1129                  * Sets this operator to be a function annotation and sets its name
1130                  * to `func`.
1131                  * If a reserved sequence was previously set, clears it.
1132                  *
1133                  * @param func The function name.
1134                  * @return A reference to the builder.
1135                  *
1136                  * @internal ICU 75 technology preview
1137                  * @deprecated This API is for technology preview only.
1138                  */
1139                 Builder& setFunctionName(FunctionName&& func);
1140                 /**
1141                  * Sets this operator to be a function annotation and adds a
1142                  * single option.
1143                  * If a reserved sequence was previously set, clears it.
1144                  *
1145                  * @param key The name of the option.
1146                  * @param value The value (right-hand side) of the option.
1147                  * @param status Input/output error code.
1148                  * @return A reference to the builder.
1149                  *
1150                  * @internal ICU 75 technology preview
1151                  * @deprecated This API is for technology preview only.
1152                  */
1153                 Builder& addOption(const UnicodeString &key, Operand&& value, UErrorCode& status) noexcept;
1154                 /**
1155                  * Constructs a new immutable `Operator` using the `reserved` annotation
1156                  * or the function name and options that were previously set.
1157                  * If neither `setReserved()` nor `setFunctionName()` was previously
1158                  * called, then `status` is set to U_INVALID_STATE_ERROR.
1159                  *
1160                  * The builder object (`this`) can still be used after calling `build()`.
1161                  *
1162                  * The `build()` method is non-const for internal implementation reasons,
1163                  * but is observably const.
1164                  *
1165                  * @param status    Input/output error code.
1166                  * @return          The new Operator
1167                  *
1168                  * @internal ICU 75 technology preview
1169                  * @deprecated This API is for technology preview only.
1170                  */
1171                 Operator build(UErrorCode& status);
1172                 /**
1173                  * Default constructor.
1174                  * Returns a Builder with no function name or reserved sequence set.
1175                  *
1176                  * @param status    Input/output error code.
1177                  *
1178                  * @internal ICU 75 technology preview
1179                  * @deprecated This API is for technology preview only.
1180                  */
1181                 Builder(UErrorCode& status);
1182                 /**
1183                  * Destructor.
1184                  *
1185                  * @internal ICU 75 technology preview
1186                  * @deprecated This API is for technology preview only.
1187                  */
1188                 virtual ~Builder();
1189                 Builder(const Builder&) = delete;
1190                 Builder& operator=(const Builder&) = delete;
1191                 Builder(Builder&&) = delete;
1192                 Builder& operator=(Builder&&) = delete;
1193             }; // class Operator::Builder
1194             /**
1195              * Copy constructor.
1196              *
1197              * @internal ICU 75 technology preview
1198              * @deprecated This API is for technology preview only.
1199              */
1200             Operator(const Operator& other) noexcept;
1201             /**
1202              * Non-member swap function.
1203              * @param o1 will get o2's contents
1204              * @param o2 will get o1's contents
1205              *
1206              * @internal ICU 75 technology preview
1207              * @deprecated This API is for technology preview only.
1208              */
swap(Operator & o1,Operator & o2)1209             friend inline void swap(Operator& o1, Operator& o2) noexcept {
1210                 using std::swap;
1211 
1212                 swap(o1.contents, o2.contents);
1213             }
1214             /**
1215              * Assignment operator.
1216              *
1217              * @internal ICU 75 technology preview
1218              * @deprecated This API is for technology preview only.
1219              */
1220             Operator& operator=(Operator) noexcept;
1221             /**
1222              * Default constructor.
1223              * Puts the Operator into a valid but undefined state.
1224              *
1225              * @internal ICU 75 technology preview
1226              * @deprecated This API is for technology preview only.
1227              */
Operator()1228             Operator() : contents(Reserved()) {}
1229             /**
1230              * Destructor.
1231              *
1232              * @internal ICU 75 technology preview
1233              * @deprecated This API is for technology preview only.
1234              */
1235             virtual ~Operator();
1236         private:
1237             friend class Binding;
1238             friend class Builder;
1239             friend class message2::Checker;
1240             friend class message2::MessageFormatter;
1241             friend class message2::Serializer;
1242 
1243             // Function call constructor
1244             Operator(const FunctionName& f, const UVector& options, UErrorCode&);
1245             // Reserved sequence constructor
Operator(const Reserved & r)1246             Operator(const Reserved& r) : contents(r) {}
1247 
1248             const OptionMap& getOptionsInternal() const;
1249             Operator(const FunctionName&, const OptionMap&);
1250             /* const */ std::variant<Reserved, Callable> contents;
1251         }; // class Operator
1252   } // namespace data_model
1253 } // namespace message2
1254 
1255 U_NAMESPACE_END
1256 
1257 /// @cond DOXYGEN_IGNORE
1258 // Export an explicit template instantiation of the std::optional that is used as a
1259 // data member of various MFDataModel classes.
1260 // (When building DLLs for Windows this is required.)
1261 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
1262 // for similar examples.)
1263 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1264 template class U_I18N_API std::optional<icu::message2::data_model::Operator>;
1265 template class U_I18N_API std::optional<icu::message2::data_model::Reserved>;
1266 #endif
1267 /// @endcond
1268 
1269 U_NAMESPACE_BEGIN
1270 
1271 namespace message2 {
1272   namespace data_model {
1273       // Internal only
1274       typedef enum UMarkupType {
1275           UMARKUP_OPEN = 0,
1276           UMARKUP_CLOSE,
1277           UMARKUP_STANDALONE,
1278           UMARKUP_COUNT
1279       } UMarkupType;
1280 
1281       /**
1282          * The `Markup` class corresponds to the `markup` nonterminal in the MessageFormat 2
1283          * grammar and the `markup` interface defined in
1284          * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model/message.json
1285          *
1286          * `Markup` is immutable, copyable and movable.
1287          *
1288          * @internal ICU 75 technology preview
1289          * @deprecated This API is for technology preview only.
1290          */
1291         class U_I18N_API Markup : public UObject {
1292         public:
1293             /**
1294              * Checks if this markup is an opening tag.
1295              *
1296              * @return True if and only if this represents an opening tag.
1297              *
1298              * @internal ICU 75 technology preview
1299              * @deprecated This API is for technology preview only.
1300              */
isOpen()1301             UBool isOpen() const { return (type == UMARKUP_OPEN); }
1302             /**
1303              * Checks if this markup is an closing tag.
1304              *
1305              * @return True if and only if this represents an closing tag.
1306              *
1307              * @internal ICU 75 technology preview
1308              * @deprecated This API is for technology preview only.
1309              */
isClose()1310             UBool isClose() const { return (type == UMARKUP_CLOSE); }
1311             /**
1312              * Checks if this markup is an standalone tag.
1313              *
1314              * @return True if and only if this represents a standalone tag.
1315              *
1316              * @internal ICU 75 technology preview
1317              * @deprecated This API is for technology preview only.
1318              */
isStandalone()1319             UBool isStandalone() const { return (type == UMARKUP_STANDALONE); }
1320             /**
1321              * Gets the name of this markup
1322              *
1323              * @return A reference to the string identifying the markup
1324              *
1325              * @internal ICU 75 technology preview
1326              * @deprecated This API is for technology preview only.
1327              */
getName()1328             const UnicodeString& getName() const { return name; }
1329             /**
1330              * Gets the options of this markup
1331              *
1332              * @return A reference to the string identifying the markup
1333              *
1334              * @internal ICU 75 technology preview
1335              * @deprecated This API is for technology preview only.
1336              */
getOptions()1337             std::vector<Option> getOptions() const { return options.getOptions(); }
1338             /**
1339              * Gets the attributes of this markup
1340              *
1341              * @return A vector of attributes
1342              *
1343              * @internal ICU 75 technology preview
1344              * @deprecated This API is for technology preview only.
1345              */
getAttributes()1346             std::vector<Option> getAttributes() const { return attributes.getOptions(); }
1347             /**
1348              * Default constructor.
1349              * Puts the Markup into a valid but undefined state.
1350              *
1351              * @internal ICU 75 technology preview
1352              * @deprecated This API is for technology preview only.
1353              */
Markup()1354             Markup() {}
1355             /**
1356              * Destructor.
1357              *
1358              * @internal ICU 75 technology preview
1359              * @deprecated This API is for technology preview only.
1360              */
1361             virtual ~Markup();
1362             /**
1363              * The mutable `Markup::Builder` class allows the markup to be constructed
1364              * incrementally.
1365              *
1366              * Builder is not copyable or movable.
1367              *
1368              * @internal ICU 75 technology preview
1369              * @deprecated This API is for technology preview only.
1370              */
1371             class U_I18N_API Builder : public UMemory {
1372             private:
1373                 friend class Markup;
1374 
1375                 UnicodeString name;
1376                 OptionMap::Builder options;
1377                 OptionMap::Builder attributes;
1378                 UMarkupType type = UMARKUP_COUNT;
1379             public:
1380                 /**
1381                  * Sets the name of this markup.
1382                  *
1383                  * @param n A string representing the name.
1384                  * @return A reference to the builder.
1385                  *
1386                  * @internal ICU 75 technology preview
1387                  * @deprecated This API is for technology preview only.
1388                  */
setName(const UnicodeString & n)1389                 Builder& setName(const UnicodeString& n) { name = n; return *this; }
1390                 /**
1391                  * Sets this to be an opening markup.
1392                  *
1393                  * @return A reference to the builder.
1394                  *
1395                  * @internal ICU 75 technology preview
1396                  * @deprecated This API is for technology preview only.
1397                  */
setOpen()1398                 Builder& setOpen() { type = UMARKUP_OPEN; return *this; }
1399                 /**
1400                  * Sets this to be an closing markup.
1401                  *
1402                  * @return A reference to the builder.
1403                  *
1404                  * @internal ICU 75 technology preview
1405                  * @deprecated This API is for technology preview only.
1406                  */
setClose()1407                 Builder& setClose() { type = UMARKUP_CLOSE; return *this; }
1408                 /**
1409                  * Sets this to be a standalone markup.
1410                  *
1411                  * @return A reference to the builder.
1412                  *
1413                  * @internal ICU 75 technology preview
1414                  * @deprecated This API is for technology preview only.
1415                  */
setStandalone()1416                 Builder& setStandalone() { type = UMARKUP_STANDALONE; return *this; }
1417                 /**
1418                  * Adds a single option.
1419                  *
1420                  * @param key The name of the option.
1421                  * @param value The value (right-hand side) of the option.
1422                  * @param status Input/output error code.
1423                  * @return A reference to the builder.
1424                  *
1425                  * @internal ICU 75 technology preview
1426                  * @deprecated This API is for technology preview only.
1427                  */
1428                 Builder& addOption(const UnicodeString &key, Operand&& value, UErrorCode& status);
1429                 /**
1430                  * Adds a single attribute.
1431                  *
1432                  * @param key The name of the attribute.
1433                  * @param value The value (right-hand side) of the attribute.
1434                  * @param status Input/output error code.
1435                  * @return A reference to the builder.
1436                  *
1437                  * @internal ICU 75 technology preview
1438                  * @deprecated This API is for technology preview only.
1439                  */
1440                 Builder& addAttribute(const UnicodeString &key, Operand&& value, UErrorCode& status);
1441                 /**
1442                  * Constructs a new immutable `Markup` using the name and type
1443                  * and (optionally) options and attributes that were previously set.
1444                  * If `setName()` and at least one of `setOpen()`, `setClose()`, and `setStandalone()`
1445                  * were not previously called,
1446                  * then `status` is set to U_INVALID_STATE_ERROR.
1447                  *
1448                  * The builder object (`this`) can still be used after calling `build()`.
1449                  * The `build()` method is non-const for internal implementation reasons,
1450                  * but is observably const.
1451                  *
1452                  * @param status    Input/output error code.
1453                  * @return          The new Markup.
1454                  *
1455                  * @internal ICU 75 technology preview
1456                  * @deprecated This API is for technology preview only.
1457                  */
1458                 Markup build(UErrorCode& status);
1459                 /**
1460                  * Default constructor.
1461                  * Returns a Builder with no name, type, options, or attributes set.
1462                  *
1463                  * @param status    Input/output error code.
1464                  *
1465                  * @internal ICU 75 technology preview
1466                  * @deprecated This API is for technology preview only.
1467                  */
1468                 Builder(UErrorCode& status);
1469                 /**
1470                  * Destructor.
1471                  *
1472                  * @internal ICU 75 technology preview
1473                  * @deprecated This API is for technology preview only.
1474                  */
1475                 virtual ~Builder();
1476                 Builder(const Builder&) = delete;
1477                 Builder& operator=(const Builder&) = delete;
1478                 Builder(Builder&&) = delete;
1479                 Builder& operator=(Builder&&) = delete;
1480             }; // class Markup::Builder
1481 
1482         private:
1483             friend class Builder;
1484             friend class message2::Serializer;
1485 
1486             UMarkupType type;
1487             UnicodeString name;
1488             OptionMap options;
1489             OptionMap attributes;
getOptionsInternal()1490             const OptionMap& getOptionsInternal() const { return options; }
getAttributesInternal()1491             const OptionMap& getAttributesInternal() const { return attributes; }
1492             Markup(UMarkupType, UnicodeString, OptionMap&&, OptionMap&&);
1493         }; // class Markup
1494 
1495         /**
1496          * The `Expression` class corresponds to the `expression` nonterminal in the MessageFormat 2
1497          * grammar and the `Expression` interface defined in
1498          * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#patterns
1499          *
1500          * It represents either an operand with no annotation; an annotation with no operand;
1501          * or an operand annotated with an annotation.
1502          *
1503          * `Expression` is immutable, copyable and movable.
1504          *
1505          * @internal ICU 75 technology preview
1506          * @deprecated This API is for technology preview only.
1507          */
1508         class U_I18N_API Expression : public UObject {
1509         public:
1510             /**
1511              * Checks if this expression is an annotation
1512              * with no operand.
1513              *
1514              * @return True if and only if the expression has
1515              *         an annotation and has no operand.
1516              *
1517              * @internal ICU 75 technology preview
1518              * @deprecated This API is for technology preview only.
1519              */
1520             UBool isStandaloneAnnotation() const;
1521             /**
1522              * Checks if this expression has a function
1523              * annotation (with or without an operand). A reserved
1524              * sequence is not a function annotation.
1525              *
1526              * @return True if and only if the expression has an annotation
1527              *         that is a function.
1528              *
1529              * @internal ICU 75 technology preview
1530              * @deprecated This API is for technology preview only.
1531              */
1532             UBool isFunctionCall() const;
1533             /**
1534              * Returns true if and only if this expression is
1535              * annotated with a reserved sequence.
1536              *
1537              * @return True if and only if the expression has an
1538              *         annotation that is a reserved sequence,
1539              *
1540              * @internal ICU 75 technology preview
1541              * @deprecated This API is for technology preview only.
1542              */
1543             UBool isReserved() const;
1544             /**
1545              * Accesses the function or reserved sequence
1546              * annotating this expression.
1547              * If !(isFunctionCall() || isReserved()), sets
1548              * `status` to U_INVALID_STATE_ERROR.
1549              *
1550              * @param status Input/output error code.
1551              * @return A non-owned pointer to the operator of this expression,
1552              *         which does not outlive the expression.
1553              *
1554              * @internal ICU 75 technology preview
1555              * @deprecated This API is for technology preview only.
1556              */
1557             const Operator* getOperator(UErrorCode& status) const;
1558             /**
1559              * Accesses the operand of this expression.
1560              *
1561              * @return A reference to the operand of this expression,
1562              *         which may be the null operand.
1563              *
1564              * @internal ICU 75 technology preview
1565              * @deprecated This API is for technology preview only.
1566              */
1567             const Operand& getOperand() const;
1568             /**
1569              * Gets the attributes of this expression
1570              *
1571              * @return A vector of attributes
1572              *
1573              * @internal ICU 75 technology preview
1574              * @deprecated This API is for technology preview only.
1575              */
getAttributes()1576             std::vector<Option> getAttributes() const { return attributes.getOptions(); }
1577             /**
1578              * The mutable `Expression::Builder` class allows the operator to be constructed
1579              * incrementally.
1580              *
1581              * Builder is not copyable or movable.
1582              *
1583              * @internal ICU 75 technology preview
1584              * @deprecated This API is for technology preview only.
1585              */
1586             class U_I18N_API Builder : public UMemory {
1587             private:
1588                 friend class Expression;
1589 
1590                 bool hasOperand = false;
1591                 bool hasOperator = false;
1592                 Operand rand;
1593                 Operator rator;
1594                 OptionMap::Builder attributes;
1595             public:
1596                 /**
1597                  * Sets the operand of this expression.
1598                  *
1599                  * @param rAnd The operand to set. Passed by move.
1600                  * @return A reference to the builder.
1601                  *
1602                  * @internal ICU 75 technology preview
1603                  * @deprecated This API is for technology preview only.
1604                  */
1605                 Builder& setOperand(Operand&& rAnd);
1606                 /**
1607                  * Sets the operator of this expression.
1608                  *
1609                  * @param rAtor The operator to set. Passed by move.
1610                  * @return A reference to the builder.
1611                  *
1612                  * @internal ICU 75 technology preview
1613                  * @deprecated This API is for technology preview only.
1614                  */
1615                 Builder& setOperator(Operator&& rAtor);
1616                 /**
1617                  * Adds a single attribute.
1618                  *
1619                  * @param key The name of the attribute.
1620                  * @param value The value (right-hand side) of the attribute.
1621                  * @param status Input/output error code.
1622                  * @return A reference to the builder.
1623                  *
1624                  * @internal ICU 75 technology preview
1625                  * @deprecated This API is for technology preview only.
1626                  */
1627                 Builder& addAttribute(const UnicodeString &key, Operand&& value, UErrorCode& status);
1628                 /**
1629                  * Constructs a new immutable `Expression` using the operand and operator that
1630                  * were previously set. If neither `setOperand()` nor `setOperator()` was
1631                  * previously called, or if `setOperand()` was called with the null operand
1632                  * and `setOperator()` was never called, then `status` is set to
1633                  * U_INVALID_STATE_ERROR.
1634                  *
1635                  * The builder object (`this`) can still be used after calling `build()`.
1636                  * The `build()` method is non-const for internal implementation reasons,
1637                  * but is observably const.
1638 
1639                  * @param status    Input/output error code.
1640                  * @return          The new Expression.
1641                  *
1642                  * @internal ICU 75 technology preview
1643                  * @deprecated This API is for technology preview only.
1644                  */
1645                 Expression build(UErrorCode& status);
1646                 /**
1647                  * Default constructor.
1648                  * Returns a Builder with no operator or operand set.
1649                  *
1650                  * @param status    Input/output error code.
1651                  *
1652                  * @internal ICU 75 technology preview
1653                  * @deprecated This API is for technology preview only.
1654                  */
1655                 Builder(UErrorCode& status);
1656                 /**
1657                  * Destructor.
1658                  *
1659                  * @internal ICU 75 technology preview
1660                  * @deprecated This API is for technology preview only.
1661                  */
1662                 virtual ~Builder();
1663                 Builder(const Builder&) = delete;
1664                 Builder& operator=(const Builder&) = delete;
1665                 Builder(Builder&&) = delete;
1666                 Builder& operator=(Builder&&) = delete;
1667             }; // class Expression::Builder
1668             /**
1669              * Non-member swap function.
1670              * @param e1 will get e2's contents
1671              * @param e2 will get e1's contents
1672              *
1673              * @internal ICU 75 technology preview
1674              * @deprecated This API is for technology preview only.
1675              */
swap(Expression & e1,Expression & e2)1676             friend inline void swap(Expression& e1, Expression& e2) noexcept {
1677                 using std::swap;
1678 
1679                 swap(e1.rator, e2.rator);
1680                 swap(e1.rand, e2.rand);
1681                 swap(e1.attributes, e2.attributes);
1682             }
1683             /**
1684              * Copy constructor.
1685              *
1686              * @internal ICU 75 technology preview
1687              * @deprecated This API is for technology preview only.
1688              */
1689             Expression(const Expression& other);
1690             /**
1691              * Assignment operator.
1692              *
1693              * @internal ICU 75 technology preview
1694              * @deprecated This API is for technology preview only.
1695              */
1696             Expression& operator=(Expression) noexcept;
1697             /**
1698              * Default constructor.
1699              * Puts the Expression into a valid but undefined state.
1700              *
1701              * @internal ICU 75 technology preview
1702              * @deprecated This API is for technology preview only.
1703              */
1704             Expression();
1705             /**
1706              * Destructor.
1707              *
1708              * @internal ICU 75 technology preview
1709              * @deprecated This API is for technology preview only.
1710              */
1711             virtual ~Expression();
1712         private:
1713             friend class message2::Serializer;
1714 
1715             /*
1716               Internally, an expression is represented as the application of an optional operator to an operand.
1717               The operand is always present; for function calls with no operand, it's represented
1718               as an operand for which `isNull()` is true.
1719 
1720               Operator               | Operand
1721               --------------------------------
1722               { |42| :fun opt=value } =>  (FunctionName=fun,     | Literal(quoted=true, contents="42")
1723               options={opt: value})
1724               { abcd }                =>  null                   | Literal(quoted=false, contents="abcd")
1725               { : fun opt=value }     =>  (FunctionName=fun,
1726               options={opt: value})  | NullOperand()
1727             */
1728 
Expression(const Operator & rAtor,const Operand & rAnd,const OptionMap & attrs)1729             Expression(const Operator &rAtor, const Operand &rAnd, const OptionMap& attrs) : rator(rAtor), rand(rAnd), attributes(attrs) {}
Expression(const Operand & rAnd,const OptionMap & attrs)1730             Expression(const Operand &rAnd, const OptionMap& attrs) : rator(std::nullopt), rand(Operand(rAnd)), attributes(attrs) {}
Expression(const Operator & rAtor,const OptionMap & attrs)1731             Expression(const Operator &rAtor, const OptionMap& attrs) : rator(rAtor), rand(), attributes(attrs) {}
1732             /* const */ std::optional<Operator> rator;
1733             /* const */ Operand rand;
1734             /* const */ OptionMap attributes;
getAttributesInternal()1735             const OptionMap& getAttributesInternal() const { return attributes; }
1736         }; // class Expression
1737   } // namespace data_model
1738 } // namespace message2
1739 
1740 /// @cond DOXYGEN_IGNORE
1741 // Export an explicit template instantiation of the LocalPointer that is used as a
1742 // data member of various MFDataModel classes.
1743 // (When building DLLs for Windows this is required.)
1744 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
1745 // for similar examples.)
1746 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1747 template class U_I18N_API LocalPointerBase<message2::data_model::Expression>;
1748 template class U_I18N_API LocalArray<message2::data_model::Expression>;
1749 #endif
1750 /// @endcond
1751 
1752 namespace message2 {
1753   namespace data_model {
1754       /**
1755          * The `UnsupportedStatement` class corresponds to the `reserved-statement` nonterminal in the MessageFormat 2
1756          * grammar and the `unsupported-statement` type defined in:
1757          * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model/message.json#L169
1758          *
1759          * It represents a keyword (string) together with an optional
1760          * `Reserved` annotation and a non-empty list of expressions.
1761          *
1762          * `UnsupportedStatement` is immutable, copyable and movable.
1763          *
1764          * @internal ICU 75 technology preview
1765          * @deprecated This API is for technology preview only.
1766          */
1767         class U_I18N_API UnsupportedStatement : public UObject {
1768         public:
1769             /**
1770              * Accesses the keyword of this statement.
1771              *
1772              * @return A reference to a string.
1773              *
1774              * @internal ICU 75 technology preview
1775              * @deprecated This API is for technology preview only.
1776              */
getKeyword()1777             const UnicodeString& getKeyword() const { return keyword; }
1778             /**
1779              * Accesses the `reserved-body` of this statement.
1780              *
1781              * @param status Input/output error code. Set to U_ILLEGAL_ARGUMENT_ERROR
1782              *         if this unsupported statement has no body.
1783              * @return A non-owned pointer to a `Reserved` annotation,
1784              *         which is non-null if U_SUCCESS(status).
1785              *
1786              * @internal ICU 75 technology preview
1787              * @deprecated This API is for technology preview only.
1788              */
1789             const Reserved* getBody(UErrorCode& status) const;
1790             /**
1791              * Accesses the expressions of this statement.
1792              *
1793              * @return A vector of Expressions.
1794              *
1795              * @internal ICU 75 technology preview
1796              * @deprecated This API is for technology preview only.
1797              */
getExpressions()1798             std::vector<Expression> getExpressions() const {
1799                 if (expressionsLen <= 0 || !expressions.isValid()) {
1800                     // This case should never happen, but we can't use an assertion here
1801                     return {};
1802                 }
1803                 return toStdVector<Expression>(expressions.getAlias(), expressionsLen);
1804             }
1805             /**
1806              * The mutable `UnsupportedStatement::Builder` class allows the statement to be constructed
1807              * incrementally.
1808              *
1809              * Builder is not copyable or movable.
1810              *
1811              * @internal ICU 75 technology preview
1812              * @deprecated This API is for technology preview only.
1813              */
1814             class U_I18N_API Builder : public UMemory {
1815             private:
1816                 friend class UnsupportedStatement;
1817                 friend class message2::Parser;
1818 
1819                 UnicodeString keyword;
1820                 std::optional<Reserved> body;
1821                 UVector* expressions; // Vector of expressions;
1822                                       // not a LocalPointer for
1823                                       // the same reason as in `SelectorKeys::builder`
1824             public:
1825                 /**
1826                  * Sets the keyword of this statement.
1827                  *
1828                  * @param k The keyword to set.
1829                  * @return A reference to the builder.
1830                  *
1831                  * @internal ICU 75 technology preview
1832                  * @deprecated This API is for technology preview only.
1833                  */
1834                 Builder& setKeyword(const UnicodeString& k);
1835                 /**
1836                  * Sets the body of this statement.
1837                  *
1838                  * @param r The `Reserved` annotation to set as the body. Passed by move.
1839                  * @return A reference to the builder.
1840                  *
1841                  * @internal ICU 75 technology preview
1842                  * @deprecated This API is for technology preview only.
1843                  */
1844                 Builder& setBody(Reserved&& r);
1845                 /**
1846                  * Adds an expression to this statement.
1847                  *
1848                  * @param e The expression to add. Passed by move.
1849                  * @param status Input/output error code.
1850                  * @return A reference to the builder.
1851                  *
1852                  * @internal ICU 75 technology preview
1853                  * @deprecated This API is for technology preview only.
1854                  */
1855                 Builder& addExpression(Expression&& e, UErrorCode& status);
1856                 /**
1857                  * Constructs a new immutable `UnsupportedStatement` using the keyword,
1858                  * body and (if applicable) expressions that were previously set.
1859                  * If `setKeyword()` was never called, then `status` is set to
1860                  * U_INVALID_STATE_ERROR. If `setBody()` was never called, the body is
1861                  * treated as absent (not an error). If `addExpression()` was not called
1862                  * at least once, then `status` is set to U_INVALID_STATE_ERROR.
1863                  *
1864                  * The builder object (`this`) can still be used after calling `build()`.
1865                  * @param status    Input/output error code.
1866                  * @return          The new UnsupportedStatement
1867                  *
1868                  * @internal ICU 75 technology preview
1869                  * @deprecated This API is for technology preview only.
1870                  */
1871                 UnsupportedStatement build(UErrorCode& status) const;
1872                 /**
1873                  * Default constructor.
1874                  * Returns a Builder with no keyword or body set.
1875                  *
1876                  * @param status    Input/output error code.
1877                  *
1878                  * @internal ICU 75 technology preview
1879                  * @deprecated This API is for technology preview only.
1880                  */
1881                 Builder(UErrorCode& status);
1882                 /**
1883                  * Destructor.
1884                  *
1885                  * @internal ICU 75 technology preview
1886                  * @deprecated This API is for technology preview only.
1887                  */
1888                 virtual ~Builder();
1889                 Builder(const Builder&) = delete;
1890                 Builder& operator=(const Builder&) = delete;
1891                 Builder(Builder&&) = delete;
1892                 Builder& operator=(Builder&&) = delete;
1893             }; // class UnsupportedStatement::Builder
1894             /**
1895              * Non-member swap function.
1896              * @param s1 will get s2's contents
1897              * @param s2 will get s1's contents
1898              *
1899              * @internal ICU 75 technology preview
1900              * @deprecated This API is for technology preview only.
1901              */
swap(UnsupportedStatement & s1,UnsupportedStatement & s2)1902             friend inline void swap(UnsupportedStatement& s1, UnsupportedStatement& s2) noexcept {
1903                 using std::swap;
1904 
1905                 swap(s1.keyword, s2.keyword);
1906                 swap(s1.body, s2.body);
1907                 swap(s1.expressions, s2.expressions);
1908                 swap(s1.expressionsLen, s2.expressionsLen);
1909             }
1910             /**
1911              * Copy constructor.
1912              *
1913              * @internal ICU 75 technology preview
1914              * @deprecated This API is for technology preview only.
1915              */
1916             UnsupportedStatement(const UnsupportedStatement& other);
1917             /**
1918              * Assignment operator.
1919              *
1920              * @internal ICU 75 technology preview
1921              * @deprecated This API is for technology preview only.
1922              */
1923             UnsupportedStatement& operator=(UnsupportedStatement) noexcept;
1924             /**
1925              * Default constructor.
1926              * Puts the UnsupportedStatement into a valid but undefined state.
1927              *
1928              * @internal ICU 75 technology preview
1929              * @deprecated This API is for technology preview only.
1930              */
UnsupportedStatement()1931             UnsupportedStatement() : expressions(LocalArray<Expression>()) {}
1932             /**
1933              * Destructor.
1934              *
1935              * @internal ICU 75 technology preview
1936              * @deprecated This API is for technology preview only.
1937              */
1938             virtual ~UnsupportedStatement();
1939         private:
1940             friend class message2::Serializer;
1941 
1942             /* const */ UnicodeString keyword;
1943             /* const */ std::optional<Reserved> body;
1944             /* const */ LocalArray<Expression> expressions;
1945             /* const */ int32_t expressionsLen = 0;
1946 
getExpressionsInternal()1947             const Expression* getExpressionsInternal() const { return expressions.getAlias(); }
1948 
1949             UnsupportedStatement(const UnicodeString&, const std::optional<Reserved>&, const UVector&, UErrorCode&);
1950         }; // class UnsupportedStatement
1951 
1952       class Pattern;
1953 
1954   // Despite the comments, `PatternPart` is internal-only
1955        /**
1956          *  A `PatternPart` is a single element (text or expression) in a `Pattern`.
1957          * It corresponds to the `body` field of the `Pattern` interface
1958          *  defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#patterns
1959          *
1960          * `PatternPart` is immutable, copyable and movable.
1961          *
1962          * @internal ICU 75 technology preview
1963          * @deprecated This API is for technology preview only.
1964          */
1965         class PatternPart : public UObject {
1966         public:
1967             /**
1968              * Checks if the part is a text part.
1969              *
1970              * @return True if and only if this is a text part.
1971              *
1972              * @internal ICU 75 technology preview
1973              * @deprecated This API is for technology preview only.
1974              */
isText()1975             UBool isText() const { return std::holds_alternative<UnicodeString>(piece); }
1976             /**
1977              * Checks if the part is a markup part.
1978              *
1979              * @return True if and only if this is a markup part.
1980              *
1981              * @internal ICU 75 technology preview
1982              * @deprecated This API is for technology preview only.
1983              */
isMarkup()1984             UBool isMarkup() const { return std::holds_alternative<Markup>(piece); }
1985             /**
1986              * Checks if the part is an expression part.
1987              *
1988              * @return True if and only if this is an expression part.
1989              *
1990              * @internal ICU 75 technology preview
1991              * @deprecated This API is for technology preview only.
1992              */
isExpression()1993             UBool isExpression() const { return std::holds_alternative<Expression>(piece); }
1994             /**
1995              * Accesses the expression of the part.
1996              * Precondition: isExpression()
1997              *
1998              * @return A reference to the part's underlying expression.
1999              *
2000              * @internal ICU 75 technology preview
2001              * @deprecated This API is for technology preview only.
2002              */
2003             const Expression& contents() const;
2004             /**
2005              * Accesses the expression of the part.
2006              * Precondition: isMarkup()
2007              *
2008              * @return A reference to the part's underlying expression.
2009              *
2010              * @internal ICU 75 technology preview
2011              * @deprecated This API is for technology preview only.
2012              */
2013             const Markup& asMarkup() const;
2014             /**
2015              * Accesses the text contents of the part.
2016              * Precondition: isText()
2017              *
2018              * @return A reference to a string representing the part's text..
2019              *
2020              * @internal ICU 75 technology preview
2021              * @deprecated This API is for technology preview only.
2022              */
2023             const UnicodeString& asText() const;
2024             /**
2025              * Non-member swap function.
2026              * @param p1 will get p2's contents
2027              * @param p2 will get p1's contents
2028              *
2029              * @internal ICU 75 technology preview
2030              * @deprecated This API is for technology preview only.
2031              */
swap(PatternPart & p1,PatternPart & p2)2032             friend inline void swap(PatternPart& p1, PatternPart& p2) noexcept {
2033                 using std::swap;
2034 
2035                 swap(p1.piece, p2.piece);
2036             }
2037             /**
2038              * Copy constructor.
2039              *
2040              * @internal ICU 75 technology preview
2041              * @deprecated This API is for technology preview only.
2042              */
2043             PatternPart(const PatternPart& other);
2044             /**
2045              * Assignment operator.
2046              *
2047              * @internal ICU 75 technology preview
2048              * @deprecated This API is for technology preview only.
2049              */
2050             PatternPart& operator=(PatternPart) noexcept;
2051             /**
2052              * Destructor.
2053              *
2054              * @internal ICU 75 technology preview
2055              * @deprecated This API is for technology preview only.
2056              */
2057             virtual ~PatternPart();
2058             /**
2059              * Text part constructor. Returns a text pattern part
2060              * with text `t`.
2061              *
2062              * @param t A text string.
2063              *
2064              * @internal ICU 75 technology preview
2065              * @deprecated This API is for technology preview only.
2066              */
PatternPart(const UnicodeString & t)2067             explicit PatternPart(const UnicodeString& t) : piece(t) {}
2068             /**
2069              * Expression part constructor. Returns an Expression pattern
2070              * part with expression `e`.
2071              *
2072              * @param e An Expression.
2073              *
2074              * @internal ICU 75 technology preview
2075              * @deprecated This API is for technology preview only.
2076              */
PatternPart(Expression && e)2077             explicit PatternPart(Expression&& e) : piece(e) {}
2078             /**
2079              * Markup part constructor. Returns a Markup pattern
2080              * part with markup `m`
2081              *
2082              * @param m A Markup.
2083              *
2084              * @internal ICU 75 technology preview
2085              * @deprecated This API is for technology preview only.
2086              */
PatternPart(Markup && m)2087             explicit PatternPart(Markup&& m) : piece(m) {}
2088             /**
2089              * Default constructor.
2090              * Puts the PatternPart into a valid but undefined state.
2091              *
2092              * @internal ICU 75 technology preview
2093              * @deprecated This API is for technology preview only.
2094              */
2095             PatternPart() = default;
2096         private:
2097             friend class Pattern;
2098 
2099             std::variant<UnicodeString, Expression, Markup> piece;
2100         }; // class PatternPart
2101   } // namespace data_model
2102 } // namespace message2
2103 
2104   /// @cond DOXYGEN_IGNORE
2105 // Export an explicit template instantiation of the LocalPointer that is used as a
2106 // data member of various MFDataModel classes.
2107 // (When building DLLs for Windows this is required.)
2108 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
2109 // for similar examples.)
2110 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
2111 template class U_I18N_API LocalPointerBase<message2::data_model::PatternPart>;
2112 template class U_I18N_API LocalArray<message2::data_model::PatternPart>;
2113 template class U_I18N_API LocalPointerBase<message2::data_model::UnsupportedStatement>;
2114 template class U_I18N_API LocalArray<message2::data_model::UnsupportedStatement>;
2115 #endif
2116 /// @endcond
2117 
2118 namespace message2 {
2119   namespace data_model {
2120         /**
2121          *  A `Pattern` is a sequence of formattable parts.
2122          * It corresponds to the `Pattern` interface
2123          * defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#patterns
2124          *
2125          * `Pattern` is immutable, copyable and movable.
2126          *
2127          * @internal ICU 75 technology preview
2128          * @deprecated This API is for technology preview only.
2129          */
2130         class U_I18N_API Pattern : public UObject {
2131         private:
2132             friend class PatternPart;
2133 
2134         public:
2135             struct Iterator;
2136             /**
2137              * Returns the parts of this pattern
2138              *
2139              * @return A forward iterator of variants. Each element is either a string (text part)
2140              *         or an expression part.
2141              *
2142              * @internal ICU 75 technology preview
2143              * @deprecated This API is for technology preview only.
2144              */
begin()2145             Iterator begin() const {
2146                 return Iterator(this, 0);
2147             }
2148             /**
2149              * Returns a special value to mark the end of iteration
2150              *
2151              * @return A forward iterator of variants. This should only be used for comparisons
2152              *         against an iterator returned by incrementing begin().
2153              *
2154              * @internal ICU 75 technology preview
2155              * @deprecated This API is for technology preview only.
2156              */
end()2157             Iterator end() const {
2158                 return Iterator(this, len);
2159             }
2160             /**
2161              * The mutable `Pattern::Builder` class allows the pattern to be
2162              * constructed one part at a time.
2163              *
2164              * Builder is not copyable or movable.
2165              *
2166              * @internal ICU 75 technology preview
2167              * @deprecated This API is for technology preview only.
2168              */
2169             class U_I18N_API Builder : public UMemory {
2170             private:
2171                 friend class Pattern;
2172 
2173                 UVector* parts;  // Not a LocalPointer for the same reason as in `SelectorKeys::Builder`
2174 
2175             public:
2176                 /**
2177                  * Adds a single expression part to the pattern.
2178                  *
2179                  * @param part The part to be added (passed by move)
2180                  * @param status Input/output error code.
2181                  * @return A reference to the builder.
2182                  *
2183                  * @internal ICU 75 technology preview
2184                  * @deprecated This API is for technology preview only.
2185                  */
2186                 Builder& add(Expression&& part, UErrorCode& status) noexcept;
2187                 /**
2188                  * Adds a single markup part to the pattern.
2189                  *
2190                  * @param part The part to be added (passed by move)
2191                  * @param status Input/output error code.
2192                  * @return A reference to the builder.
2193                  *
2194                  * @internal ICU 75 technology preview
2195                  * @deprecated This API is for technology preview only.
2196                  */
2197                 Builder& add(Markup&& part, UErrorCode& status) noexcept;
2198                 /**
2199                  * Adds a single text part to the pattern. Copies `part`.
2200                  *
2201                  * @param part The part to be added (passed by move)
2202                  * @param status Input/output error code.
2203                  * @return A reference to the builder.
2204                  *
2205                  * @internal ICU 75 technology preview
2206                  * @deprecated This API is for technology preview only.
2207                  */
2208                 Builder& add(UnicodeString&& part, UErrorCode& status) noexcept;
2209                 /**
2210                  * Constructs a new immutable `Pattern` using the list of parts
2211                  * set with previous `add()` calls.
2212                  *
2213                  * The builder object (`this`) can still be used after calling `build()`.
2214                  *
2215                  * @param status    Input/output error code.
2216                  * @return          The pattern object
2217                  *
2218                  * @internal ICU 75 technology preview
2219                  * @deprecated This API is for technology preview only.
2220                  */
2221                 Pattern build(UErrorCode& status) const noexcept;
2222                 /**
2223                  * Default constructor.
2224                  * Returns a Builder with an empty sequence of PatternParts.
2225                  *
2226                  * @param status Input/output error code
2227                  *
2228                  * @internal ICU 75 technology preview
2229                  * @deprecated This API is for technology preview only.
2230                  */
2231                 Builder(UErrorCode& status);
2232                 /**
2233                  * Destructor.
2234                  *
2235                  * @internal ICU 75 technology preview
2236                  * @deprecated This API is for technology preview only.
2237                  */
2238                 virtual ~Builder();
2239                 Builder(const Builder&) = delete;
2240                 Builder& operator=(const Builder&) = delete;
2241                 Builder(Builder&&) = delete;
2242                 Builder& operator=(Builder&&) = delete;
2243             }; // class Pattern::Builder
2244 
2245             /**
2246              * Default constructor.
2247              * Puts the Pattern into a valid but undefined state.
2248              *
2249              * @internal ICU 75 technology preview
2250              * @deprecated This API is for technology preview only.
2251              */
Pattern()2252             Pattern() : parts(LocalArray<PatternPart>()) {}
2253             /**
2254              * Non-member swap function.
2255              * @param p1 will get p2's contents
2256              * @param p2 will get p1's contents
2257              *
2258              * @internal ICU 75 technology preview
2259              * @deprecated This API is for technology preview only.
2260              */
swap(Pattern & p1,Pattern & p2)2261             friend inline void swap(Pattern& p1, Pattern& p2) noexcept {
2262                 using std::swap;
2263 
2264                 swap(p1.bogus, p2.bogus);
2265                 swap(p1.len, p2.len);
2266                 swap(p1.parts, p2.parts);
2267             }
2268             /**
2269              * Copy constructor.
2270              *
2271              * @internal ICU 75 technology preview
2272              * @deprecated This API is for technology preview only.
2273              */
2274             Pattern(const Pattern& other);
2275             /**
2276              * Assignment operator
2277              *
2278              * @internal ICU 75 technology preview
2279              * @deprecated This API is for technology preview only.
2280              */
2281             Pattern& operator=(Pattern) noexcept;
2282             /**
2283              * Destructor.
2284              *
2285              * @internal ICU 75 technology preview
2286              * @deprecated This API is for technology preview only.
2287              */
2288             virtual ~Pattern();
2289 
2290             /**
2291              *  The `Pattern::Iterator` class provides an iterator over the formattable
2292              * parts of a pattern.
2293              *
2294              * `Pattern::Iterator` is mutable and is not copyable or movable.
2295              *
2296              * @internal ICU 75 technology preview
2297              * @deprecated This API is for technology preview only.
2298              */
2299             struct U_I18N_API Iterator {
2300             private:
2301                 using iterator_category = std::forward_iterator_tag;
2302                 using difference_type = std::ptrdiff_t;
2303                 using value_type = std::variant<UnicodeString, Expression, Markup>;
2304                 using pointer = value_type*;
2305                 using reference = const value_type&;
2306 
2307                 friend class Pattern;
IteratorIterator2308                 Iterator(const Pattern* p, int32_t i) : pos(i), pat(p) {}
2309                 friend bool operator== (const Iterator& a, const Iterator& b) { return (a.pat == b.pat && a.pos == b.pos); }
2310 
2311                 int32_t pos;
2312                 const Pattern* pat;
2313 
2314             public:
2315                 /**
2316                  * Dereference operator (gets the element at the current iterator position)
2317                  *
2318                  * @internal ICU 75 technology preview
2319                  * @deprecated This API is for technology preview only.
2320                  */
2321                 reference operator*() const {
2322                     const PatternPart& part = pat->parts[pos];
2323                     return patternContents(part);
2324                 }
2325                 /**
2326                  * Increment operator (advances to the next iterator position)
2327                  *
2328                  * @internal ICU 75 technology preview
2329                  * @deprecated This API is for technology preview only.
2330                  */
2331                 Iterator operator++() { pos++; return *this; }
2332                 /**
2333                  * Inequality comparison operator (used for comparing an iterator to the result of end())
2334                  *
2335                  * @internal ICU 75 technology preview
2336                  * @deprecated This API is for technology preview only.
2337                  */
2338                 friend bool operator!= (const Iterator& a, const Iterator& b) { return !(a == b); }
2339             }; // struct Iterator
2340 
2341         private:
2342             friend class Builder;
2343             friend class message2::MessageFormatter;
2344             friend class message2::Serializer;
2345 
2346             // Set to true if a copy constructor fails;
2347             // needed in order to distinguish an uninitialized
2348             // Pattern from a 0-length pattern
2349             bool bogus = false;
2350 
2351             // Possibly-empty array of parts
2352             int32_t len = 0;
2353             LocalArray<PatternPart> parts;
2354 
2355             Pattern(const UVector& parts, UErrorCode& status);
2356             // Helper
2357             static void initParts(Pattern&, const Pattern&);
2358 
2359             /**
2360              * Returns the size.
2361              *
2362              * @return The number of parts in the pattern.
2363              *
2364              * @internal ICU 75 technology preview
2365              * @deprecated This API is for technology preview only.
2366              */
2367             int32_t numParts() const;
2368             /**
2369              * Returns the `i`th part in the pattern.
2370              * Precondition: i < numParts()
2371              *
2372              * @param i Index of the part being accessed.
2373              * @return  A reference to the part at index `i`.
2374              *
2375              * @internal ICU 75 technology preview
2376              * @deprecated This API is for technology preview only.
2377              */
2378             const PatternPart& getPart(int32_t i) const;
2379 
2380             // Gets around not being able to declare Pattern::Iterator as a friend
2381             // in PatternPart
2382             static const std::variant<UnicodeString, Expression, Markup>&
patternContents(const PatternPart & p)2383                 patternContents(const PatternPart& p) { return p.piece; }
2384         }; // class Pattern
2385 
2386         /**
2387          *  A `Variant` pairs a list of keys with a pattern
2388          * It corresponds to the `Variant` interface
2389          * defined in https://github.com/unicode-org/message-format-wg/tree/main/spec/data-model
2390          *
2391          * `Variant` is immutable, copyable and movable.
2392          *
2393          * @internal ICU 75 technology preview
2394          * @deprecated This API is for technology preview only.
2395          */
2396         class U_I18N_API Variant : public UObject {
2397         public:
2398             /**
2399              * Accesses the pattern of the variant.
2400              *
2401              * @return A reference to the pattern.
2402              *
2403              * @internal ICU 75 technology preview
2404              * @deprecated This API is for technology preview only.
2405              */
getPattern()2406             const Pattern& getPattern() const { return p; }
2407             /**
2408              * Accesses the keys of the variant.
2409              *
2410              * @return A reference to the keys.
2411              *
2412              * @internal ICU 75 technology preview
2413              * @deprecated This API is for technology preview only.
2414              */
getKeys()2415             const SelectorKeys& getKeys() const { return k; }
2416             /**
2417              * Constructor. Returns a variant that formats to `pattern`
2418              * when `keys` match the selector expressions in the enclosing
2419              * `match` construct.
2420              *
2421              * @param keys A reference to a `SelectorKeys`.
2422              * @param pattern A pattern (passed by move)
2423              *
2424              * @internal ICU 75 technology preview
2425              * @deprecated This API is for technology preview only.
2426              */
Variant(const SelectorKeys & keys,Pattern && pattern)2427             Variant(const SelectorKeys& keys, Pattern&& pattern) : k(keys), p(std::move(pattern)) {}
2428             /**
2429              * Non-member swap function.
2430              * @param v1 will get v2's contents
2431              * @param v2 will get v1's contents
2432              *
2433              * @internal ICU 75 technology preview
2434              * @deprecated This API is for technology preview only.
2435              */
swap(Variant & v1,Variant & v2)2436             friend inline void swap(Variant& v1, Variant& v2) noexcept {
2437                 using std::swap;
2438 
2439                 swap(v1.k, v2.k);
2440                 swap(v1.p, v2.p);
2441             }
2442             /**
2443              * Assignment operator
2444              *
2445              * @internal ICU 75 technology preview
2446              * @deprecated This API is for technology preview only.
2447              */
2448             Variant& operator=(Variant other) noexcept;
2449             /**
2450              * Default constructor.
2451              * Returns a Variant in a valid but undefined state.
2452              *
2453              * @internal ICU 75 technology preview
2454              * @deprecated This API is for technology preview only.
2455              */
2456             Variant() = default;
2457             /**
2458              * Copy constructor.
2459              *
2460              * @internal ICU 75 technology preview
2461              * @deprecated This API is for technology preview only.
2462              */
2463             Variant(const Variant&);
2464             /**
2465              * Destructor.
2466              *
2467              * @internal ICU 75 technology preview
2468              * @deprecated This API is for technology preview only.
2469              */
2470             virtual ~Variant();
2471         private:
2472             /* const */ SelectorKeys k;
2473             /* const */ Pattern p;
2474         }; // class Variant
2475     } // namespace data_model
2476 
2477         namespace data_model {
2478         /**
2479          *  A `Binding` pairs a variable name with an expression.
2480          * It corresponds to the `Declaration` interface
2481          * defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#messages
2482          *
2483          * `Binding` is immutable and copyable. It is not movable.
2484          *
2485          * @internal ICU 75 technology preview
2486          * @deprecated This API is for technology preview only.
2487          */
2488         class U_I18N_API Binding : public UObject {
2489         public:
2490             /**
2491              * Accesses the right-hand side of a binding.
2492              *
2493              * @return A reference to the expression.
2494              *
2495              * @internal ICU 75 technology preview
2496              * @deprecated This API is for technology preview only.
2497              */
2498             const Expression& getValue() const;
2499             /**
2500              * Accesses the left-hand side of the binding.
2501              *
2502              * @return A reference to the variable name.
2503              *
2504              * @internal ICU 75 technology preview
2505              * @deprecated This API is for technology preview only.
2506              */
getVariable()2507             const VariableName& getVariable() const { return var; }
2508             /**
2509              * Constructor for input binding.
2510              *
2511              * @param variableName The variable name (left-hand side) of the binding. Passed by move.
2512              * @param rhs The right-hand side of the input binding. Passed by move.
2513              *                   `rhs` must have an operand that is a variable reference to `variableName`.
2514              *                   If `rhs` has an operator, it must be a function call.
2515              *                   If either of these properties is violated, `errorCode` is set to
2516              *                   U_INVALID_STATE_ERROR.
2517              * @param errorCode Input/output error code
2518              *
2519              * @internal ICU 75 technology preview
2520              * @deprecated This API is for technology preview only.
2521              */
2522             static Binding input(UnicodeString&& variableName, Expression&& rhs, UErrorCode& errorCode);
2523             /**
2524              * Returns true if and only if this binding represents a local declaration.
2525              * Otherwise, it's an input declaration.
2526              *
2527              * @return True if this binding represents a variable and expression;
2528              *         false if it represents a variable plus an annotation.
2529              */
isLocal()2530             UBool isLocal() const { return local; }
2531             /**
2532              * Constructor.
2533              *
2534              * @param v A variable name.
2535              * @param e An expression.
2536              *
2537              * @internal ICU 75 technology preview
2538              * @deprecated This API is for technology preview only.
2539              */
Binding(const VariableName & v,Expression && e)2540             Binding(const VariableName& v, Expression&& e) : var(v), expr(std::move(e)), local(true), annotation(nullptr) {}
2541             /**
2542              * Non-member swap function.
2543              * @param b1 will get b2's contents
2544              * @param b2 will get b1's contents
2545              *
2546              * @internal ICU 75 technology preview
2547              * @deprecated This API is for technology preview only.
2548              */
swap(Binding & b1,Binding & b2)2549             friend inline void swap(Binding& b1, Binding& b2) noexcept {
2550                 using std::swap;
2551 
2552                 swap(b1.var, b2.var);
2553                 swap(b1.expr, b2.expr);
2554                 swap(b1.local, b2.local);
2555                 b1.updateAnnotation();
2556                 b2.updateAnnotation();
2557             }
2558             /**
2559              * Copy constructor.
2560              *
2561              * @internal ICU 75 technology preview
2562              * @deprecated This API is for technology preview only.
2563              */
2564             Binding(const Binding& other);
2565             /**
2566              * Copy assignment operator
2567              *
2568              * @internal ICU 75 technology preview
2569              * @deprecated This API is for technology preview only.
2570              */
2571             Binding& operator=(Binding) noexcept;
2572             /**
2573              * Default constructor.
2574              * Puts the Binding into a valid but undefined state.
2575              *
2576              * @internal ICU 75 technology preview
2577              * @deprecated This API is for technology preview only.
2578              */
Binding()2579             Binding() : local(true) {}
2580             /**
2581              * Destructor.
2582              *
2583              * @internal ICU 75 technology preview
2584              * @deprecated This API is for technology preview only.
2585              */
2586             virtual ~Binding();
2587         private:
2588             friend class message2::Checker;
2589             friend class message2::MessageFormatter;
2590             friend class message2::Parser;
2591             friend class message2::Serializer;
2592 
2593             /* const */ VariableName var;
2594             /* const */ Expression expr;
2595             /* const */ bool local;
2596 
2597             // The following field is always nullptr for a local
2598             // declaration, and possibly nullptr for an .input declaration
2599             // If non-null, the referent is a member of `expr` so
2600             // its lifetime is the same as the lifetime of the enclosing Binding
2601             // (as long as there's no mutation)
2602             const Callable* annotation = nullptr;
2603 
2604             const OptionMap& getOptionsInternal() const;
2605 
hasAnnotation()2606             bool hasAnnotation() const { return !local && (annotation != nullptr); }
2607             void updateAnnotation();
2608         }; // class Binding
2609     } // namespace data_model
2610 } // namespace message2
2611 
2612   /// @cond DOXYGEN_IGNORE
2613 // Export an explicit template instantiation of the LocalPointer that is used as a
2614 // data member of various MFDataModel classes.
2615 // (When building DLLs for Windows this is required.)
2616 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
2617 // for similar examples.)
2618 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
2619 template class U_I18N_API LocalPointerBase<message2::data_model::Variant>;
2620 template class U_I18N_API LocalPointerBase<message2::data_model::Binding>;
2621 template class U_I18N_API LocalArray<message2::data_model::Variant>;
2622 template class U_I18N_API LocalArray<message2::data_model::Binding>;
2623 #endif
2624 /// @endcond
2625 
2626 namespace message2 {
2627     using namespace data_model;
2628 
2629 
2630     // Internal only
2631 
2632     class MFDataModel;
2633 
2634     #ifndef U_IN_DOXYGEN
2635     class Matcher : public UObject {
2636     public:
2637         Matcher& operator=(Matcher);
2638         Matcher(const Matcher&);
2639         /**
2640          * Non-member swap function.
2641          * @param m1 will get m2's contents
2642          * @param m2 will get m1's contents
2643          *
2644          * @internal ICU 75 technology preview
2645          * @deprecated This API is for technology preview only.
2646          */
swap(Matcher & m1,Matcher & m2)2647         friend inline void swap(Matcher& m1, Matcher& m2) noexcept {
2648             using std::swap;
2649 
2650             if (m1.bogus) {
2651                 m2.bogus = true;
2652                 return;
2653             }
2654             if (m2.bogus) {
2655                 m1.bogus = true;
2656                 return;
2657             }
2658             swap(m1.selectors, m2.selectors);
2659             swap(m1.numSelectors, m2.numSelectors);
2660             swap(m1.variants, m2.variants);
2661             swap(m1.numVariants, m2.numVariants);
2662         }
2663         virtual ~Matcher();
2664     private:
2665 
2666         friend class MFDataModel;
2667 
2668         Matcher(Expression* ss, int32_t ns, Variant* vs, int32_t nv);
Matcher()2669         Matcher() {}
2670 
2671         // A Matcher may have numSelectors=0 and numVariants=0
2672         // (this is a data model error, but it's representable).
2673         // So we have to keep a separate flag to track failed copies.
2674         bool bogus = false;
2675 
2676         // The expressions that are being matched on.
2677         LocalArray<Expression> selectors;
2678         // The number of selectors
2679         int32_t numSelectors = 0;
2680         // The list of `when` clauses (case arms).
2681         LocalArray<Variant> variants;
2682         // The number of variants
2683         int32_t numVariants = 0;
2684     }; // class Matcher
2685     #endif
2686 } // namespace message2
2687 
2688 U_NAMESPACE_END
2689 
2690 /// @cond DOXYGEN_IGNORE
2691 // Export an explicit template instantiation of the std::variant that is used as a
2692 // data member of various MFDataModel classes.
2693 // (When building DLLs for Windows this is required.)
2694 // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others
2695 // for similar examples.)
2696 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
2697 #if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION)
2698 template class U_I18N_API std::_Variant_storage_<false, icu::message2::Matcher,icu::message2::data_model::Pattern>;
2699 #endif
2700 template class U_I18N_API std::variant<icu::message2::Matcher,icu::message2::data_model::Pattern>;
2701 #endif
2702 /// @endcond
2703 
2704 U_NAMESPACE_BEGIN
2705 
2706 namespace message2 {
2707     // -----------------------------------------------------------------------
2708     // Public MFDataModel class
2709 
2710     /**
2711      *
2712      * The `MFDataModel` class describes a parsed representation of the text of a message.
2713      * This representation is public as higher-level APIs for messages will need to know its public
2714      * interface: for example, to re-instantiate a parsed message with different values for imported
2715      variables.
2716      *
2717      * The MFDataModel API implements <a target="github"
2718      href="https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md">the
2719      * specification of the abstract syntax (data model representation)</a> for MessageFormat.
2720      *
2721      * `MFDataModel` is immutable, copyable and movable.
2722      *
2723      * @internal ICU 75 technology preview
2724      * @deprecated This API is for technology preview only.
2725      */
2726     class U_I18N_API MFDataModel : public UMemory {
2727         /*
2728           Classes that represent nodes in the data model are nested inside the
2729           `MFDataModel` class.
2730 
2731           Classes such as `Expression`, `Pattern` and `VariantMap` are immutable and
2732           are constructed using the builder pattern.
2733 
2734           Most classes representing nodes have copy constructors. This is because builders
2735           contain immutable data that must be copied when calling `build()`, since the builder
2736           could go out of scope before the immutable result of the builder does. Copying is
2737           also necessary to prevent unexpected mutation if intermediate builders are saved
2738           and mutated again after calling `build()`.
2739 
2740           The copy constructors perform a deep copy, for example by copying the entire
2741           list of options for an `Operator` (and copying the entire underlying vector.)
2742           Some internal fields should be `const`, but are declared as non-`const` to make
2743           the copy constructor simpler to implement. (These are noted throughout.) In
2744           other words, those fields are `const` except during the execution of a copy
2745           constructor.
2746 
2747           On the other hand, intermediate `Builder` methods that return a `Builder&`
2748           mutate the state of the builder, so in code like:
2749 
2750           Expression::Builder& exprBuilder = Expression::builder()-> setOperand(foo);
2751           Expression::Builder& exprBuilder2 = exprBuilder.setOperator(bar);
2752 
2753           the call to `setOperator()` would mutate `exprBuilder`, since `exprBuilder`
2754           and `exprBuilder2` are references to the same object.
2755 
2756           An alternate choice would be to make `build()` destructive, so that copying would
2757           be unnecessary. Or, both copying and moving variants of `build()` could be
2758           provided. Copying variants of the intermediate `Builder` methods could be
2759           provided as well, if this proved useful.
2760         */
2761     public:
2762         /**
2763          * Accesses the local variable declarations for this data model.
2764          *
2765          * @return A vector of bindings for local variables.
2766          *
2767          * @internal ICU 75 technology preview
2768          * @deprecated This API is for technology preview only.
2769          */
getLocalVariables()2770         std::vector<Binding> getLocalVariables() const {
2771             std::vector<Binding> result;
2772             if (!bogus) {
2773                 return toStdVector<Binding>(bindings.getAlias(), bindingsLen);
2774             }
2775             return {};
2776         }
2777         /**
2778          * Accesses the selectors. Returns an empty vector if this is a pattern message.
2779          *
2780          * @return A vector of selectors.
2781          *
2782          * @internal ICU 75 technology preview
2783          * @deprecated This API is for technology preview only.
2784          */
getSelectors()2785         const std::vector<Expression> getSelectors() const {
2786             if (std::holds_alternative<Pattern>(body)) {
2787                 return {};
2788             }
2789             const Matcher* match = std::get_if<Matcher>(&body);
2790             // match must be non-null, given the previous check
2791             return toStdVector<Expression>(match->selectors.getAlias(), match->numSelectors);
2792         }
2793         /**
2794          * Accesses the variants. Returns an empty vector if this is a pattern message.
2795          *
2796          * @return A vector of variants.
2797          *
2798          * @internal ICU 75 technology preview
2799          * @deprecated This API is for technology preview only.
2800          */
getVariants()2801         std::vector<Variant> getVariants() const {
2802             // Return empty vector if no variants
2803             if (std::holds_alternative<Pattern>(body)) {
2804                 return {};
2805             }
2806             const Matcher* match = std::get_if<Matcher>(&body);
2807             // match must be non-null, given the previous check
2808             return toStdVector<Variant>(match->variants.getAlias(), match->numVariants);
2809             return {};
2810         }
2811         /**
2812          * Accesses the unsupported statements for this data model.
2813          *
2814          * @return A vector of unsupported statements.
2815          *
2816          * @internal ICU 75 technology preview
2817          * @deprecated This API is for technology preview only.
2818          */
getUnsupportedStatements()2819         std::vector<UnsupportedStatement> getUnsupportedStatements() const {
2820             std::vector<UnsupportedStatement> result;
2821             if (!bogus) {
2822                 return toStdVector<UnsupportedStatement>(unsupportedStatements.getAlias(), unsupportedStatementsLen);
2823             }
2824             return {};
2825         }
2826         /**
2827          * Accesses the pattern (in a message without selectors).
2828          * Returns a reference to an empty pattern if the message has selectors.
2829          *
2830          * @return A reference to the pattern.
2831          *
2832          * @internal ICU 75 technology preview
2833          * @deprecated This API is for technology preview only.
2834          */
2835         const Pattern& getPattern() const;
2836 
2837         /**
2838          * The mutable `MFDataModel::Builder` class allows the data model to be
2839          * constructed incrementally.
2840          *
2841          * @internal ICU 75 technology preview
2842          * @deprecated This API is for technology preview only.
2843          */
2844         class U_I18N_API Builder;
2845 
2846         /**
2847          * Default constructor.
2848          * Puts the MFDataModel into a valid but undefined state.
2849          *
2850          * @internal ICU 75 technology preview
2851          * @deprecated This API is for technology preview only.
2852          */
2853         MFDataModel();
2854         /**
2855          * Non-member swap function.
2856          * @param m1 will get m2's contents
2857          * @param m2 will get m1's contents
2858          *
2859          * @internal ICU 75 technology preview
2860          * @deprecated This API is for technology preview only.
2861          */
swap(MFDataModel & m1,MFDataModel & m2)2862         friend inline void swap(MFDataModel& m1, MFDataModel& m2) noexcept {
2863             using std::swap;
2864 
2865             if (m1.bogus) {
2866                 m2.bogus = true;
2867                 return;
2868             }
2869             if (m2.bogus) {
2870                 m1.bogus = true;
2871                 return;
2872             }
2873             swap(m1.body, m2.body);
2874             swap(m1.bindings, m2.bindings);
2875             swap(m1.bindingsLen, m2.bindingsLen);
2876             swap(m1.unsupportedStatements, m2.unsupportedStatements);
2877             swap(m1.unsupportedStatementsLen, m2.unsupportedStatementsLen);
2878         }
2879         /**
2880          * Assignment operator
2881          *
2882          * @internal ICU 75 technology preview
2883          * @deprecated This API is for technology preview only.
2884          */
2885         MFDataModel& operator=(MFDataModel) noexcept;
2886         /**
2887          * Copy constructor.
2888          *
2889          * @internal ICU 75 technology preview
2890          * @deprecated This API is for technology preview only.
2891          */
2892         MFDataModel(const MFDataModel& other);
2893         /**
2894          * Destructor.
2895          *
2896          * @internal ICU 75 technology preview
2897          * @deprecated This API is for technology preview only.
2898          */
2899         virtual ~MFDataModel();
2900 
2901         /**
2902          * The mutable `MFDataModel::Builder` class allows the data model to be
2903          * constructed incrementally. Builder is not copyable or movable.
2904          *
2905          * @internal ICU 75 technology preview
2906          * @deprecated This API is for technology preview only.
2907          */
2908         class U_I18N_API Builder : public UMemory {
2909         private:
2910             friend class MFDataModel;
2911 
2912             void checkDuplicate(const VariableName&, UErrorCode&) const;
2913             void buildSelectorsMessage(UErrorCode&);
2914             bool hasPattern = true;
2915             bool hasSelectors = false;
2916             Pattern pattern;
2917             // The following members are not LocalPointers for the same reason as in SelectorKeys::Builder
2918             UVector* selectors = nullptr;
2919             UVector* variants = nullptr;
2920             UVector* bindings = nullptr;
2921             UVector* unsupportedStatements = nullptr;
2922         public:
2923             /**
2924              * Adds a binding, There must not already be a binding
2925              * with the same name.
2926              *
2927              * @param b The binding. Passed by move.
2928              * @param status Input/output error code. Set to U_DUPLICATE_DECLARATION_ERROR
2929              *                   if `addBinding()` was previously called with a binding
2930              *                   with the same variable name as `b`.
2931              *
2932              * @internal ICU 75 technology preview
2933              * @deprecated This API is for technology preview only.
2934              */
2935             Builder& addBinding(Binding&& b, UErrorCode& status);
2936             /**
2937              * Adds an unsupported statement.
2938              *
2939              * @param s The statement. Passed by move.
2940              * @param status Input/output error code.
2941              *
2942              *
2943              * @internal ICU 75 technology preview
2944              * @deprecated This API is for technology preview only.
2945              */
2946             Builder& addUnsupportedStatement(UnsupportedStatement&& s, UErrorCode& status);
2947             /**
2948              * Adds a selector expression. Copies `expression`.
2949              * If a pattern was previously set, clears the pattern.
2950              *
2951              * @param selector Expression to add as a selector. Passed by move.
2952              * @param errorCode Input/output error code
2953              * @return A reference to the builder.
2954              *
2955              * @internal ICU 75 technology preview
2956              * @deprecated This API is for technology preview only.
2957              */
2958             Builder& addSelector(Expression&& selector, UErrorCode& errorCode) noexcept;
2959             /**
2960              * Adds a single variant.
2961              * If a pattern was previously set using `setPattern()`, clears the pattern.
2962              *
2963              * @param keys Keys for the variant. Passed by move.
2964              * @param pattern Pattern for the variant. Passed by move.
2965              * @param errorCode Input/output error code
2966              * @return A reference to the builder.
2967              *
2968              * @internal ICU 75 technology preview
2969              * @deprecated This API is for technology preview only.
2970              */
2971             Builder& addVariant(SelectorKeys&& keys, Pattern&& pattern, UErrorCode& errorCode) noexcept;
2972             /**
2973              * Sets the body of the message as a pattern.
2974              * If selectors and/or variants were previously set, clears them.
2975              *
2976              * @param pattern Pattern to represent the body of the message.
2977              *                Passed by move.
2978              * @return A reference to the builder.
2979              *
2980              * @internal ICU 75 technology preview
2981              * @deprecated This API is for technology preview only.
2982              */
2983             Builder& setPattern(Pattern&& pattern);
2984             /**
2985              * Constructs a new immutable data model.
2986              * If `setPattern()` has not been called and if `addSelector()` and
2987              * `addVariant()` were not each called at least once,
2988              * `status` is set to `U_INVALID_STATE_ERROR`.
2989              * If `addSelector()` was called and `addVariant()` was never called,
2990              * or vice versa, then `status` is set to U_INVALID_STATE_ERROR.
2991              * Otherwise, either a Pattern or Selectors message is constructed
2992              * based on the pattern that was previously set, or selectors and variants
2993              * that were previously set.
2994              *
2995              * The builder object (`this`) can still be used after calling `build()`.
2996              *
2997              * @param status Input/output error code.
2998              * @return       The new MFDataModel
2999              *
3000              * @internal ICU 75 technology preview
3001              * @deprecated This API is for technology preview only.
3002              */
3003             MFDataModel build(UErrorCode& status) const noexcept;
3004             /**
3005              * Default constructor.
3006              * Returns a Builder with no pattern or selectors set.
3007              * Either `setPattern()` or both `addSelector()` and
3008              * `addVariant()` must be called before calling `build()`
3009              * on the resulting builder.
3010              *
3011              * @param status Input/output error code.
3012              *
3013              * @internal ICU 75 technology preview
3014              * @deprecated This API is for technology preview only.
3015              */
3016             Builder(UErrorCode& status);
3017             /**
3018              * Destructor.
3019              *
3020              * @internal ICU 75 technology preview
3021              * @deprecated This API is for technology preview only.
3022              */
3023             virtual ~Builder();
3024             Builder(const Builder&) = delete;
3025             Builder& operator=(const Builder&) = delete;
3026             Builder(Builder&&) = delete;
3027             Builder& operator=(Builder&&) = delete;
3028         }; // class Builder
3029 
3030     private:
3031         friend class Checker;
3032         friend class MessageFormatter;
3033         friend class Serializer;
3034 
3035         Pattern empty; // Provided so that `getPattern()` can return a result
3036                        // if called on a selectors message
hasPattern()3037         bool hasPattern() const { return std::holds_alternative<Pattern>(body); }
3038 
3039         bool bogus = false; // Set if a copy constructor fails
3040 
3041         // A message body is either a matcher (selector list and variant list),
3042         // or a single pattern
3043         std::variant<Matcher, Pattern> body;
3044 
3045         // Bindings for local variables
3046         /* const */ LocalArray<Binding> bindings;
3047         int32_t bindingsLen = 0;
3048 
3049         // Unsupported statements
3050         // (Treated as a type of `declaration` in the data model spec;
3051         // stored separately for convenience)
3052         /* const */ LocalArray<UnsupportedStatement> unsupportedStatements;
3053         int32_t unsupportedStatementsLen = 0;
3054 
3055         const Binding* getLocalVariablesInternal() const;
3056         const Expression* getSelectorsInternal() const;
3057         const Variant* getVariantsInternal() const;
3058         const UnsupportedStatement* getUnsupportedStatementsInternal() const;
3059 
numSelectors()3060         int32_t numSelectors() const {
3061             const Matcher* matcher = std::get_if<Matcher>(&body);
3062             return (matcher == nullptr ? 0 : matcher->numSelectors);
3063         }
numVariants()3064         int32_t numVariants() const {
3065             const Matcher* matcher = std::get_if<Matcher>(&body);
3066             return (matcher == nullptr ? 0 : matcher->numVariants);
3067         }
3068 
3069         // Helper
3070         void initBindings(const Binding*);
3071 
3072         MFDataModel(const Builder& builder, UErrorCode&) noexcept;
3073     }; // class MFDataModel
3074 
3075 } // namespace message2
3076 
3077 U_NAMESPACE_END
3078 
3079 #endif // U_HIDE_DEPRECATED_API
3080 
3081 #endif /* #if !UCONFIG_NO_MF2 */
3082 
3083 #endif /* #if !UCONFIG_NO_FORMATTING */
3084 
3085 #endif /* U_SHOW_CPLUSPLUS_API */
3086 
3087 #endif // MESSAGEFORMAT_DATA_MODEL_H
3088 
3089 // eof
3090 
3091