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