messageformat2_data_model.cpp (25931B)
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_NORMALIZATION 7 8 #if !UCONFIG_NO_FORMATTING 9 10 #if !UCONFIG_NO_MF2 11 12 #include "unicode/messageformat2_data_model.h" 13 #include "messageformat2_allocation.h" 14 #include "messageformat2_macros.h" 15 #include "uvector.h" 16 17 U_NAMESPACE_BEGIN 18 19 namespace message2 { 20 21 namespace data_model { 22 23 // Implementation 24 25 //------------------ SelectorKeys 26 27 const Key* SelectorKeys::getKeysInternal() const { 28 return keys.getAlias(); 29 } 30 31 // Lexically order key lists 32 bool SelectorKeys::operator<(const SelectorKeys& other) const { 33 // Handle key lists of different sizes first -- 34 // this case does have to be handled (even though it would 35 // reflect a data model error) because of the need to produce 36 // partial output 37 if (len < other.len) { 38 return true; 39 } 40 if (len > other.len) { 41 return false; 42 } 43 44 for (int32_t i = 0; i < len; i++) { 45 if (keys[i] < other.keys[i]) { 46 return true; 47 } 48 if (!(keys[i] == other.keys[i])) { 49 return false; 50 } 51 } 52 // If we've reached here, all keys must be equal 53 return false; 54 } 55 56 SelectorKeys::Builder::Builder(UErrorCode& status) { 57 keys = createUVector(status); 58 } 59 60 SelectorKeys::Builder& SelectorKeys::Builder::add(Key&& key, UErrorCode& status) noexcept { 61 U_ASSERT(keys != nullptr); 62 if (U_SUCCESS(status)) { 63 Key* k = create<Key>(std::move(key), status); 64 keys->adoptElement(k, status); 65 } 66 return *this; 67 } 68 69 SelectorKeys SelectorKeys::Builder::build(UErrorCode& status) const { 70 if (U_FAILURE(status)) { 71 return {}; 72 } 73 U_ASSERT(keys != nullptr); 74 return SelectorKeys(*keys, status); 75 } 76 77 SelectorKeys::Builder::~Builder() { 78 if (keys != nullptr) { 79 delete keys; 80 } 81 } 82 83 SelectorKeys::SelectorKeys(const UVector& ks, UErrorCode& status) : len(ks.size()) { 84 Key* result = copyVectorToArray<Key>(ks, status); 85 if (U_FAILURE(status)) { 86 return; 87 } 88 keys.adoptInstead(result); 89 } 90 91 SelectorKeys& SelectorKeys::operator=(SelectorKeys other) noexcept { 92 swap(*this, other); 93 return *this; 94 } 95 96 SelectorKeys::SelectorKeys(const SelectorKeys& other) : len(other.len) { 97 UErrorCode localErrorCode = U_ZERO_ERROR; 98 if (len != 0) { 99 keys.adoptInstead(copyArray(other.keys.getAlias(), len, localErrorCode)); 100 } 101 if (U_FAILURE(localErrorCode)) { 102 len = 0; 103 } 104 } 105 106 SelectorKeys::~SelectorKeys() { 107 len = 0; 108 } 109 110 //------------------ Literal 111 112 bool Literal::operator<(const Literal& other) const { 113 // Ignore quoting for the purposes of ordering 114 return contents < other.contents; 115 } 116 117 bool Literal::operator==(const Literal& other) const { 118 // Ignore quoting for the purposes of ordering 119 return contents == other.contents; 120 } 121 122 UnicodeString Literal::quoted() const { 123 UnicodeString result(PIPE); 124 result += unquoted(); 125 result += PIPE; 126 return result; 127 } 128 129 const UnicodeString& Literal::unquoted() const { return contents; } 130 131 Literal& Literal::operator=(Literal other) noexcept { 132 swap(*this, other); 133 134 return *this; 135 } 136 137 Literal::~Literal() { 138 thisIsQuoted = false; 139 } 140 141 //------------------ Operand 142 143 Operand::Operand(const Operand& other) : contents(other.contents) {} 144 145 Operand& Operand::operator=(Operand other) noexcept { 146 swap(*this, other); 147 148 return *this; 149 } 150 151 UBool Operand::isVariable() const { 152 return (contents.has_value() && std::holds_alternative<VariableName>(*contents)); 153 } 154 UBool Operand::isLiteral() const { 155 return (contents.has_value() && std::holds_alternative<Literal>(*contents)); 156 } 157 UBool Operand::isNull() const { return !contents.has_value(); } 158 159 const Literal& Operand::asLiteral() const { 160 U_ASSERT(isLiteral()); 161 return *(std::get_if<Literal>(&(*contents))); 162 } 163 164 const VariableName& Operand::asVariable() const { 165 U_ASSERT(isVariable()); 166 return *(std::get_if<VariableName>(&(*contents))); 167 } 168 169 Operand::~Operand() {} 170 171 //---------------- Key 172 173 Key& Key::operator=(Key other) noexcept { 174 swap(*this, other); 175 return *this; 176 } 177 178 bool Key::operator<(const Key& other) const { 179 // Arbitrarily treat * as greater than all concrete keys 180 if (isWildcard()) { 181 return false; 182 } 183 if (other.isWildcard()) { 184 return true; 185 } 186 return (asLiteral() < other.asLiteral()); 187 } 188 189 bool Key::operator==(const Key& other) const { 190 if (isWildcard()) { 191 return other.isWildcard(); 192 } 193 if (other.isWildcard()) { 194 return false; 195 } 196 return (asLiteral() == other.asLiteral()); 197 } 198 199 const Literal& Key::asLiteral() const { 200 U_ASSERT(!isWildcard()); 201 return *contents; 202 } 203 204 Key::~Key() {} 205 206 //------------------------ Operator 207 208 OptionMap::OptionMap(const UVector& opts, UErrorCode& status) : len(opts.size()) { 209 Option* result = copyVectorToArray<Option>(opts, status); 210 if (U_FAILURE(status)) { 211 bogus = true; 212 return; 213 } 214 options.adoptInstead(result); 215 bogus = false; 216 } 217 218 OptionMap::OptionMap(const OptionMap& other) : len(other.len) { 219 U_ASSERT(!other.bogus); 220 if (len == 0) { 221 bogus = false; 222 return; 223 } 224 UErrorCode localErrorCode = U_ZERO_ERROR; 225 Option* result = copyArray(other.options.getAlias(), len, localErrorCode); 226 if (U_FAILURE(localErrorCode)) { 227 bogus = true; 228 return; 229 } 230 bogus = false; 231 options.adoptInstead(result); 232 } 233 234 OptionMap& OptionMap::operator=(OptionMap other) { 235 swap(*this, other); 236 return *this; 237 } 238 239 const Option& OptionMap::getOption(int32_t i, UErrorCode& status) const { 240 if (U_FAILURE(status) || bogus) { 241 if (bogus) { 242 status = U_MEMORY_ALLOCATION_ERROR; 243 } 244 } else { 245 U_ASSERT(options.isValid()); 246 U_ASSERT(i < len); 247 } 248 return options[i]; 249 } 250 251 int32_t OptionMap::size() const { 252 U_ASSERT(options.isValid() || len == 0); 253 return len; 254 } 255 256 OptionMap::~OptionMap() {} 257 258 OptionMap OptionMap::Builder::build(UErrorCode& status) { 259 return OptionMap(*options, status); 260 } 261 262 OptionMap::Builder::Builder(UErrorCode& status) { 263 options = createStringUVector(status); 264 } 265 266 OptionMap::Builder::Builder(OptionMap::Builder&& other) { 267 checkDuplicates = other.checkDuplicates; 268 options = other.options; 269 other.options = nullptr; 270 } 271 272 OptionMap::Builder& OptionMap::Builder::operator=(OptionMap::Builder other) noexcept { 273 swap(*this, other); 274 return *this; 275 } 276 277 /* static */ OptionMap::Builder OptionMap::Builder::attributes(UErrorCode& status) { 278 Builder b(status); 279 // The same code is re-used for representing attributes and options. 280 // Duplicate attributes are allowed, while duplicate options are disallowed. 281 b.checkDuplicates = false; 282 return b; 283 } 284 285 static UBool hasOptionNamed(const UVector& v, const UnicodeString& s) { 286 for (int32_t i = 0; i < v.size(); i++) { 287 const Option* opt = static_cast<Option*>(v[i]); 288 U_ASSERT(opt != nullptr); 289 if (opt->getName() == s) { 290 return true; 291 } 292 } 293 return false; 294 } 295 296 OptionMap::Builder& OptionMap::Builder::add(Option&& opt, UErrorCode& status) { 297 THIS_ON_ERROR(status); 298 299 // If the option name is already in the map, emit a data model error 300 if (checkDuplicates && hasOptionNamed(*options, opt.getName())) { 301 status = U_MF_DUPLICATE_OPTION_NAME_ERROR; 302 } else { 303 Option* newOption = create<Option>(std::move(opt), status); 304 options->adoptElement(newOption, status); 305 } 306 return *this; 307 } 308 309 OptionMap::Builder::~Builder() { 310 if (options != nullptr) { 311 delete options; 312 } 313 } 314 315 const OptionMap& Operator::getOptionsInternal() const { 316 return options; 317 } 318 319 Option::Option(const Option& other): name(other.name), rand(other.rand) {} 320 321 Option& Option::operator=(Option other) noexcept { 322 swap(*this, other); 323 return *this; 324 } 325 326 Option::~Option() {} 327 328 Operator::Builder::Builder(UErrorCode& status) : options(OptionMap::Builder(status)) {} 329 330 Operator::Builder& Operator::Builder::setFunctionName(FunctionName&& func) { 331 functionName = std::move(func); 332 return *this; 333 } 334 335 const FunctionName& Operator::getFunctionName() const { 336 return name; 337 } 338 339 Operator::Builder& Operator::Builder::addOption(const UnicodeString &key, Operand&& value, UErrorCode& errorCode) noexcept { 340 THIS_ON_ERROR(errorCode); 341 342 options.add(Option(key, std::move(value)), errorCode); 343 return *this; 344 } 345 346 Operator Operator::Builder::build(UErrorCode& errorCode) { 347 return Operator(functionName, options.build(errorCode)); 348 } 349 350 Operator::Operator(const Operator& other) noexcept 351 : name(other.name), options(other.options) {} 352 353 Operator& Operator::operator=(Operator other) noexcept { 354 swap(*this, other); 355 return *this; 356 } 357 358 // Function call 359 360 Operator::Operator(const FunctionName& f, const OptionMap& opts) : name(f), options(opts) {} 361 362 Operator::Builder::~Builder() {} 363 364 Operator::~Operator() {} 365 366 // ------------ Markup 367 368 Markup::Builder::Builder(UErrorCode& status) 369 : options(OptionMap::Builder(status)), attributes(OptionMap::Builder::attributes(status)) {} 370 371 Markup::Markup(UMarkupType ty, UnicodeString n, OptionMap&& o, OptionMap&& a) 372 : type(ty), name(n), options(std::move(o)), attributes(std::move(a)) {} 373 374 Markup::Builder& Markup::Builder::addOption(const UnicodeString &key, 375 Operand&& value, 376 UErrorCode& errorCode) { 377 options.add(Option(key, std::move(value)), errorCode); 378 return *this; 379 } 380 381 Markup::Builder& Markup::Builder::addAttribute(const UnicodeString &key, 382 Operand&& value, 383 UErrorCode& errorCode) { 384 attributes.add(Option(key, std::move(value)), errorCode); 385 return *this; 386 } 387 388 Markup Markup::Builder::build(UErrorCode& errorCode) { 389 Markup result; 390 391 if (U_FAILURE(errorCode)) { 392 return result; 393 } 394 395 if (type == UMARKUP_COUNT || name.length() == 0) { 396 // One of `setOpen()`, `setClose()`, or `setStandalone()` 397 // must be called before calling build() 398 // setName() must be called before calling build() 399 errorCode = U_INVALID_STATE_ERROR; 400 } else { 401 result = Markup(type, 402 name, 403 options.build(errorCode), 404 attributes.build(errorCode)); 405 } 406 return result; 407 } 408 409 Markup::Builder::~Builder() {} 410 411 Markup::~Markup() {} 412 413 // ------------ Expression 414 415 Expression::Builder::Builder(UErrorCode& status) 416 : attributes(OptionMap::Builder::attributes(status)) {} 417 418 UBool Expression::isStandaloneAnnotation() const { 419 return rand.isNull(); 420 } 421 422 // Returns true for function calls with operands as well as 423 // standalone annotations. 424 UBool Expression::isFunctionCall() const { 425 return rator.has_value(); 426 } 427 428 const Operator* Expression::getOperator(UErrorCode& status) const { 429 NULL_ON_ERROR(status); 430 431 if (!isFunctionCall()) { 432 status = U_INVALID_STATE_ERROR; 433 return nullptr; 434 } 435 U_ASSERT(rator); 436 return &(*rator); 437 } 438 439 // May return null operand 440 const Operand& Expression::getOperand() const { return rand; } 441 442 Expression::Builder& Expression::Builder::setOperand(Operand&& rAnd) { 443 hasOperand = true; 444 rand = std::move(rAnd); 445 return *this; 446 } 447 448 Expression::Builder& Expression::Builder::setOperator(Operator&& rAtor) { 449 hasOperator = true; 450 rator = std::move(rAtor); 451 return *this; 452 } 453 454 Expression::Builder& Expression::Builder::addAttribute(const UnicodeString& k, 455 Operand&& v, 456 UErrorCode& status) { 457 attributes.add(Option(k, std::move(v)), status); 458 return *this; 459 } 460 461 Expression Expression::Builder::build(UErrorCode& errorCode) { 462 Expression result; 463 464 if (U_FAILURE(errorCode)) { 465 return result; 466 } 467 468 if ((!hasOperand || rand.isNull()) && !hasOperator) { 469 errorCode = U_INVALID_STATE_ERROR; 470 return result; 471 } 472 473 OptionMap attributeMap = attributes.build(errorCode); 474 if (hasOperand && hasOperator) { 475 result = Expression(rator, rand, std::move(attributeMap)); 476 } else if (hasOperand && !hasOperator) { 477 result = Expression(rand, std::move(attributeMap)); 478 } else { 479 // rator is valid, rand is not valid 480 result = Expression(rator, std::move(attributeMap)); 481 } 482 return result; 483 } 484 485 Expression::Expression() : rator(std::nullopt) {} 486 487 Expression::Expression(const Expression& other) : rator(other.rator), rand(other.rand), attributes(other.attributes) {} 488 489 Expression& Expression::operator=(Expression other) noexcept { 490 swap(*this, other); 491 return *this; 492 } 493 494 Expression::Builder::~Builder() {} 495 496 Expression::~Expression() {} 497 498 // ----------- PatternPart 499 500 // PatternPart needs a copy constructor in order to make Pattern deeply copyable 501 // If !isRawText and the copy of the other expression fails, 502 // then isBogus() will be true for this PatternPart 503 PatternPart::PatternPart(const PatternPart& other) : piece(other.piece) {} 504 505 const Expression& PatternPart::contents() const { 506 U_ASSERT(isExpression()); 507 return *std::get_if<Expression>(&piece); 508 } 509 510 const Markup& PatternPart::asMarkup() const { 511 U_ASSERT(isMarkup()); 512 return *std::get_if<Markup>(&piece); 513 } 514 515 // Precondition: isText(); 516 const UnicodeString& PatternPart::asText() const { 517 U_ASSERT(isText()); 518 return *std::get_if<UnicodeString>(&piece); 519 } 520 521 PatternPart& PatternPart::operator=(PatternPart other) noexcept { 522 swap(*this, other); 523 return *this; 524 } 525 526 PatternPart::~PatternPart() {} 527 528 // ---------------- Pattern 529 530 Pattern::Pattern(const UVector& ps, UErrorCode& status) : len(ps.size()) { 531 if (U_FAILURE(status)) { 532 return; 533 } 534 PatternPart* result = copyVectorToArray<PatternPart>(ps, status); 535 CHECK_ERROR(status); 536 parts.adoptInstead(result); 537 } 538 539 // Copy constructor 540 Pattern::Pattern(const Pattern& other) : len(other.len) { 541 U_ASSERT(!other.bogus); 542 UErrorCode localErrorCode = U_ZERO_ERROR; 543 if (len == 0) { 544 parts.adoptInstead(nullptr); 545 } else { 546 parts.adoptInstead(copyArray(other.parts.getAlias(), len, localErrorCode)); 547 } 548 if (U_FAILURE(localErrorCode)) { 549 bogus = true; 550 } 551 } 552 553 int32_t Pattern::numParts() const { 554 U_ASSERT(!bogus); 555 return len; 556 } 557 558 const PatternPart& Pattern::getPart(int32_t i) const { 559 U_ASSERT(!bogus && i < numParts()); 560 return parts[i]; 561 } 562 563 Pattern::Builder::Builder(UErrorCode& status) { 564 parts = createUVector(status); 565 } 566 567 Pattern Pattern::Builder::build(UErrorCode& status) const noexcept { 568 if (U_FAILURE(status)) { 569 return {}; 570 } 571 U_ASSERT(parts != nullptr); 572 return Pattern(*parts, status); 573 } 574 575 Pattern::Builder& Pattern::Builder::add(Expression&& part, UErrorCode& status) noexcept { 576 U_ASSERT(parts != nullptr); 577 if (U_SUCCESS(status)) { 578 PatternPart* l = create<PatternPart>(PatternPart(std::move(part)), status); 579 parts->adoptElement(l, status); 580 } 581 return *this; 582 } 583 584 Pattern::Builder& Pattern::Builder::add(Markup&& part, UErrorCode& status) noexcept { 585 U_ASSERT(parts != nullptr); 586 if (U_SUCCESS(status)) { 587 PatternPart* l = create<PatternPart>(PatternPart(std::move(part)), status); 588 parts->adoptElement(l, status); 589 } 590 return *this; 591 } 592 593 Pattern::Builder& Pattern::Builder::add(UnicodeString&& part, UErrorCode& status) noexcept { 594 U_ASSERT(parts != nullptr); 595 if (U_SUCCESS(status)) { 596 PatternPart* l = create<PatternPart>(PatternPart(std::move(part)), status); 597 parts->adoptElement(l, status); 598 } 599 return *this; 600 } 601 602 Pattern& Pattern::operator=(Pattern other) noexcept { 603 swap(*this, other); 604 605 return *this; 606 } 607 608 Pattern::Builder::~Builder() { 609 if (parts != nullptr) { 610 delete parts; 611 } 612 } 613 614 Pattern::~Pattern() {} 615 616 // ---------------- Binding 617 618 const Expression& Binding::getValue() const { 619 return expr; 620 } 621 622 /* static */ Binding Binding::input(UnicodeString&& variableName, Expression&& rhs, UErrorCode& errorCode) { 623 Binding b; 624 if (U_SUCCESS(errorCode)) { 625 const Operand& rand = rhs.getOperand(); 626 if (!(rand.isVariable() && (rand.asVariable() == variableName))) { 627 errorCode = U_INVALID_STATE_ERROR; 628 } else { 629 const Operator* rator = rhs.getOperator(errorCode); 630 bool hasOperator = U_SUCCESS(errorCode); 631 // Clear error code -- the "error" from the absent operator 632 // is handled 633 errorCode = U_ZERO_ERROR; 634 b = Binding(variableName, std::move(rhs)); 635 b.local = false; 636 if (hasOperator) { 637 rator = b.getValue().getOperator(errorCode); 638 U_ASSERT(U_SUCCESS(errorCode)); 639 b.annotation = rator; 640 } else { 641 b.annotation = nullptr; 642 } 643 U_ASSERT(!hasOperator || b.annotation != nullptr); 644 } 645 } 646 return b; 647 } 648 649 const OptionMap& Binding::getOptionsInternal() const { 650 U_ASSERT(annotation != nullptr); 651 return annotation->getOptionsInternal(); 652 } 653 654 void Binding::updateAnnotation() { 655 UErrorCode localErrorCode = U_ZERO_ERROR; 656 const Operator* rator = expr.getOperator(localErrorCode); 657 if (U_FAILURE(localErrorCode)) { 658 return; 659 } 660 U_ASSERT(U_SUCCESS(localErrorCode)); 661 annotation = rator; 662 } 663 664 Binding::Binding(const Binding& other) : var(other.var), expr(other.expr), local(other.local) { 665 updateAnnotation(); 666 } 667 668 Binding& Binding::operator=(Binding other) noexcept { 669 swap(*this, other); 670 return *this; 671 } 672 673 Binding::~Binding() {} 674 675 // --------------- Variant 676 677 Variant& Variant::operator=(Variant other) noexcept { 678 swap(*this, other); 679 return *this; 680 } 681 682 Variant::Variant(const Variant& other) : k(other.k), p(other.p) {} 683 684 Variant::~Variant() {} 685 686 // ------------- Matcher 687 688 Matcher& Matcher::operator=(Matcher other) { 689 swap(*this, other); 690 return *this; 691 } 692 693 Matcher::Matcher(const Matcher& other) { 694 U_ASSERT(!other.bogus); 695 numSelectors = other.numSelectors; 696 numVariants = other.numVariants; 697 UErrorCode localErrorCode = U_ZERO_ERROR; 698 selectors.adoptInstead(copyArray<VariableName>(other.selectors.getAlias(), 699 numSelectors, 700 localErrorCode)); 701 variants.adoptInstead(copyArray<Variant>(other.variants.getAlias(), 702 numVariants, 703 localErrorCode)); 704 if (U_FAILURE(localErrorCode)) { 705 bogus = true; 706 } 707 } 708 709 Matcher::Matcher(VariableName* ss, int32_t ns, Variant* vs, int32_t nv) 710 : selectors(ss), numSelectors(ns), variants(vs), numVariants(nv) {} 711 712 Matcher::~Matcher() {} 713 714 // --------------- MFDataModel 715 716 const Pattern& MFDataModel::getPattern() const { 717 if (std::holds_alternative<Matcher>(body)) { 718 // Return reference to empty pattern if this is a selectors message 719 return empty; 720 } 721 return *(std::get_if<Pattern>(&body)); 722 } 723 724 // Returns nullptr if no bindings 725 const Binding* MFDataModel::getLocalVariablesInternal() const { 726 U_ASSERT(!bogus); 727 U_ASSERT(bindingsLen == 0 || bindings.isValid()); 728 return bindings.getAlias(); 729 } 730 731 const VariableName* MFDataModel::getSelectorsInternal() const { 732 U_ASSERT(!bogus); 733 U_ASSERT(!hasPattern()); 734 return std::get_if<Matcher>(&body)->selectors.getAlias(); 735 } 736 737 const Variant* MFDataModel::getVariantsInternal() const { 738 U_ASSERT(!bogus); 739 U_ASSERT(!hasPattern()); 740 return std::get_if<Matcher>(&body)->variants.getAlias(); 741 } 742 743 MFDataModel::Builder::Builder(UErrorCode& status) { 744 bindings = createUVector(status); 745 } 746 747 // Invalidate pattern and create selectors/variants if necessary 748 void MFDataModel::Builder::buildSelectorsMessage(UErrorCode& status) { 749 CHECK_ERROR(status); 750 751 if (hasPattern) { 752 selectors = createUVector(status); 753 variants = createUVector(status); 754 hasPattern = false; 755 } 756 hasPattern = false; 757 hasSelectors = true; 758 } 759 760 void MFDataModel::Builder::checkDuplicate(const VariableName& var, UErrorCode& status) const { 761 CHECK_ERROR(status); 762 763 // This means that handling declarations is quadratic in the number of variables, 764 // but the `UVector` of locals in the builder could be changed to a `Hashtable` 765 // if that's a problem 766 // Note: this also doesn't check _all_ duplicate declaration errors, 767 // see MessageFormatter::Checker::checkDeclarations() 768 for (int32_t i = 0; i < bindings->size(); i++) { 769 if ((static_cast<Binding*>(bindings->elementAt(i)))->getVariable() == var) { 770 status = U_MF_DUPLICATE_DECLARATION_ERROR; 771 break; 772 } 773 } 774 } 775 776 MFDataModel::Builder& MFDataModel::Builder::addBinding(Binding&& b, UErrorCode& status) { 777 if (U_SUCCESS(status)) { 778 U_ASSERT(bindings != nullptr); 779 checkDuplicate(b.getVariable(), status); 780 UErrorCode savedStatus = status; 781 if (status == U_MF_DUPLICATE_DECLARATION_ERROR) { 782 // Want to add the binding anyway even if it's a duplicate 783 status = U_ZERO_ERROR; 784 } 785 bindings->adoptElement(create<Binding>(std::move(b), status), status); 786 if (U_SUCCESS(status) || savedStatus == U_MF_DUPLICATE_DECLARATION_ERROR) { 787 status = savedStatus; 788 } 789 } 790 return *this; 791 } 792 793 MFDataModel::Builder& MFDataModel::Builder::addSelector(VariableName&& selector, 794 UErrorCode& status) { 795 THIS_ON_ERROR(status); 796 797 buildSelectorsMessage(status); 798 U_ASSERT(selectors != nullptr); 799 selectors->adoptElement(create<VariableName>(std::move(selector), status), status); 800 801 return *this; 802 } 803 804 /* 805 `pattern` must be non-null 806 */ 807 MFDataModel::Builder& MFDataModel::Builder::addVariant(SelectorKeys&& keys, Pattern&& pattern, UErrorCode& errorCode) noexcept { 808 buildSelectorsMessage(errorCode); 809 Variant* v = create<Variant>(Variant(std::move(keys), std::move(pattern)), errorCode); 810 if (U_SUCCESS(errorCode)) { 811 variants->adoptElement(v, errorCode); 812 } 813 return *this; 814 } 815 816 MFDataModel::Builder& MFDataModel::Builder::setPattern(Pattern&& pat) { 817 pattern = std::move(pat); 818 hasPattern = true; 819 hasSelectors = false; 820 // Invalidate variants 821 if (variants != nullptr) { 822 variants->removeAllElements(); 823 } 824 return *this; 825 } 826 827 MFDataModel::MFDataModel(const MFDataModel& other) : body(Pattern()) { 828 U_ASSERT(!other.bogus); 829 830 UErrorCode localErrorCode = U_ZERO_ERROR; 831 832 if (other.hasPattern()) { 833 body = *std::get_if<Pattern>(&other.body); 834 } else { 835 const VariableName* otherSelectors = other.getSelectorsInternal(); 836 const Variant* otherVariants = other.getVariantsInternal(); 837 int32_t numSelectors = other.numSelectors(); 838 int32_t numVariants = other.numVariants(); 839 LocalArray<VariableName> copiedSelectors(copyArray(otherSelectors, numSelectors, localErrorCode), localErrorCode); 840 LocalArray<Variant> copiedVariants(copyArray(otherVariants, numVariants, localErrorCode), localErrorCode); 841 if (U_FAILURE(localErrorCode)) { 842 bogus = true; 843 return; 844 } 845 body = Matcher(copiedSelectors.orphan(), numSelectors, copiedVariants.orphan(), numVariants); 846 } 847 848 bindingsLen = other.bindingsLen; 849 if (bindingsLen > 0) { 850 bindings.adoptInstead(copyArray(other.bindings.getAlias(), bindingsLen, localErrorCode)); 851 } 852 if (U_FAILURE(localErrorCode)) { 853 bogus = true; 854 } 855 } 856 857 MFDataModel::MFDataModel(const MFDataModel::Builder& builder, UErrorCode& errorCode) noexcept : body(Pattern()) { 858 CHECK_ERROR(errorCode); 859 860 if (builder.hasPattern) { 861 body.emplace<Pattern>(builder.pattern); 862 } else { 863 U_ASSERT(builder.variants != nullptr); 864 U_ASSERT(builder.selectors != nullptr); 865 int32_t numVariants = builder.variants->size(); 866 int32_t numSelectors = builder.selectors->size(); 867 LocalArray<Variant> variants(copyVectorToArray<Variant>(*builder.variants, errorCode), errorCode); 868 LocalArray<VariableName> selectors(copyVectorToArray<VariableName>(*builder.selectors, 869 errorCode), 870 errorCode); 871 if (U_FAILURE(errorCode)) { 872 bogus = true; 873 return; 874 } 875 body.emplace<Matcher>(Matcher(selectors.orphan(), numSelectors, variants.orphan(), numVariants)); 876 } 877 878 U_ASSERT(builder.bindings != nullptr); 879 bindingsLen = builder.bindings->size(); 880 if (bindingsLen > 0) { 881 bindings.adoptInstead(copyVectorToArray<Binding>(*builder.bindings, errorCode)); 882 } 883 if (U_FAILURE(errorCode)) { 884 bogus = true; 885 } 886 } 887 888 MFDataModel::MFDataModel() : body(Pattern()) {} 889 890 MFDataModel& MFDataModel::operator=(MFDataModel other) noexcept { 891 U_ASSERT(!other.bogus); 892 swap(*this, other); 893 return *this; 894 } 895 896 MFDataModel MFDataModel::Builder::build(UErrorCode& errorCode) const noexcept { 897 if (U_FAILURE(errorCode)) { 898 return {}; 899 } 900 if (!hasPattern && !hasSelectors) { 901 errorCode = U_INVALID_STATE_ERROR; 902 } 903 return MFDataModel(*this, errorCode); 904 } 905 906 MFDataModel::~MFDataModel() {} 907 MFDataModel::Builder::~Builder() { 908 if (selectors != nullptr) { 909 delete selectors; 910 } 911 if (variants != nullptr) { 912 delete variants; 913 } 914 if (bindings != nullptr) { 915 delete bindings; 916 } 917 } 918 919 } // namespace data_model 920 } // namespace message2 921 922 U_NAMESPACE_END 923 924 #endif /* #if !UCONFIG_NO_MF2 */ 925 926 #endif /* #if !UCONFIG_NO_FORMATTING */ 927 928 #endif /* #if !UCONFIG_NO_NORMALIZATION */