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