Files
MapLibreParticleLab/src/mbgl/style/expression/collator_expression.cpp
2024-04-25 03:21:08 +02:00

129 lines
4.7 KiB
C++

#include <mbgl/style/expression/collator.hpp>
#include <mbgl/style/expression/collator_expression.hpp>
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
namespace style {
namespace expression {
CollatorExpression::CollatorExpression(std::unique_ptr<Expression> caseSensitive_,
std::unique_ptr<Expression> diacriticSensitive_,
std::optional<std::unique_ptr<Expression>> locale_)
: Expression(Kind::CollatorExpression,
type::Collator,
depsOf(caseSensitive_) | depsOf(diacriticSensitive_) | depsOf(locale_) |
// Collations are treated as feature-dependent. See `style::expression::isFeatureConstant`
Dependency::Feature),
caseSensitive(std::move(caseSensitive_)),
diacriticSensitive(std::move(diacriticSensitive_)),
locale(std::move(locale_)) {}
using namespace mbgl::style::conversion;
ParseResult CollatorExpression::parse(const Convertible& value, ParsingContext& ctx) {
if (arrayLength(value) != 2) {
ctx.error("Expected one argument.");
return ParseResult();
}
auto options = arrayMember(value, 1);
if (!isObject(options)) {
ctx.error("Collator options argument must be an object.");
return ParseResult();
}
const std::optional<Convertible> caseSensitiveOption = objectMember(options, "case-sensitive");
ParseResult caseSensitive;
if (caseSensitiveOption) {
caseSensitive = ctx.parse(*caseSensitiveOption, 1, {type::Boolean});
} else {
caseSensitive = {std::make_unique<Literal>(false)};
}
if (!caseSensitive) {
return ParseResult();
}
const std::optional<Convertible> diacriticSensitiveOption = objectMember(options, "diacritic-sensitive");
ParseResult diacriticSensitive;
if (diacriticSensitiveOption) {
diacriticSensitive = ctx.parse(*diacriticSensitiveOption, 1, {type::Boolean});
} else {
diacriticSensitive = {std::make_unique<Literal>(false)};
}
if (!diacriticSensitive) {
return ParseResult();
}
const std::optional<Convertible> localeOption = objectMember(options, "locale");
ParseResult locale;
if (localeOption) {
locale = ctx.parse(*localeOption, 1, {type::String});
if (!locale || !*locale) {
return ParseResult();
}
}
return ParseResult(std::make_unique<CollatorExpression>(
std::move(*caseSensitive), std::move(*diacriticSensitive), std::move(locale)));
}
void CollatorExpression::eachChild(const std::function<void(const Expression&)>& fn) const {
fn(*caseSensitive);
fn(*diacriticSensitive);
if (locale && *locale) {
fn(**locale);
}
}
bool CollatorExpression::operator==(const Expression& e) const noexcept {
if (e.getKind() == Kind::CollatorExpression) {
const auto* rhs = static_cast<const CollatorExpression*>(&e);
const bool lLocSet = locale && *locale;
const bool rLocSet = rhs->locale && *rhs->locale;
if ((!lLocSet && rLocSet) || (lLocSet && (!rLocSet || **locale != **rhs->locale))) {
return false;
}
return *caseSensitive == *(rhs->caseSensitive) && *diacriticSensitive == *(rhs->diacriticSensitive);
}
return false;
}
mbgl::Value CollatorExpression::serialize() const {
std::unordered_map<std::string, mbgl::Value> options;
options["case-sensitive"] = caseSensitive->serialize();
options["diacritic-sensitive"] = diacriticSensitive->serialize();
if (locale && *locale) {
options["locale"] = (*locale)->serialize();
}
return std::vector<mbgl::Value>{{std::string("collator"), options}};
}
EvaluationResult CollatorExpression::evaluate(const EvaluationContext& params) const {
auto caseSensitiveResult = caseSensitive->evaluate(params);
if (!caseSensitiveResult) {
return caseSensitiveResult.error();
}
auto diacriticSensitiveResult = diacriticSensitive->evaluate(params);
if (!diacriticSensitiveResult) {
return diacriticSensitiveResult.error();
}
if (locale && *locale) {
if (auto localeResult = (*locale)->evaluate(params)) {
return Collator(caseSensitiveResult->get<bool>(),
diacriticSensitiveResult->get<bool>(),
localeResult->get<std::string>());
} else {
return localeResult.error();
}
} else {
return Collator(caseSensitiveResult->get<bool>(), diacriticSensitiveResult->get<bool>());
}
}
} // namespace expression
} // namespace style
} // namespace mbgl