| 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 |