1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#include <mbgl/style/expression/collator.hpp>
#include <mbgl/style/expression/collator_expression.hpp>
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
namespace style {
namespace expression {
CollatorExpression::CollatorExpression(std::unique_ptr<Expression> caseSensitive_,
std::unique_ptr<Expression> diacriticSensitive_,
optional<std::unique_ptr<Expression>> locale_)
: Expression(Kind::CollatorExpression, type::Collator)
, 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 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 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 optional<Convertible> localeOption = objectMember(options, "locale");
ParseResult locale;
if (localeOption) {
locale = ctx.parse(*localeOption, 1, {type::String});
if (!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) {
fn(**locale);
}
}
bool CollatorExpression::operator==(const Expression& e) const {
if (e.getKind() == Kind::CollatorExpression) {
auto rhs = static_cast<const CollatorExpression*>(&e);
if ((locale && (!rhs->locale || **locale != **(rhs->locale))) ||
(!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) {
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) {
auto localeResult = (*locale)->evaluate(params);
if (!localeResult) {
return localeResult.error();
}
return Collator(caseSensitiveResult->get<bool>(), diacriticSensitiveResult->get<bool>(), localeResult->get<std::string>());
} else {
return Collator(caseSensitiveResult->get<bool>(), diacriticSensitiveResult->get<bool>());
}
}
} // namespace expression
} // namespace style
} // namespace mbgl
|