summaryrefslogtreecommitdiff
path: root/src/mbgl/style/expression/collator_expression.cpp
blob: b27eedbc76165ff5ef02d15994abbc86056dcd88 (plain)
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