1 #include <mbgl/style/expression/collator.hpp>
2 #include <mbgl/util/platform.hpp>
3 #include <libnu/strcoll.h>
4 #include <unaccent.hpp>
5
6 /*
7 The default implementation of Collator ignores locale.
8 Case sensitivity and collation order are based on
9 Default Unicode Collation Element Table (DUCET).
10
11 Diacritic-insensitivity is implemented with nunicode's
12 non-standard "unaccent" functionality, which is tailored
13 to European languages.
14
15 It would be possible to implement locale awareness using ICU,
16 but would require bundling locale data.
17 */
18
19 namespace mbgl {
20 namespace style {
21 namespace expression {
22
23 class Collator::Impl {
24 public:
Impl(bool caseSensitive_,bool diacriticSensitive_,optional<std::string>)25 Impl(bool caseSensitive_, bool diacriticSensitive_, optional<std::string>)
26 : caseSensitive(caseSensitive_)
27 , diacriticSensitive(diacriticSensitive_)
28 {}
29
operator ==(const Impl & other) const30 bool operator==(const Impl& other) const {
31 return caseSensitive == other.caseSensitive &&
32 diacriticSensitive == other.diacriticSensitive;
33 }
34
compare(const std::string & lhs,const std::string & rhs) const35 int compare(const std::string& lhs, const std::string& rhs) const {
36 if (caseSensitive && diacriticSensitive) {
37 return nu_strcoll(lhs.c_str(), rhs.c_str(),
38 nu_utf8_read, nu_utf8_read);
39 } else if (!caseSensitive && diacriticSensitive) {
40 return nu_strcasecoll(lhs.c_str(), rhs.c_str(),
41 nu_utf8_read, nu_utf8_read);
42 } else if (caseSensitive && !diacriticSensitive) {
43 return nu_strcoll(platform::unaccent(lhs).c_str(), platform::unaccent(rhs).c_str(),
44 nu_utf8_read, nu_utf8_read);
45 } else {
46 return nu_strcasecoll(platform::unaccent(lhs).c_str(), platform::unaccent(rhs).c_str(),
47 nu_utf8_read, nu_utf8_read);
48 }
49 }
50
resolvedLocale() const51 std::string resolvedLocale() const {
52 return "";
53 }
54 private:
55 bool caseSensitive;
56 bool diacriticSensitive;
57 };
58
59
Collator(bool caseSensitive,bool diacriticSensitive,optional<std::string> locale_)60 Collator::Collator(bool caseSensitive, bool diacriticSensitive, optional<std::string> locale_)
61 : impl(std::make_shared<Impl>(caseSensitive, diacriticSensitive, std::move(locale_)))
62 {}
63
operator ==(const Collator & other) const64 bool Collator::operator==(const Collator& other) const {
65 return *impl == *(other.impl);
66 }
67
compare(const std::string & lhs,const std::string & rhs) const68 int Collator::compare(const std::string& lhs, const std::string& rhs) const {
69 return impl->compare(lhs, rhs);
70 }
71
resolvedLocale() const72 std::string Collator::resolvedLocale() const {
73 return impl->resolvedLocale();
74 }
75
76
77 } // namespace expression
78 } // namespace style
79 } // namespace mbgl
80