Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (C) 2013 Google Inc. | 1 // Copyright (C) 2013 Google Inc. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. | 13 // limitations under the License. |
| 14 | 14 |
| 15 #include "rule.h" | 15 #include "rule.h" |
| 16 | 16 |
| 17 #include <libaddressinput/address_field.h> | 17 #include <libaddressinput/address_field.h> |
| 18 #include <libaddressinput/util/scoped_ptr.h> | 18 #include <libaddressinput/util/scoped_ptr.h> |
| 19 | 19 |
| 20 #include <cassert> | |
| 21 #include <cstddef> | |
| 20 #include <map> | 22 #include <map> |
| 21 #include <string> | 23 #include <string> |
| 22 #include <utility> | 24 #include <utility> |
| 25 #include <vector> | |
| 23 | 26 |
| 24 #include "address_field_util.h" | |
| 25 #include "grit.h" | 27 #include "grit.h" |
| 26 #include "messages.h" | 28 #include "messages.h" |
| 27 #include "util/json.h" | 29 #include "util/json.h" |
| 28 #include "util/string_split.h" | 30 #include "util/string_split.h" |
| 29 | 31 |
| 30 namespace i18n { | 32 namespace i18n { |
| 31 namespace addressinput { | 33 namespace addressinput { |
| 32 | 34 |
| 33 namespace { | 35 namespace { |
| 34 | 36 |
| 35 typedef std::map<std::string, int> NameMessageIdMap; | 37 typedef std::map<std::string, int> NameMessageIdMap; |
| 36 | 38 |
| 37 const char kAdminAreaNameTypeKey[] = "state_name_type"; | 39 const char kAdminAreaNameTypeKey[] = "state_name_type"; |
| 38 const char kFormatKey[] = "fmt"; | 40 const char kFormatKey[] = "fmt"; |
| 39 const char kLanguageKey[] = "lang"; | 41 const char kLanguageKey[] = "lang"; |
| 40 const char kLanguagesKey[] = "languages"; | 42 const char kLanguagesKey[] = "languages"; |
| 43 const char kPostalCodeFormatKey[] = "zip"; | |
| 41 const char kPostalCodeNameTypeKey[] = "zip_name_type"; | 44 const char kPostalCodeNameTypeKey[] = "zip_name_type"; |
| 45 const char kRequiredKey[] = "require"; | |
| 42 const char kSubKeysKey[] = "sub_keys"; | 46 const char kSubKeysKey[] = "sub_keys"; |
| 43 | 47 |
| 44 // Used as a separator in a list of items. For example, the list of supported | 48 // Used as a separator in a list of items. For example, the list of supported |
| 45 // languages can be "de~fr~it". | 49 // languages can be "de~fr~it". |
| 46 const char kSeparator = '~'; | 50 const char kSeparator = '~'; |
| 47 | 51 |
| 48 NameMessageIdMap InitAdminAreaMessageIds() { | 52 NameMessageIdMap InitAdminAreaMessageIds() { |
| 49 NameMessageIdMap message_ids; | 53 NameMessageIdMap message_ids; |
| 50 message_ids.insert(std::make_pair( | 54 message_ids.insert(std::make_pair( |
| 51 "area", IDS_LIBADDRESSINPUT_I18N_AREA)); | 55 "area", IDS_LIBADDRESSINPUT_I18N_AREA)); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 InitPostalCodeMessageIds()); | 95 InitPostalCodeMessageIds()); |
| 92 return kPostalCodeMessageIds; | 96 return kPostalCodeMessageIds; |
| 93 } | 97 } |
| 94 | 98 |
| 95 int GetMessageIdFromName(const std::string& name, | 99 int GetMessageIdFromName(const std::string& name, |
| 96 const NameMessageIdMap& message_ids) { | 100 const NameMessageIdMap& message_ids) { |
| 97 NameMessageIdMap::const_iterator it = message_ids.find(name); | 101 NameMessageIdMap::const_iterator it = message_ids.find(name); |
| 98 return it != message_ids.end() ? it->second : INVALID_MESSAGE_ID; | 102 return it != message_ids.end() ? it->second : INVALID_MESSAGE_ID; |
| 99 } | 103 } |
| 100 | 104 |
| 105 std::map<char, AddressField> InitFields() { | |
| 106 std::map<char, AddressField> fields; | |
| 107 fields.insert(std::make_pair('R', COUNTRY)); | |
| 108 fields.insert(std::make_pair('S', ADMIN_AREA)); | |
| 109 fields.insert(std::make_pair('C', LOCALITY)); | |
| 110 fields.insert(std::make_pair('D', DEPENDENT_LOCALITY)); | |
| 111 fields.insert(std::make_pair('x', SORTING_CODE)); | |
| 112 fields.insert(std::make_pair('Z', POSTAL_CODE)); | |
| 113 fields.insert(std::make_pair('A', STREET_ADDRESS)); | |
| 114 fields.insert(std::make_pair('O', ORGANIZATION)); | |
| 115 fields.insert(std::make_pair('N', RECIPIENT)); | |
| 116 return fields; | |
| 117 } | |
| 118 | |
| 119 const std::map<char, AddressField>& GetFields() { | |
| 120 static const std::map<char, AddressField> kFields(InitFields()); | |
|
Evan Stade
2013/12/19 23:00:04
no static non-PODs allowed
use switch/case for th
please use gerrit instead
2013/12/20 00:37:43
Switch/case does not work for strings. Changed to
| |
| 121 return kFields; | |
| 122 } | |
| 123 | |
| 124 bool IsTokenPrefix(char c) { | |
| 125 return c == '%'; | |
| 126 } | |
| 127 | |
| 128 bool IsNewlineToken(char c) { | |
| 129 return c == 'n'; | |
| 130 } | |
| 131 | |
| 132 bool IsToken(char c) { | |
| 133 return GetFields().find(c) != GetFields().end(); | |
| 134 } | |
| 135 | |
| 136 AddressField ParseToken(char c) { | |
| 137 std::map<char, AddressField>::const_iterator it = GetFields().find(c); | |
| 138 assert(it != GetFields().end()); | |
| 139 return it->second; | |
| 140 } | |
| 141 | |
| 142 // Clears |fields|, parses |format|, and adds the format address fields to | |
| 143 // |fields|. For example, parses "%S%C%n%D%X" into {{ADMIN_AREA, LOCALITY}, | |
| 144 // {DEPENDENT_LOCALITY, SORTING_CODE}}. | |
| 145 void ParseAddressFieldsFormat(const std::string& format, | |
| 146 std::vector<std::vector<AddressField> >* fields) { | |
| 147 assert(fields != NULL); | |
| 148 fields->clear(); | |
| 149 bool begin_newline = true; | |
| 150 for (std::string::const_iterator current = format.begin(), | |
| 151 next = format.begin() + 1; | |
|
Evan Stade
2013/12/19 23:00:04
splitstring on % makes this shorter I think?
please use gerrit instead
2013/12/20 00:37:43
Good guess! I tried your suggestion, but the resul
| |
| 152 current != format.end() && next != format.end(); | |
| 153 ++current, ++next) { | |
| 154 if (!IsTokenPrefix(*current)) { | |
| 155 continue; | |
| 156 } | |
| 157 if (IsToken(*next)) { | |
| 158 if (begin_newline) { | |
| 159 fields->push_back(std::vector<AddressField>()); | |
| 160 begin_newline = false; | |
| 161 } | |
| 162 fields->back().push_back(ParseToken(*next)); | |
| 163 } else if (IsNewlineToken(*next)) { | |
| 164 begin_newline = true; | |
| 165 } | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 // Clears |fields|, parses |required|, and adds the required fields to |fields|. | |
| 170 // For example, parses "SCDX" into {ADMIN_AREA, LOCALITY, DEPENDENT_LOCALITY, | |
| 171 // SORTING_CODE}. | |
| 172 void ParseAddressFieldsRequired(const std::string& required, | |
| 173 std::vector<AddressField>* fields) { | |
| 174 assert(fields != NULL); | |
| 175 fields->clear(); | |
| 176 for (std::string::const_iterator token = required.begin(); | |
| 177 token != required.end(); ++token) { | |
| 178 if (IsToken(*token)) { | |
| 179 fields->push_back(ParseToken(*token)); | |
| 180 } | |
| 181 } | |
| 182 } | |
| 183 | |
| 101 } // namespace | 184 } // namespace |
| 102 | 185 |
| 103 Rule::Rule() | 186 Rule::Rule() |
| 104 : format_(), | 187 : format_(), |
| 188 required_(), | |
| 105 sub_keys_(), | 189 sub_keys_(), |
| 106 languages_(), | 190 languages_(), |
| 107 language_(), | 191 language_(), |
| 192 postal_code_format_(), | |
| 108 admin_area_name_message_id_(INVALID_MESSAGE_ID), | 193 admin_area_name_message_id_(INVALID_MESSAGE_ID), |
| 109 postal_code_name_message_id_(INVALID_MESSAGE_ID) {} | 194 postal_code_name_message_id_(INVALID_MESSAGE_ID) {} |
| 110 | 195 |
| 111 Rule::~Rule() {} | 196 Rule::~Rule() {} |
| 112 | 197 |
| 113 void Rule::CopyFrom(const Rule& rule) { | 198 void Rule::CopyFrom(const Rule& rule) { |
| 114 format_ = rule.format_; | 199 format_ = rule.format_; |
| 200 required_ = rule.required_; | |
| 115 sub_keys_ = rule.sub_keys_; | 201 sub_keys_ = rule.sub_keys_; |
| 116 languages_ = rule.languages_; | 202 languages_ = rule.languages_; |
| 117 language_ = rule.language_; | 203 language_ = rule.language_; |
| 204 postal_code_format_ = rule.postal_code_format_; | |
| 118 admin_area_name_message_id_ = rule.admin_area_name_message_id_; | 205 admin_area_name_message_id_ = rule.admin_area_name_message_id_; |
| 119 postal_code_name_message_id_ = rule.postal_code_name_message_id_; | 206 postal_code_name_message_id_ = rule.postal_code_name_message_id_; |
| 120 } | 207 } |
| 121 | 208 |
| 122 bool Rule::ParseSerializedRule(const std::string& serialized_rule) { | 209 bool Rule::ParseSerializedRule(const std::string& serialized_rule) { |
| 123 scoped_ptr<Json> json(Json::Build()); | 210 scoped_ptr<Json> json(Json::Build()); |
| 124 if (!json->ParseObject(serialized_rule)) { | 211 if (!json->ParseObject(serialized_rule)) { |
| 125 return false; | 212 return false; |
| 126 } | 213 } |
| 127 | 214 |
| 128 if (json->HasStringValueForKey(kFormatKey)) { | 215 if (json->HasStringValueForKey(kFormatKey)) { |
| 129 ParseAddressFieldsFormat(json->GetStringValueForKey(kFormatKey), &format_); | 216 ParseAddressFieldsFormat(json->GetStringValueForKey(kFormatKey), &format_); |
| 130 } | 217 } |
| 131 | 218 |
| 219 if (json->HasStringValueForKey(kRequiredKey)) { | |
| 220 ParseAddressFieldsRequired( | |
| 221 json->GetStringValueForKey(kRequiredKey), &required_); | |
| 222 } | |
| 223 | |
| 132 if (json->HasStringValueForKey(kSubKeysKey)) { | 224 if (json->HasStringValueForKey(kSubKeysKey)) { |
| 133 SplitString( | 225 SplitString( |
| 134 json->GetStringValueForKey(kSubKeysKey), kSeparator, &sub_keys_); | 226 json->GetStringValueForKey(kSubKeysKey), kSeparator, &sub_keys_); |
| 135 } | 227 } |
| 136 | 228 |
| 137 if (json->HasStringValueForKey(kLanguagesKey)) { | 229 if (json->HasStringValueForKey(kLanguagesKey)) { |
| 138 SplitString( | 230 SplitString( |
| 139 json->GetStringValueForKey(kLanguagesKey), kSeparator, &languages_); | 231 json->GetStringValueForKey(kLanguagesKey), kSeparator, &languages_); |
| 140 } | 232 } |
| 141 | 233 |
| 142 if (json->HasStringValueForKey(kLanguageKey)) { | 234 if (json->HasStringValueForKey(kLanguageKey)) { |
| 143 language_ = json->GetStringValueForKey(kLanguageKey); | 235 language_ = json->GetStringValueForKey(kLanguageKey); |
| 144 } | 236 } |
| 145 | 237 |
| 238 if (json->HasStringValueForKey(kPostalCodeFormatKey)) { | |
| 239 postal_code_format_ = json->GetStringValueForKey(kPostalCodeFormatKey); | |
| 240 } | |
| 241 | |
| 146 if (json->HasStringValueForKey(kAdminAreaNameTypeKey)) { | 242 if (json->HasStringValueForKey(kAdminAreaNameTypeKey)) { |
| 147 admin_area_name_message_id_ = | 243 admin_area_name_message_id_ = |
| 148 GetMessageIdFromName(json->GetStringValueForKey(kAdminAreaNameTypeKey), | 244 GetMessageIdFromName(json->GetStringValueForKey(kAdminAreaNameTypeKey), |
| 149 GetAdminAreaMessageIds()); | 245 GetAdminAreaMessageIds()); |
| 150 } | 246 } |
| 151 | 247 |
| 152 if (json->HasStringValueForKey(kPostalCodeNameTypeKey)) { | 248 if (json->HasStringValueForKey(kPostalCodeNameTypeKey)) { |
| 153 postal_code_name_message_id_ = | 249 postal_code_name_message_id_ = |
| 154 GetMessageIdFromName(json->GetStringValueForKey(kPostalCodeNameTypeKey), | 250 GetMessageIdFromName(json->GetStringValueForKey(kPostalCodeNameTypeKey), |
| 155 GetPostalCodeMessageIds()); | 251 GetPostalCodeMessageIds()); |
| 156 } | 252 } |
| 157 | 253 |
| 158 return true; | 254 return true; |
| 159 } | 255 } |
| 160 | 256 |
| 161 } // namespace addressinput | 257 } // namespace addressinput |
| 162 } // namespace i18n | 258 } // namespace i18n |
| OLD | NEW |