xref: /aosp_15_r20/external/icu/icu4c/source/i18n/messageformat2_data_model.cpp (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
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 #if !UCONFIG_NO_FORMATTING
7 
8 #if !UCONFIG_NO_MF2
9 
10 #include "unicode/messageformat2_data_model.h"
11 #include "messageformat2_allocation.h"
12 #include "messageformat2_macros.h"
13 #include "uvector.h"
14 
15 U_NAMESPACE_BEGIN
16 
17 namespace message2 {
18 
19 // Implementation
20 
21 //------------------ SelectorKeys
22 
getKeysInternal() const23 const Key* SelectorKeys::getKeysInternal() const {
24     return keys.getAlias();
25 }
26 
27 // Lexically order key lists
operator <(const SelectorKeys & other) const28 bool SelectorKeys::operator<(const SelectorKeys& other) const {
29     // Handle key lists of different sizes first --
30     // this case does have to be handled (even though it would
31     // reflect a data model error) because of the need to produce
32     // partial output
33     if (len < other.len) {
34         return true;
35     }
36     if (len > other.len) {
37         return false;
38     }
39 
40     for (int32_t i = 0; i < len; i++) {
41         if (keys[i] < other.keys[i]) {
42             return true;
43         }
44         if (!(keys[i] == other.keys[i])) {
45             return false;
46         }
47     }
48     // If we've reached here, all keys must be equal
49     return false;
50 }
51 
Builder(UErrorCode & status)52 SelectorKeys::Builder::Builder(UErrorCode& status) {
53     keys = createUVector(status);
54 }
55 
add(Key && key,UErrorCode & status)56 SelectorKeys::Builder& SelectorKeys::Builder::add(Key&& key, UErrorCode& status) noexcept {
57     U_ASSERT(keys != nullptr);
58     if (U_SUCCESS(status)) {
59         Key* k = create<Key>(std::move(key), status);
60         keys->adoptElement(k, status);
61     }
62     return *this;
63 }
64 
build(UErrorCode & status) const65 SelectorKeys SelectorKeys::Builder::build(UErrorCode& status) const {
66     if (U_FAILURE(status)) {
67         return {};
68     }
69     U_ASSERT(keys != nullptr);
70     return SelectorKeys(*keys, status);
71 }
72 
~Builder()73 SelectorKeys::Builder::~Builder() {
74     if (keys != nullptr) {
75         delete keys;
76     }
77 }
78 
SelectorKeys(const UVector & ks,UErrorCode & status)79 SelectorKeys::SelectorKeys(const UVector& ks, UErrorCode& status) : len(ks.size()) {
80     Key* result = copyVectorToArray<Key>(ks, status);
81     if (U_FAILURE(status)) {
82         return;
83     }
84     keys.adoptInstead(result);
85 }
86 
operator =(SelectorKeys other)87 SelectorKeys& SelectorKeys::operator=(SelectorKeys other) noexcept {
88     swap(*this, other);
89     return *this;
90 }
91 
SelectorKeys(const SelectorKeys & other)92 SelectorKeys::SelectorKeys(const SelectorKeys& other) : len(other.len) {
93     UErrorCode localErrorCode = U_ZERO_ERROR;
94     if (len != 0) {
95         keys.adoptInstead(copyArray(other.keys.getAlias(), len, localErrorCode));
96     }
97     if (U_FAILURE(localErrorCode)) {
98         len = 0;
99     }
100 }
101 
~SelectorKeys()102 SelectorKeys::~SelectorKeys() {
103     len = 0;
104 }
105 
106 //------------------ Literal
107 
operator <(const Literal & other) const108 bool Literal::operator<(const Literal& other) const {
109     // Ignore quoting for the purposes of ordering
110     return contents < other.contents;
111 }
112 
operator ==(const Literal & other) const113 bool Literal::operator==(const Literal& other) const {
114     // Ignore quoting for the purposes of ordering
115     return contents == other.contents;
116 }
117 
quoted() const118 UnicodeString Literal::quoted() const {
119     UnicodeString result(PIPE);
120     result += unquoted();
121     result += PIPE;
122     return result;
123 }
124 
unquoted() const125 const UnicodeString& Literal::unquoted() const { return contents; }
126 
operator =(Literal other)127 Literal& Literal::operator=(Literal other) noexcept {
128     swap(*this, other);
129 
130     return *this;
131 }
132 
~Literal()133 Literal::~Literal() {
134     thisIsQuoted = false;
135 }
136 
137 //------------------ Operand
138 
Operand(const Operand & other)139 Operand::Operand(const Operand& other) : contents(other.contents) {}
140 
operator =(Operand other)141 Operand& Operand::operator=(Operand other) noexcept {
142     swap(*this, other);
143 
144     return *this;
145 }
146 
isVariable() const147 UBool Operand::isVariable() const {
148     return (contents.has_value() && std::holds_alternative<VariableName>(*contents));
149 }
isLiteral() const150 UBool Operand::isLiteral() const {
151     return (contents.has_value() && std::holds_alternative<Literal>(*contents));
152 }
isNull() const153 UBool Operand::isNull() const { return !contents.has_value(); }
154 
asLiteral() const155 const Literal& Operand::asLiteral() const {
156     U_ASSERT(isLiteral());
157     return *(std::get_if<Literal>(&(*contents)));
158 }
159 
asVariable() const160 const VariableName& Operand::asVariable() const {
161     U_ASSERT(isVariable());
162     return *(std::get_if<VariableName>(&(*contents)));
163 }
164 
~Operand()165 Operand::~Operand() {}
166 
167 //---------------- Key
168 
operator =(Key other)169 Key& Key::operator=(Key other) noexcept {
170     swap(*this, other);
171     return *this;
172 }
173 
operator <(const Key & other) const174 bool Key::operator<(const Key& other) const {
175     // Arbitrarily treat * as greater than all concrete keys
176     if (isWildcard()) {
177         return false;
178     }
179     if (other.isWildcard()) {
180         return true;
181     }
182     return (asLiteral() < other.asLiteral());
183 }
184 
operator ==(const Key & other) const185 bool Key::operator==(const Key& other) const {
186     if (isWildcard()) {
187         return other.isWildcard();
188     }
189     return (asLiteral() == other.asLiteral());
190 }
191 
asLiteral() const192 const Literal& Key::asLiteral() const {
193     U_ASSERT(!isWildcard());
194     return *contents;
195 }
196 
~Key()197 Key::~Key() {}
198 
199 // ------------ Reserved
200 
201 // Copy constructor
Reserved(const Reserved & other)202 Reserved::Reserved(const Reserved& other) : len(other.len) {
203     U_ASSERT(!other.bogus);
204 
205     UErrorCode localErrorCode = U_ZERO_ERROR;
206     if (len == 0) {
207         parts.adoptInstead(nullptr);
208     } else {
209         parts.adoptInstead(copyArray(other.parts.getAlias(), len, localErrorCode));
210     }
211     if (U_FAILURE(localErrorCode)) {
212         bogus = true;
213     }
214 }
215 
operator =(Reserved other)216 Reserved& Reserved::operator=(Reserved other) noexcept {
217     swap(*this, other);
218     return *this;
219 }
220 
Reserved(const UVector & ps,UErrorCode & status)221 Reserved::Reserved(const UVector& ps, UErrorCode& status) noexcept : len(ps.size()) {
222     if (U_FAILURE(status)) {
223         return;
224     }
225     parts = LocalArray<Literal>(copyVectorToArray<Literal>(ps, status));
226 }
227 
numParts() const228 int32_t Reserved::numParts() const {
229     U_ASSERT(!bogus);
230     return len;
231 }
232 
getPart(int32_t i) const233 const Literal& Reserved::getPart(int32_t i) const {
234     U_ASSERT(!bogus);
235     U_ASSERT(i < numParts());
236     return parts[i];
237 }
238 
Builder(UErrorCode & status)239 Reserved::Builder::Builder(UErrorCode& status) {
240     parts = createUVector(status);
241 }
242 
build(UErrorCode & status) const243 Reserved Reserved::Builder::build(UErrorCode& status) const noexcept {
244     if (U_FAILURE(status)) {
245         return {};
246     }
247     U_ASSERT(parts != nullptr);
248     return Reserved(*parts, status);
249 }
250 
add(Literal && part,UErrorCode & status)251 Reserved::Builder& Reserved::Builder::add(Literal&& part, UErrorCode& status) noexcept {
252     U_ASSERT(parts != nullptr);
253     if (U_SUCCESS(status)) {
254         Literal* l = create<Literal>(std::move(part), status);
255         parts->adoptElement(l, status);
256     }
257     return *this;
258 }
259 
~Builder()260 Reserved::Builder::~Builder() {
261     if (parts != nullptr) {
262         delete parts;
263     }
264 }
265 
~Reserved()266 Reserved::~Reserved() {
267     len = 0;
268 }
269 
270 //------------------------ Operator
271 
OptionMap(const UVector & opts,UErrorCode & status)272 OptionMap::OptionMap(const UVector& opts, UErrorCode& status) : len(opts.size()) {
273     Option* result = copyVectorToArray<Option>(opts, status);
274     if (U_FAILURE(status)) {
275         bogus = true;
276         return;
277     }
278     options.adoptInstead(result);
279     bogus = false;
280 }
281 
OptionMap(const OptionMap & other)282 OptionMap::OptionMap(const OptionMap& other) : len(other.len) {
283     U_ASSERT(!other.bogus);
284     UErrorCode localErrorCode = U_ZERO_ERROR;
285     Option* result = copyArray(other.options.getAlias(), len, localErrorCode);
286     if (U_FAILURE(localErrorCode)) {
287         bogus = true;
288         return;
289     }
290     bogus = false;
291     options.adoptInstead(result);
292 }
293 
operator =(OptionMap other)294 OptionMap& OptionMap::operator=(OptionMap other) {
295     swap(*this, other);
296     return *this;
297 }
298 
getOption(int32_t i,UErrorCode & status) const299 const Option& OptionMap::getOption(int32_t i, UErrorCode& status) const {
300     if (U_FAILURE(status) || bogus) {
301         if (bogus) {
302             status = U_MEMORY_ALLOCATION_ERROR;
303         }
304     } else {
305         U_ASSERT(options.isValid());
306         U_ASSERT(i < len);
307     }
308     return options[i];
309 }
310 
size() const311 int32_t OptionMap::size() const {
312     U_ASSERT(options.isValid() || len == 0);
313     return len;
314 }
315 
~OptionMap()316 OptionMap::~OptionMap() {}
317 
build(UErrorCode & status)318 OptionMap OptionMap::Builder::build(UErrorCode& status) {
319     return OptionMap(*options, status);
320 }
321 
Builder(UErrorCode & status)322 OptionMap::Builder::Builder(UErrorCode& status) {
323     options = createStringUVector(status);
324 }
325 
Builder(OptionMap::Builder && other)326 OptionMap::Builder::Builder(OptionMap::Builder&& other) {
327     checkDuplicates = other.checkDuplicates;
328     options = other.options;
329     other.options = nullptr;
330 }
331 
operator =(OptionMap::Builder other)332 OptionMap::Builder& OptionMap::Builder::operator=(OptionMap::Builder other) noexcept {
333     swap(*this, other);
334     return *this;
335 }
336 
attributes(UErrorCode & status)337 /* static */ OptionMap::Builder OptionMap::Builder::attributes(UErrorCode& status) {
338     Builder b(status);
339     // The same code is re-used for representing attributes and options.
340     // Duplicate attributes are allowed, while duplicate options are disallowed.
341     b.checkDuplicates = false;
342     return b;
343 }
344 
hasOptionNamed(const UVector & v,const UnicodeString & s)345 static UBool hasOptionNamed(const UVector& v, const UnicodeString& s) {
346     for (int32_t i = 0; i < v.size(); i++) {
347         const Option* opt = static_cast<Option*>(v[i]);
348         U_ASSERT(opt != nullptr);
349         if (opt->getName() == s) {
350             return true;
351         }
352     }
353     return false;
354 }
355 
add(Option && opt,UErrorCode & status)356 OptionMap::Builder& OptionMap::Builder::add(Option&& opt, UErrorCode& status) {
357     THIS_ON_ERROR(status);
358 
359     // If the option name is already in the map, emit a data model error
360     if (checkDuplicates && hasOptionNamed(*options, opt.getName())) {
361         status = U_MF_DUPLICATE_OPTION_NAME_ERROR;
362     } else {
363         Option* newOption = create<Option>(std::move(opt), status);
364         options->adoptElement(newOption, status);
365     }
366     return *this;
367 }
368 
~Builder()369 OptionMap::Builder::~Builder() {
370     if (options != nullptr) {
371         delete options;
372     }
373 }
374 
asReserved() const375 const Reserved& Operator::asReserved() const {
376     U_ASSERT(isReserved());
377     return *(std::get_if<Reserved>(&contents));
378 }
379 
getOptionsInternal() const380 const OptionMap& Operator::getOptionsInternal() const {
381     U_ASSERT(!isReserved());
382     return std::get_if<Callable>(&contents)->getOptions();
383 }
384 
Option(const Option & other)385 Option::Option(const Option& other): name(other.name), rand(other.rand) {}
386 
operator =(Option other)387 Option& Option::operator=(Option other) noexcept {
388     swap(*this, other);
389     return *this;
390 }
391 
~Option()392 Option::~Option() {}
393 
Builder(UErrorCode & status)394 Operator::Builder::Builder(UErrorCode& status) : options(OptionMap::Builder(status)) {}
395 
setReserved(Reserved && reserved)396 Operator::Builder& Operator::Builder::setReserved(Reserved&& reserved) {
397     isReservedSequence = true;
398     hasFunctionName = false;
399     hasOptions = false;
400     asReserved = std::move(reserved);
401     return *this;
402 }
403 
setFunctionName(FunctionName && func)404 Operator::Builder& Operator::Builder::setFunctionName(FunctionName&& func) {
405     isReservedSequence = false;
406     hasFunctionName = true;
407     functionName = std::move(func);
408     return *this;
409 }
410 
getFunctionName() const411 const FunctionName& Operator::getFunctionName() const {
412     U_ASSERT(!isReserved());
413     return std::get_if<Callable>(&contents)->getName();
414 }
415 
addOption(const UnicodeString & key,Operand && value,UErrorCode & errorCode)416 Operator::Builder& Operator::Builder::addOption(const UnicodeString &key, Operand&& value, UErrorCode& errorCode) noexcept {
417     THIS_ON_ERROR(errorCode);
418 
419     isReservedSequence = false;
420     hasOptions = true;
421     options.add(Option(key, std::move(value)), errorCode);
422     return *this;
423 }
424 
build(UErrorCode & errorCode)425 Operator Operator::Builder::build(UErrorCode& errorCode) {
426     Operator result;
427     if (U_FAILURE(errorCode)) {
428         return result;
429     }
430     // Must be either reserved or function, not both; enforced by methods
431     if (isReservedSequence) {
432         // Methods enforce that the function name and options are unset
433         // if `setReserved()` is called, so if they were valid, that
434         // would indicate a bug.
435         U_ASSERT(!hasOptions && !hasFunctionName);
436         result = Operator(asReserved);
437     } else {
438         if (!hasFunctionName) {
439             // Neither function name nor reserved was set
440             // There is no default, so this case could occur if the
441             // caller creates a builder and doesn't make any calls
442             // before calling build().
443             errorCode = U_INVALID_STATE_ERROR;
444             return result;
445         }
446         result = Operator(functionName, options.build(errorCode));
447     }
448     return result;
449 }
450 
Operator(const Operator & other)451 Operator::Operator(const Operator& other) noexcept : contents(other.contents) {}
452 
operator =(Operator other)453 Operator& Operator::operator=(Operator other) noexcept {
454     swap(*this, other);
455     return *this;
456 }
457 
458 // Function call
Operator(const FunctionName & f,const UVector & optsVector,UErrorCode & status)459 Operator::Operator(const FunctionName& f, const UVector& optsVector, UErrorCode& status) : contents(Callable(f, OptionMap(optsVector, status))) {}
460 
Operator(const FunctionName & f,const OptionMap & opts)461 Operator::Operator(const FunctionName& f, const OptionMap& opts) : contents(Callable(f, opts)) {}
462 
~Builder()463 Operator::Builder::~Builder() {}
464 
~Operator()465 Operator::~Operator() {}
466 
operator =(Callable other)467 Callable& Callable::operator=(Callable other) noexcept {
468     swap(*this, other);
469     return *this;
470 }
471 
Callable(const Callable & other)472 Callable::Callable(const Callable& other) : name(other.name), options(other.options) {}
473 
~Callable()474 Callable::~Callable() {}
475 
476 // ------------ Markup
477 
Builder(UErrorCode & status)478 Markup::Builder::Builder(UErrorCode& status)
479     : options(OptionMap::Builder(status)), attributes(OptionMap::Builder::attributes(status)) {}
480 
Markup(UMarkupType ty,UnicodeString n,OptionMap && o,OptionMap && a)481 Markup::Markup(UMarkupType ty, UnicodeString n, OptionMap&& o, OptionMap&& a)
482     : type(ty), name(n), options(std::move(o)), attributes(std::move(a)) {}
483 
addOption(const UnicodeString & key,Operand && value,UErrorCode & errorCode)484 Markup::Builder& Markup::Builder::addOption(const UnicodeString &key,
485                                             Operand&& value,
486                                             UErrorCode& errorCode) {
487     options.add(Option(key, std::move(value)), errorCode);
488     return *this;
489 }
490 
addAttribute(const UnicodeString & key,Operand && value,UErrorCode & errorCode)491 Markup::Builder& Markup::Builder::addAttribute(const UnicodeString &key,
492                                                Operand&& value,
493                                                UErrorCode& errorCode) {
494     attributes.add(Option(key, std::move(value)), errorCode);
495     return *this;
496 }
497 
build(UErrorCode & errorCode)498 Markup Markup::Builder::build(UErrorCode& errorCode) {
499     Markup result;
500 
501     if (U_FAILURE(errorCode)) {
502         return result;
503     }
504 
505     if (type == UMARKUP_COUNT || name.length() == 0) {
506         // One of `setOpen()`, `setClose()`, or `setStandalone()`
507         // must be called before calling build()
508         // setName() must be called before calling build()
509         errorCode = U_INVALID_STATE_ERROR;
510     } else {
511         result = Markup(type,
512                         name,
513                         options.build(errorCode),
514                         attributes.build(errorCode));
515     }
516     return result;
517 }
518 
~Builder()519 Markup::Builder::~Builder() {}
520 
~Markup()521 Markup::~Markup() {}
522 
523 // ------------ Expression
524 
Builder(UErrorCode & status)525 Expression::Builder::Builder(UErrorCode& status)
526     : attributes(OptionMap::Builder::attributes(status)) {}
527 
isStandaloneAnnotation() const528 UBool Expression::isStandaloneAnnotation() const {
529     return rand.isNull();
530 }
531 
532 // Returns true for function calls with operands as well as
533 // standalone annotations.
534 // Reserved sequences are not function calls
isFunctionCall() const535 UBool Expression::isFunctionCall() const {
536     return (rator.has_value() && !rator->isReserved());
537 }
538 
isReserved() const539 UBool Expression::isReserved() const {
540     return (rator.has_value() && rator->isReserved());
541 }
542 
getOperator(UErrorCode & status) const543 const Operator* Expression::getOperator(UErrorCode& status) const {
544     NULL_ON_ERROR(status);
545 
546     if (!(isReserved() || isFunctionCall())) {
547         status = U_INVALID_STATE_ERROR;
548         return nullptr;
549     }
550     U_ASSERT(rator);
551     return &(*rator);
552 }
553 
554 // May return null operand
getOperand() const555 const Operand& Expression::getOperand() const { return rand; }
556 
setOperand(Operand && rAnd)557 Expression::Builder& Expression::Builder::setOperand(Operand&& rAnd) {
558     hasOperand = true;
559     rand = std::move(rAnd);
560     return *this;
561 }
562 
setOperator(Operator && rAtor)563 Expression::Builder& Expression::Builder::setOperator(Operator&& rAtor) {
564     hasOperator = true;
565     rator = std::move(rAtor);
566     return *this;
567 }
568 
addAttribute(const UnicodeString & k,Operand && v,UErrorCode & status)569 Expression::Builder& Expression::Builder::addAttribute(const UnicodeString& k,
570                                                        Operand&& v,
571                                                        UErrorCode& status) {
572     attributes.add(Option(k, std::move(v)), status);
573     return *this;
574 }
575 
build(UErrorCode & errorCode)576 Expression Expression::Builder::build(UErrorCode& errorCode) {
577     Expression result;
578 
579     if (U_FAILURE(errorCode)) {
580         return result;
581     }
582 
583     if ((!hasOperand || rand.isNull()) && !hasOperator) {
584         errorCode = U_INVALID_STATE_ERROR;
585         return result;
586     }
587 
588     OptionMap attributeMap = attributes.build(errorCode);
589     if (hasOperand && hasOperator) {
590         result = Expression(rator, rand, std::move(attributeMap));
591     } else if (hasOperand && !hasOperator) {
592         result = Expression(rand, std::move(attributeMap));
593     } else {
594         // rator is valid, rand is not valid
595         result = Expression(rator, std::move(attributeMap));
596     }
597     return result;
598 }
599 
Expression()600 Expression::Expression() : rator(std::nullopt) {}
601 
Expression(const Expression & other)602 Expression::Expression(const Expression& other) : rator(other.rator), rand(other.rand), attributes(other.attributes) {}
603 
operator =(Expression other)604 Expression& Expression::operator=(Expression other) noexcept {
605     swap(*this, other);
606     return *this;
607 }
608 
~Builder()609 Expression::Builder::~Builder() {}
610 
~Expression()611 Expression::~Expression() {}
612 
613 // ----------- UnsupportedStatement
614 
Builder(UErrorCode & status)615 UnsupportedStatement::Builder::Builder(UErrorCode& status) {
616     expressions = createUVector(status);
617 }
618 
setKeyword(const UnicodeString & k)619 UnsupportedStatement::Builder& UnsupportedStatement::Builder::setKeyword(const UnicodeString& k) {
620     keyword = k;
621     return *this;
622 }
623 
setBody(Reserved && r)624 UnsupportedStatement::Builder& UnsupportedStatement::Builder::setBody(Reserved&& r) {
625     body.emplace(r);
626     return *this;
627 }
628 
addExpression(Expression && e,UErrorCode & status)629 UnsupportedStatement::Builder& UnsupportedStatement::Builder::addExpression(Expression&& e, UErrorCode& status) {
630     U_ASSERT(expressions != nullptr);
631     if (U_SUCCESS(status)) {
632         Expression* expr = create<Expression>(std::move(e), status);
633         expressions->adoptElement(expr, status);
634     }
635     return *this;
636 }
637 
build(UErrorCode & status) const638 UnsupportedStatement UnsupportedStatement::Builder::build(UErrorCode& status) const {
639     if (U_SUCCESS(status)) {
640         U_ASSERT(expressions != nullptr);
641         if (keyword.length() <= 0) {
642             status = U_ILLEGAL_ARGUMENT_ERROR;
643         } else if (expressions->size() < 1) {
644             status = U_ILLEGAL_ARGUMENT_ERROR;
645         } else {
646             return UnsupportedStatement(keyword, body, *expressions, status);
647         }
648     }
649     return {};
650 }
651 
getBody(UErrorCode & errorCode) const652 const Reserved* UnsupportedStatement::getBody(UErrorCode& errorCode) const {
653     if (U_SUCCESS(errorCode)) {
654         if (body.has_value()) {
655             return &(*body);
656         }
657         errorCode = U_ILLEGAL_ARGUMENT_ERROR;
658     }
659     return nullptr;
660 }
661 
UnsupportedStatement(const UnicodeString & k,const std::optional<Reserved> & r,const UVector & es,UErrorCode & status)662 UnsupportedStatement::UnsupportedStatement(const UnicodeString& k,
663                                            const std::optional<Reserved>& r,
664                                            const UVector& es,
665                                            UErrorCode& status)
666     : keyword(k), body(r), expressionsLen(es.size()) {
667     CHECK_ERROR(status);
668 
669     U_ASSERT(expressionsLen >= 1);
670     Expression* result = copyVectorToArray<Expression>(es, status);
671     CHECK_ERROR(status);
672     expressions.adoptInstead(result);
673 }
674 
UnsupportedStatement(const UnsupportedStatement & other)675 UnsupportedStatement::UnsupportedStatement(const UnsupportedStatement& other) {
676     keyword = other.keyword;
677     body = other.body;
678     expressionsLen = other.expressionsLen;
679     U_ASSERT(expressionsLen > 0);
680     UErrorCode localErrorCode = U_ZERO_ERROR;
681     expressions.adoptInstead(copyArray(other.expressions.getAlias(), expressionsLen, localErrorCode));
682     if (U_FAILURE(localErrorCode)) {
683         expressionsLen = 0;
684     }
685 }
686 
operator =(UnsupportedStatement other)687 UnsupportedStatement& UnsupportedStatement::operator=(UnsupportedStatement other) noexcept {
688     swap(*this, other);
689     return *this;
690 }
691 
~Builder()692 UnsupportedStatement::Builder::~Builder() {
693     if (expressions != nullptr) {
694         delete expressions;
695     }
696 }
697 
~UnsupportedStatement()698 UnsupportedStatement::~UnsupportedStatement() {}
699 // ----------- PatternPart
700 
701 // PatternPart needs a copy constructor in order to make Pattern deeply copyable
702 // If !isRawText and the copy of the other expression fails,
703 // then isBogus() will be true for this PatternPart
PatternPart(const PatternPart & other)704 PatternPart::PatternPart(const PatternPart& other) : piece(other.piece) {}
705 
contents() const706 const Expression& PatternPart::contents() const {
707     U_ASSERT(isExpression());
708     return *std::get_if<Expression>(&piece);
709 }
710 
asMarkup() const711 const Markup& PatternPart::asMarkup() const {
712     U_ASSERT(isMarkup());
713     return *std::get_if<Markup>(&piece);
714 }
715 
716 // Precondition: isText();
asText() const717 const UnicodeString& PatternPart::asText() const {
718     U_ASSERT(isText());
719     return *std::get_if<UnicodeString>(&piece);
720 }
721 
operator =(PatternPart other)722 PatternPart& PatternPart::operator=(PatternPart other) noexcept {
723     swap(*this, other);
724     return *this;
725 }
726 
~PatternPart()727 PatternPart::~PatternPart() {}
728 
729 // ---------------- Pattern
730 
Pattern(const UVector & ps,UErrorCode & status)731 Pattern::Pattern(const UVector& ps, UErrorCode& status) : len(ps.size()) {
732     if (U_FAILURE(status)) {
733         return;
734     }
735     PatternPart* result = copyVectorToArray<PatternPart>(ps, status);
736     CHECK_ERROR(status);
737     parts.adoptInstead(result);
738 }
739 
740 // Copy constructor
Pattern(const Pattern & other)741 Pattern::Pattern(const Pattern& other) : len(other.len) {
742     U_ASSERT(!other.bogus);
743     UErrorCode localErrorCode = U_ZERO_ERROR;
744     if (len == 0) {
745         parts.adoptInstead(nullptr);
746     } else {
747         parts.adoptInstead(copyArray(other.parts.getAlias(), len, localErrorCode));
748     }
749     if (U_FAILURE(localErrorCode)) {
750         bogus = true;
751     }
752 }
753 
numParts() const754 int32_t Pattern::numParts() const {
755     U_ASSERT(!bogus);
756     return len;
757 }
758 
getPart(int32_t i) const759 const PatternPart& Pattern::getPart(int32_t i) const {
760     U_ASSERT(!bogus && i < numParts());
761     return parts[i];
762 }
763 
Builder(UErrorCode & status)764 Pattern::Builder::Builder(UErrorCode& status) {
765     parts = createUVector(status);
766 }
767 
build(UErrorCode & status) const768 Pattern Pattern::Builder::build(UErrorCode& status) const noexcept {
769     if (U_FAILURE(status)) {
770         return {};
771     }
772     U_ASSERT(parts != nullptr);
773     return Pattern(*parts, status);
774 }
775 
add(Expression && part,UErrorCode & status)776 Pattern::Builder& Pattern::Builder::add(Expression&& part, UErrorCode& status) noexcept {
777     U_ASSERT(parts != nullptr);
778     if (U_SUCCESS(status)) {
779         PatternPart* l = create<PatternPart>(PatternPart(std::move(part)), status);
780         parts->adoptElement(l, status);
781     }
782     return *this;
783 }
784 
add(Markup && part,UErrorCode & status)785 Pattern::Builder& Pattern::Builder::add(Markup&& part, UErrorCode& status) noexcept {
786     U_ASSERT(parts != nullptr);
787     if (U_SUCCESS(status)) {
788         PatternPart* l = create<PatternPart>(PatternPart(std::move(part)), status);
789         parts->adoptElement(l, status);
790     }
791     return *this;
792 }
793 
add(UnicodeString && part,UErrorCode & status)794 Pattern::Builder& Pattern::Builder::add(UnicodeString&& part, UErrorCode& status) noexcept {
795     U_ASSERT(parts != nullptr);
796     if (U_SUCCESS(status)) {
797         PatternPart* l = create<PatternPart>(PatternPart(std::move(part)), status);
798         parts->adoptElement(l, status);
799     }
800     return *this;
801 }
802 
operator =(Pattern other)803 Pattern& Pattern::operator=(Pattern other) noexcept {
804     swap(*this, other);
805 
806     return *this;
807 }
808 
~Builder()809 Pattern::Builder::~Builder() {
810     if (parts != nullptr) {
811         delete parts;
812     }
813 }
814 
~Pattern()815 Pattern::~Pattern() {}
816 
817 // ---------------- Binding
818 
getValue() const819 const Expression& Binding::getValue() const {
820     return expr;
821 }
822 
input(UnicodeString && variableName,Expression && rhs,UErrorCode & errorCode)823 /* static */ Binding Binding::input(UnicodeString&& variableName, Expression&& rhs, UErrorCode& errorCode) {
824     Binding b;
825     if (U_SUCCESS(errorCode)) {
826         const Operand& rand = rhs.getOperand();
827         if (!(rand.isVariable() && (rand.asVariable() == variableName))) {
828             errorCode = U_INVALID_STATE_ERROR;
829         } else {
830             const Operator* rator = rhs.getOperator(errorCode);
831             bool hasOperator = U_SUCCESS(errorCode);
832             if (hasOperator && rator->isReserved()) {
833                 errorCode = U_INVALID_STATE_ERROR;
834             } else {
835                 // Clear error code -- the "error" from the absent operator
836                 // is handled
837                 errorCode = U_ZERO_ERROR;
838                 b = Binding(variableName, std::move(rhs));
839                 b.local = false;
840                 if (hasOperator) {
841                     rator = b.getValue().getOperator(errorCode);
842                     U_ASSERT(U_SUCCESS(errorCode));
843                     b.annotation = std::get_if<Callable>(&(rator->contents));
844                 } else {
845                     b.annotation = nullptr;
846                 }
847                 U_ASSERT(!hasOperator || b.annotation != nullptr);
848             }
849         }
850     }
851     return b;
852 }
853 
getOptionsInternal() const854 const OptionMap& Binding::getOptionsInternal() const {
855     U_ASSERT(annotation != nullptr);
856     return annotation->getOptions();
857 }
858 
updateAnnotation()859 void Binding::updateAnnotation() {
860     UErrorCode localErrorCode = U_ZERO_ERROR;
861     const Operator* rator = expr.getOperator(localErrorCode);
862     if (U_FAILURE(localErrorCode) || rator->isReserved()) {
863         return;
864     }
865     U_ASSERT(U_SUCCESS(localErrorCode) && !rator->isReserved());
866     annotation = std::get_if<Callable>(&(rator->contents));
867 }
868 
Binding(const Binding & other)869 Binding::Binding(const Binding& other) : var(other.var), expr(other.expr), local(other.local) {
870     updateAnnotation();
871 }
872 
operator =(Binding other)873 Binding& Binding::operator=(Binding other) noexcept {
874     swap(*this, other);
875     return *this;
876 }
877 
~Binding()878 Binding::~Binding() {}
879 
880 // --------------- Variant
881 
operator =(Variant other)882 Variant& Variant::operator=(Variant other) noexcept {
883     swap(*this, other);
884     return *this;
885 }
886 
Variant(const Variant & other)887 Variant::Variant(const Variant& other) : k(other.k), p(other.p) {}
888 
~Variant()889 Variant::~Variant() {}
890 
891 // ------------- Matcher
892 
operator =(Matcher other)893 Matcher& Matcher::operator=(Matcher other) {
894     swap(*this, other);
895     return *this;
896 }
897 
Matcher(const Matcher & other)898 Matcher::Matcher(const Matcher& other) {
899     U_ASSERT(!other.bogus);
900     numSelectors = other.numSelectors;
901     numVariants = other.numVariants;
902     UErrorCode localErrorCode = U_ZERO_ERROR;
903     selectors.adoptInstead(copyArray<Expression>(other.selectors.getAlias(),
904                                                  numSelectors,
905                                                  localErrorCode));
906     variants.adoptInstead(copyArray<Variant>(other.variants.getAlias(),
907                                              numVariants,
908                                              localErrorCode));
909     if (U_FAILURE(localErrorCode)) {
910         bogus = true;
911     }
912 }
913 
Matcher(Expression * ss,int32_t ns,Variant * vs,int32_t nv)914 Matcher::Matcher(Expression* ss, int32_t ns, Variant* vs, int32_t nv)
915     : selectors(ss), numSelectors(ns), variants(vs), numVariants(nv) {}
916 
~Matcher()917 Matcher::~Matcher() {}
918 
919 // --------------- MFDataModel
920 
getPattern() const921 const Pattern& MFDataModel::getPattern() const {
922     if (std::holds_alternative<Matcher>(body)) {
923         // Return reference to empty pattern if this is a selectors message
924         return empty;
925     }
926     return *(std::get_if<Pattern>(&body));
927 }
928 
getLocalVariablesInternal() const929 const Binding* MFDataModel::getLocalVariablesInternal() const {
930     U_ASSERT(!bogus);
931     U_ASSERT(bindings.isValid());
932     return bindings.getAlias();
933 }
934 
getSelectorsInternal() const935 const Expression* MFDataModel::getSelectorsInternal() const {
936     U_ASSERT(!bogus);
937     U_ASSERT(!hasPattern());
938     return std::get_if<Matcher>(&body)->selectors.getAlias();
939 }
940 
getVariantsInternal() const941 const Variant* MFDataModel::getVariantsInternal() const {
942     U_ASSERT(!bogus);
943     U_ASSERT(!hasPattern());
944     return std::get_if<Matcher>(&body)->variants.getAlias();
945 }
946 
getUnsupportedStatementsInternal() const947 const UnsupportedStatement* MFDataModel::getUnsupportedStatementsInternal() const {
948     U_ASSERT(!bogus);
949     U_ASSERT(unsupportedStatements.isValid());
950     return unsupportedStatements.getAlias();
951 }
952 
953 
Builder(UErrorCode & status)954 MFDataModel::Builder::Builder(UErrorCode& status) {
955     bindings = createUVector(status);
956     unsupportedStatements = createUVector(status);
957 }
958 
959 // Invalidate pattern and create selectors/variants if necessary
buildSelectorsMessage(UErrorCode & status)960 void MFDataModel::Builder::buildSelectorsMessage(UErrorCode& status) {
961     CHECK_ERROR(status);
962 
963     if (hasPattern) {
964         selectors = createUVector(status);
965         variants = createUVector(status);
966         hasPattern = false;
967     }
968     hasPattern = false;
969     hasSelectors = true;
970 }
971 
checkDuplicate(const VariableName & var,UErrorCode & status) const972 void MFDataModel::Builder::checkDuplicate(const VariableName& var, UErrorCode& status) const {
973     CHECK_ERROR(status);
974 
975     // This means that handling declarations is quadratic in the number of variables,
976     // but the `UVector` of locals in the builder could be changed to a `Hashtable`
977     // if that's a problem
978     // Note: this also doesn't check _all_ duplicate declaration errors,
979     // see MessageFormatter::Checker::checkDeclarations()
980     for (int32_t i = 0; i < bindings->size(); i++) {
981         if ((static_cast<Binding*>(bindings->elementAt(i)))->getVariable() == var) {
982             status = U_MF_DUPLICATE_DECLARATION_ERROR;
983             break;
984         }
985     }
986 }
987 
addBinding(Binding && b,UErrorCode & status)988 MFDataModel::Builder& MFDataModel::Builder::addBinding(Binding&& b, UErrorCode& status) {
989     if (U_SUCCESS(status)) {
990         U_ASSERT(bindings != nullptr);
991         checkDuplicate(b.getVariable(), status);
992         UErrorCode savedStatus = status;
993         if (status == U_MF_DUPLICATE_DECLARATION_ERROR) {
994             // Want to add the binding anyway even if it's a duplicate
995             status = U_ZERO_ERROR;
996         }
997         bindings->adoptElement(create<Binding>(std::move(b), status), status);
998         if (U_SUCCESS(status) || savedStatus == U_MF_DUPLICATE_DECLARATION_ERROR) {
999             status = savedStatus;
1000         }
1001     }
1002     return *this;
1003 }
1004 
addUnsupportedStatement(UnsupportedStatement && s,UErrorCode & status)1005 MFDataModel::Builder& MFDataModel::Builder::addUnsupportedStatement(UnsupportedStatement&& s, UErrorCode& status) {
1006     if (U_SUCCESS(status)) {
1007         U_ASSERT(unsupportedStatements != nullptr);
1008         unsupportedStatements->adoptElement(create<UnsupportedStatement>(std::move(s), status), status);
1009     }
1010     return *this;
1011 }
1012 
1013 /*
1014   selector must be non-null
1015 */
addSelector(Expression && selector,UErrorCode & status)1016 MFDataModel::Builder& MFDataModel::Builder::addSelector(Expression&& selector, UErrorCode& status) noexcept {
1017     THIS_ON_ERROR(status);
1018 
1019     buildSelectorsMessage(status);
1020     U_ASSERT(selectors != nullptr);
1021     selectors->adoptElement(create<Expression>(std::move(selector), status), status);
1022 
1023     return *this;
1024 }
1025 
1026 /*
1027   `pattern` must be non-null
1028 */
addVariant(SelectorKeys && keys,Pattern && pattern,UErrorCode & errorCode)1029 MFDataModel::Builder& MFDataModel::Builder::addVariant(SelectorKeys&& keys, Pattern&& pattern, UErrorCode& errorCode) noexcept {
1030     buildSelectorsMessage(errorCode);
1031     Variant* v = create<Variant>(Variant(std::move(keys), std::move(pattern)), errorCode);
1032     if (U_SUCCESS(errorCode)) {
1033         variants->adoptElement(v, errorCode);
1034     }
1035     return *this;
1036 }
1037 
setPattern(Pattern && pat)1038 MFDataModel::Builder& MFDataModel::Builder::setPattern(Pattern&& pat) {
1039     pattern = std::move(pat);
1040     hasPattern = true;
1041     hasSelectors = false;
1042     // Invalidate variants
1043     if (variants != nullptr) {
1044         variants->removeAllElements();
1045     }
1046     return *this;
1047 }
1048 
MFDataModel(const MFDataModel & other)1049 MFDataModel::MFDataModel(const MFDataModel& other) : body(Pattern()) {
1050     U_ASSERT(!other.bogus);
1051 
1052     UErrorCode localErrorCode = U_ZERO_ERROR;
1053 
1054     if (other.hasPattern()) {
1055         //        body.emplace<Pattern>(Pattern(*std::get_if<Pattern>(&other.body)));
1056         body = *std::get_if<Pattern>(&other.body);
1057     } else {
1058         const Expression* otherSelectors = other.getSelectorsInternal();
1059         const Variant* otherVariants = other.getVariantsInternal();
1060         int32_t numSelectors = other.numSelectors();
1061         int32_t numVariants = other.numVariants();
1062         Expression* copiedSelectors = copyArray(otherSelectors, numSelectors, localErrorCode);
1063         Variant* copiedVariants = copyArray(otherVariants, numVariants, localErrorCode);
1064         if (U_FAILURE(localErrorCode)) {
1065             bogus = true;
1066             return;
1067         }
1068         //        body.emplace<Matcher>(Matcher(copiedSelectors, numSelectors, copiedVariants, numVariants));
1069         body = Matcher(copiedSelectors, numSelectors, copiedVariants, numVariants);
1070     }
1071 
1072     bindingsLen = other.bindingsLen;
1073     bindings.adoptInstead(copyArray(other.bindings.getAlias(), bindingsLen, localErrorCode));
1074     if (U_FAILURE(localErrorCode)) {
1075         bogus = true;
1076     }
1077     unsupportedStatementsLen = other.unsupportedStatementsLen;
1078     unsupportedStatements.adoptInstead(copyArray(other.unsupportedStatements.getAlias(), unsupportedStatementsLen, localErrorCode));
1079     if (U_FAILURE(localErrorCode)) {
1080         bogus = true;
1081     }
1082 }
1083 
MFDataModel(const MFDataModel::Builder & builder,UErrorCode & errorCode)1084 MFDataModel::MFDataModel(const MFDataModel::Builder& builder, UErrorCode& errorCode) noexcept : body(Pattern()) {
1085     CHECK_ERROR(errorCode);
1086 
1087     if (builder.hasPattern) {
1088         body.emplace<Pattern>(builder.pattern);
1089     } else {
1090         U_ASSERT(builder.variants != nullptr);
1091         U_ASSERT(builder.selectors != nullptr);
1092         int32_t numVariants = builder.variants->size();
1093         int32_t numSelectors = builder.selectors->size();
1094         Variant* variants = copyVectorToArray<Variant>(*builder.variants, errorCode);
1095         Expression* selectors = copyVectorToArray<Expression>(*builder.selectors, errorCode);
1096         if (U_FAILURE(errorCode)) {
1097             bogus = true;
1098             return;
1099         }
1100         body.emplace<Matcher>(Matcher(selectors, numSelectors, variants, numVariants));
1101     }
1102 
1103     U_ASSERT(builder.bindings != nullptr);
1104     bindingsLen = builder.bindings->size();
1105     bindings.adoptInstead(copyVectorToArray<Binding>(*builder.bindings, errorCode));
1106     unsupportedStatementsLen = builder.unsupportedStatements->size();
1107     unsupportedStatements.adoptInstead(copyVectorToArray<UnsupportedStatement>(*builder.unsupportedStatements, errorCode));
1108     if (U_FAILURE(errorCode)) {
1109         bogus = true;
1110     }
1111 }
1112 
MFDataModel()1113 MFDataModel::MFDataModel() : body(Pattern()) {}
1114 
operator =(MFDataModel other)1115 MFDataModel& MFDataModel::operator=(MFDataModel other) noexcept {
1116     U_ASSERT(!other.bogus);
1117     swap(*this, other);
1118     return *this;
1119 }
1120 
build(UErrorCode & errorCode) const1121 MFDataModel MFDataModel::Builder::build(UErrorCode& errorCode) const noexcept {
1122     if (U_FAILURE(errorCode)) {
1123         return {};
1124     }
1125     if (!hasPattern && !hasSelectors) {
1126         errorCode = U_INVALID_STATE_ERROR;
1127     }
1128     return MFDataModel(*this, errorCode);
1129 }
1130 
~MFDataModel()1131 MFDataModel::~MFDataModel() {}
~Builder()1132 MFDataModel::Builder::~Builder() {
1133     if (selectors != nullptr) {
1134         delete selectors;
1135     }
1136     if (variants != nullptr) {
1137         delete variants;
1138     }
1139     if (bindings != nullptr) {
1140         delete bindings;
1141     }
1142     if (unsupportedStatements != nullptr) {
1143         delete unsupportedStatements;
1144     }
1145 }
1146 } // namespace message2
1147 
1148 U_NAMESPACE_END
1149 
1150 #endif /* #if !UCONFIG_NO_MF2 */
1151 
1152 #endif /* #if !UCONFIG_NO_FORMATTING */
1153