staticbool containsOption(const UVector& opts, const ResolvedFunctionOption& opt) { for (int32_t i = 0; i < opts.size(); i++) { if (static_cast<ResolvedFunctionOption*>(opts[i])->getName()
== opt.getName()) { return true;
}
} returnfalse;
}
// Options in `this` take precedence // `this` can't be used after mergeOptions is called
FunctionOptions FunctionOptions::mergeOptions(FunctionOptions&& other,
UErrorCode& status) {
UVector mergedOptions(status);
mergedOptions.setDeleter(uprv_deleteUObject);
if (U_FAILURE(status)) { return {};
}
// Create a new vector consisting of the options from this `FunctionOptions` for (int32_t i = 0; i < functionOptionsLen; i++) {
mergedOptions.adoptElement(create<ResolvedFunctionOption>(std::move(options[i]), status),
status);
}
// Add each option from `other` that doesn't appear in this `FunctionOptions` for (int i = 0; i < other.functionOptionsLen; i++) { // Note: this is quadratic in the length of `options` if (!containsOption(mergedOptions, other.options[i])) {
mergedOptions.adoptElement(create<ResolvedFunctionOption>(std::move(other.options[i]),
status),
status);
}
}
// `this` cannot be used after calling this method void InternalValue::forceSelection(DynamicErrors& errs, const UnicodeString* keys,
int32_t keysLen,
UnicodeString* prefs,
int32_t& prefsLen,
UErrorCode& errorCode) { if (U_FAILURE(errorCode)) { return;
}
if (!canSelect()) {
errorCode = U_ILLEGAL_ARGUMENT_ERROR; return;
} // Find the argument and complete set of options by traversing `argument`
FunctionOptions opts;
InternalValue* p = this;
FunctionName selectorName = name;
bool operandSelect = false; while (std::holds_alternative<InternalValue*>(p->argument)) { if (p->name != selectorName) { // Can only compose calls to the same selector
errorCode = U_ILLEGAL_ARGUMENT_ERROR; return;
} // Very special case to detect something like: // .local $sel = {1 :integer select=exact} .local $bad = {$sel :integer} .match $bad 1 {{ONE}} * {{operand select {$bad}}} // This can be done better once function composition is fully implemented. if (p != this &&
!p->options.getStringFunctionOption(options::SELECT).isEmpty()
&& (selectorName == functions::NUMBER || selectorName == functions::INTEGER)) { // In this case, we want to call the selector normally but emit a // `bad-option` error, possibly with the outcome of normal-looking output (with relaxed // error handling) and an error (with strict error handling).
operandSelect = true;
} // First argument to mergeOptions takes precedence
opts = opts.mergeOptions(std::move(p->options), errorCode); if (U_FAILURE(errorCode)) { return;
}
InternalValue* next = *std::get_if<InternalValue*>(&p->argument);
p = next;
}
FormattedPlaceholder arg = std::move(*std::get_if<FormattedPlaceholder>(&p->argument));
// This condition can't be checked in the selector. // Effectively, there are two different kinds of "bad option" errors: // one that can be recovered from (used for select=$var) and one that // can't (used for bad digit size options and other cases). // The checking of the recoverable error has to be done here; otherwise, // the "bad option" signaled by the selector implementation would cause // fallback output to be used when formatting the `*` pattern. bool badSelectOption = !checkSelectOption();
selector->selectKey(std::move(arg), std::move(opts),
keys, keysLen,
prefs, prefsLen, errorCode); if (errorCode == U_MF_SELECTOR_ERROR) {
errorCode = U_ZERO_ERROR;
errs.setSelectorError(selectorName, errorCode);
} elseif (errorCode == U_MF_BAD_OPTION) {
errorCode = U_ZERO_ERROR;
errs.setBadOption(selectorName, errorCode);
} elseif (operandSelect || badSelectOption) {
errs.setRecoverableBadOption(selectorName, errorCode); // In this case, only the `*` variant should match
prefsLen = 0;
}
}
bool InternalValue::checkSelectOption() const { if (name != UnicodeString("number") && name != UnicodeString("integer")) { return true;
}
// Per the spec, if the "select" option is present, it must have been // set from a literal
Formattable opt; // Returns false if the `select` option is present and it was not set from a literal
// OK if the option wasn't present if (!options.getFunctionOption(UnicodeString("select"), opt)) { return true;
} // Otherwise, return true if the option was set from a literal return options.wasSetFromLiteral(UnicodeString("select"));
}
// The fallback for a nullary function call is the function name
UnicodeString fallback; if (arg.isNullOperand()) {
fallback = u":";
fallback += name;
} else {
fallback = arg.getFallback();
}
// Very special case for :number select=foo and :integer select=foo // This check can't be done inside the function implementation because // it doesn't have a way to both signal an error and return usable output, // and the spec stipulates that fallback output shouldn't be used in the // case of a bad `select` option to a formatting call. bool badSelect = !checkSelectOption();
// Call the function with the argument
FormattedPlaceholder result = formatter->format(std::move(arg), std::move(options), errorCode); if (U_SUCCESS(errorCode) && errorCode == U_USING_DEFAULT_WARNING) { // Ignore this warning
errorCode = U_ZERO_ERROR;
} if (U_FAILURE(errorCode)) { if (errorCode == U_MF_OPERAND_MISMATCH_ERROR) {
errorCode = U_ZERO_ERROR;
errs.setOperandMismatchError(name, errorCode);
} elseif (errorCode == U_MF_BAD_OPTION) {
errorCode = U_ZERO_ERROR;
errs.setBadOption(name, errorCode);
} else {
errorCode = U_ZERO_ERROR; // Convey any other error generated by the formatter // as a formatting error
errs.setFormattingError(name, errorCode);
}
} // Ignore the output if any error occurred // We don't ignore the output in the case of a Bad Option Error, // because of the select=bad case where we want both an error // and non-fallback output. if (errs.hasFormattingError() || errs.hasBadOptionError()) { return FormattedPlaceholder(fallback);
} if (badSelect) { // In this case, we want to set an error but not replace // the output with a fallback
errs.setRecoverableBadOption(name, errorCode);
} return result;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.