OLD | NEW |
| (Empty) |
1 // Copyright (C) 2014 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 | |
15 #include "ruleset.h" | |
16 | |
17 #include <libaddressinput/address_field.h> | |
18 #include <libaddressinput/util/scoped_ptr.h> | |
19 | |
20 #include <cassert> | |
21 #include <cstddef> | |
22 #include <map> | |
23 #include <set> | |
24 #include <string> | |
25 #include <utility> | |
26 | |
27 #include "rule.h" | |
28 #include "util/canonicalize_string.h" | |
29 #include "util/stl_util.h" | |
30 | |
31 namespace i18n { | |
32 namespace addressinput { | |
33 | |
34 Ruleset::Ruleset(AddressField field, scoped_ptr<Rule> rule) | |
35 : tries_(), | |
36 canonicalizer_(), | |
37 parent_(NULL), | |
38 field_(field), | |
39 deepest_ruleset_level_(field), | |
40 rule_(rule.Pass()), | |
41 sub_regions_(), | |
42 language_codes_() { | |
43 assert(field_ >= COUNTRY); | |
44 assert(field_ <= DEPENDENT_LOCALITY); | |
45 assert(rule_ != NULL); | |
46 } | |
47 | |
48 Ruleset::~Ruleset() { | |
49 STLDeleteValues(&sub_regions_); | |
50 STLDeleteValues(&language_codes_); | |
51 | |
52 // Delete the maps and trie objects owned by |tries_| field. | |
53 for (LanguageCodeTries::const_iterator lang_it = tries_.begin(); | |
54 lang_it != tries_.end(); ++lang_it) { | |
55 AddressFieldTries* address_field_tries = lang_it->second; | |
56 assert(address_field_tries != NULL); | |
57 | |
58 for (AddressFieldTries::const_iterator address_field_it = | |
59 address_field_tries->begin(); | |
60 address_field_it != address_field_tries->end(); | |
61 ++address_field_it) { | |
62 IdentityFieldTries* identity_field_tries = address_field_it->second; | |
63 assert(identity_field_tries != NULL); | |
64 | |
65 for (IdentityFieldTries::const_iterator identity_field_it = | |
66 identity_field_tries->begin(); | |
67 identity_field_it != identity_field_tries->end(); | |
68 ++identity_field_it) { | |
69 // The tries do not own the ruleset objects. | |
70 Trie<const Ruleset*>* trie = identity_field_it->second; | |
71 assert(trie != NULL); | |
72 delete trie; | |
73 } | |
74 delete identity_field_tries; | |
75 } | |
76 delete address_field_tries; | |
77 } | |
78 } | |
79 | |
80 void Ruleset::AddSubRegionRuleset(const std::string& sub_region, | |
81 scoped_ptr<Ruleset> ruleset) { | |
82 assert(sub_regions_.find(sub_region) == sub_regions_.end()); | |
83 assert(ruleset != NULL); | |
84 assert(ruleset->field() == static_cast<AddressField>(field() + 1)); | |
85 | |
86 ruleset->parent_ = this; | |
87 sub_regions_[sub_region] = ruleset.release(); | |
88 } | |
89 | |
90 void Ruleset::AddLanguageCodeRule(const std::string& language_code, | |
91 scoped_ptr<Rule> rule) { | |
92 assert(language_codes_.find(language_code) == language_codes_.end()); | |
93 assert(rule != NULL); | |
94 language_codes_[language_code] = rule.release(); | |
95 } | |
96 | |
97 Ruleset* Ruleset::GetSubRegionRuleset(const std::string& sub_region) const { | |
98 std::map<std::string, Ruleset*>::const_iterator it = | |
99 sub_regions_.find(sub_region); | |
100 return it != sub_regions_.end() ? it->second : NULL; | |
101 } | |
102 | |
103 const Rule& Ruleset::GetLanguageCodeRule( | |
104 const std::string& language_code) const { | |
105 std::map<std::string, const Rule*>::const_iterator it = | |
106 language_codes_.find(language_code); | |
107 return it != language_codes_.end() ? *it->second : *rule_; | |
108 } | |
109 | |
110 void Ruleset::BuildPrefixSearchIndex() { | |
111 assert(field_ == COUNTRY); | |
112 assert(tries_.empty()); | |
113 | |
114 // Default language tries. | |
115 tries_[""] = new AddressFieldTries; | |
116 | |
117 // Non-default language tries. | |
118 for (std::vector<std::string>::const_iterator lang_it = | |
119 rule_->GetLanguages().begin(); | |
120 lang_it != rule_->GetLanguages().end(); | |
121 ++lang_it) { | |
122 if (*lang_it != rule_->GetLanguage() && !lang_it->empty()) { | |
123 tries_[*lang_it] = new AddressFieldTries; | |
124 } | |
125 } | |
126 | |
127 for (LanguageCodeTries::const_iterator lang_it = tries_.begin(); | |
128 lang_it != tries_.end(); ++lang_it) { | |
129 AddressFieldTries* address_field_tries = lang_it->second; | |
130 address_field_tries->insert( | |
131 std::make_pair(ADMIN_AREA, new IdentityFieldTries)); | |
132 address_field_tries->insert( | |
133 std::make_pair(LOCALITY, new IdentityFieldTries)); | |
134 address_field_tries->insert( | |
135 std::make_pair(DEPENDENT_LOCALITY, new IdentityFieldTries)); | |
136 | |
137 for (AddressFieldTries::const_iterator address_field_it = | |
138 address_field_tries->begin(); | |
139 address_field_it != address_field_tries->end(); | |
140 ++address_field_it) { | |
141 IdentityFieldTries* identity_field_tries = address_field_it->second; | |
142 identity_field_tries->insert( | |
143 std::make_pair(Rule::KEY, new Trie<const Ruleset*>)); | |
144 identity_field_tries->insert( | |
145 std::make_pair(Rule::NAME, new Trie<const Ruleset*>)); | |
146 identity_field_tries->insert( | |
147 std::make_pair(Rule::LATIN_NAME, new Trie<const Ruleset*>)); | |
148 } | |
149 } | |
150 | |
151 canonicalizer_ = StringCanonicalizer::Build(); | |
152 AddSubRegionRulesetsToTrie(*this); | |
153 } | |
154 | |
155 void Ruleset::FindRulesetsByPrefix(const std::string& language_code, | |
156 AddressField ruleset_level, | |
157 Rule::IdentityField identity_field, | |
158 const std::string& prefix, | |
159 std::set<const Ruleset*>* result) const { | |
160 assert(field_ == COUNTRY); | |
161 assert(ruleset_level >= ADMIN_AREA); | |
162 assert(ruleset_level <= DEPENDENT_LOCALITY); | |
163 assert(result != NULL); | |
164 assert(canonicalizer_ != NULL); | |
165 | |
166 LanguageCodeTries::const_iterator lang_it = tries_.find(language_code); | |
167 AddressFieldTries* address_field_tries = lang_it != tries_.end() | |
168 ? lang_it->second : tries_.find("")->second; | |
169 assert(address_field_tries != NULL); | |
170 | |
171 AddressFieldTries::const_iterator address_field_it = | |
172 address_field_tries->find(ruleset_level); | |
173 assert(address_field_it != address_field_tries->end()); | |
174 | |
175 IdentityFieldTries* identity_field_tries = address_field_it->second; | |
176 assert(identity_field_tries != NULL); | |
177 | |
178 IdentityFieldTries::const_iterator identity_field_it = | |
179 identity_field_tries->find(identity_field); | |
180 assert(identity_field_it != identity_field_tries->end()); | |
181 | |
182 Trie<const Ruleset*>* trie = identity_field_it->second; | |
183 assert(trie != NULL); | |
184 | |
185 trie->FindDataForKeyPrefix( | |
186 canonicalizer_->CanonicalizeString(prefix), result); | |
187 } | |
188 | |
189 void Ruleset::AddSubRegionRulesetsToTrie(const Ruleset& parent_ruleset) { | |
190 assert(field_ == COUNTRY); | |
191 assert(canonicalizer_ != NULL); | |
192 | |
193 for (std::map<std::string, Ruleset*>::const_iterator sub_region_it = | |
194 parent_ruleset.sub_regions_.begin(); | |
195 sub_region_it != parent_ruleset.sub_regions_.end(); | |
196 ++sub_region_it) { | |
197 const Ruleset* ruleset = sub_region_it->second; | |
198 assert(ruleset != NULL); | |
199 | |
200 if (deepest_ruleset_level_ < ruleset->field()) { | |
201 deepest_ruleset_level_ = ruleset->field(); | |
202 } | |
203 | |
204 for (LanguageCodeTries::const_iterator lang_it = tries_.begin(); | |
205 lang_it != tries_.end(); ++lang_it) { | |
206 const std::string& language_code = lang_it->first; | |
207 const Rule& rule = ruleset->GetLanguageCodeRule(language_code); | |
208 | |
209 AddressFieldTries* address_field_tries = lang_it->second; | |
210 assert(address_field_tries != NULL); | |
211 | |
212 AddressFieldTries::const_iterator address_field_it = | |
213 address_field_tries->find(ruleset->field()); | |
214 assert(address_field_it != address_field_tries->end()); | |
215 | |
216 IdentityFieldTries* identity_field_tries = address_field_it->second; | |
217 assert(identity_field_tries != NULL); | |
218 | |
219 IdentityFieldTries::const_iterator identity_field_it = | |
220 identity_field_tries->find(Rule::KEY); | |
221 assert(identity_field_it != identity_field_tries->end()); | |
222 | |
223 Trie<const Ruleset*>* key_trie = identity_field_it->second; | |
224 assert(key_trie != NULL); | |
225 | |
226 identity_field_it = identity_field_tries->find(Rule::NAME); | |
227 assert(identity_field_it != identity_field_tries->end()); | |
228 | |
229 Trie<const Ruleset*>* name_trie = identity_field_it->second; | |
230 assert(name_trie != NULL); | |
231 | |
232 identity_field_it = identity_field_tries->find(Rule::LATIN_NAME); | |
233 assert(identity_field_it != identity_field_tries->end()); | |
234 | |
235 Trie<const Ruleset*>* latin_name_trie = identity_field_it->second; | |
236 assert(latin_name_trie != NULL); | |
237 | |
238 if (!rule.GetKey().empty()) { | |
239 key_trie->AddDataForKey( | |
240 canonicalizer_->CanonicalizeString(rule.GetKey()), ruleset); | |
241 } | |
242 | |
243 if (!rule.GetName().empty()) { | |
244 name_trie->AddDataForKey( | |
245 canonicalizer_->CanonicalizeString(rule.GetName()), ruleset); | |
246 } | |
247 | |
248 if (!rule.GetLatinName().empty()) { | |
249 latin_name_trie->AddDataForKey( | |
250 canonicalizer_->CanonicalizeString(rule.GetLatinName()), ruleset); | |
251 } | |
252 } | |
253 | |
254 AddSubRegionRulesetsToTrie(*ruleset); | |
255 } | |
256 } | |
257 | |
258 } // namespace addressinput | |
259 } // namespace i18n | |
OLD | NEW |