tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */