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 <map> | 20 #include <cassert> |
| 21 #include <cstddef> | |
| 21 #include <string> | 22 #include <string> |
| 22 #include <utility> | 23 #include <vector> |
| 23 | 24 |
| 24 #include "address_field_util.h" | |
| 25 #include "grit.h" | 25 #include "grit.h" |
| 26 #include "messages.h" | 26 #include "messages.h" |
| 27 #include "util/json.h" | 27 #include "util/json.h" |
| 28 #include "util/string_split.h" | 28 #include "util/string_split.h" |
| 29 | 29 |
| 30 namespace i18n { | 30 namespace i18n { |
| 31 namespace addressinput { | 31 namespace addressinput { |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 typedef std::map<std::string, int> NameMessageIdMap; | 35 const char kCountryToken = 'R'; |
| 36 const char kAdminAreaToken = 'S'; | |
| 37 const char kLocalityToken = 'C'; | |
| 38 const char kDependentLocalityToken = 'D'; | |
| 39 const char kSortingCodeToken = 'X'; | |
| 40 const char kPostalCodeToken = 'Z'; | |
| 41 const char kStreetAddressToken = 'A'; | |
| 42 const char kOrganizationToken = 'O'; | |
| 43 const char kRecipientToken = 'N'; | |
| 36 | 44 |
| 37 const char kAdminAreaNameTypeKey[] = "state_name_type"; | 45 bool IsToken(char c) { |
| 38 const char kFormatKey[] = "fmt"; | 46 return c == kCountryToken || |
| 39 const char kLanguageKey[] = "lang"; | 47 c == kAdminAreaToken || |
| 40 const char kLanguagesKey[] = "languages"; | 48 c == kLocalityToken || |
| 41 const char kPostalCodeNameTypeKey[] = "zip_name_type"; | 49 c == kDependentLocalityToken || |
| 42 const char kSubKeysKey[] = "sub_keys"; | 50 c == kSortingCodeToken || |
| 43 | 51 c == kPostalCodeToken || |
| 44 // Used as a separator in a list of items. For example, the list of supported | 52 c == kStreetAddressToken || |
| 45 // languages can be "de~fr~it". | 53 c == kOrganizationToken || |
| 46 const char kSeparator = '~'; | 54 c == kRecipientToken; |
| 47 | |
| 48 NameMessageIdMap InitAdminAreaMessageIds() { | |
| 49 NameMessageIdMap message_ids; | |
| 50 message_ids.insert(std::make_pair( | |
| 51 "area", IDS_LIBADDRESSINPUT_I18N_AREA)); | |
| 52 message_ids.insert(std::make_pair( | |
| 53 "county", IDS_LIBADDRESSINPUT_I18N_COUNTY_LABEL)); | |
| 54 message_ids.insert(std::make_pair( | |
| 55 "department", IDS_LIBADDRESSINPUT_I18N_DEPARTMENT)); | |
| 56 message_ids.insert(std::make_pair( | |
| 57 "district", IDS_LIBADDRESSINPUT_I18N_DEPENDENT_LOCALITY_LABEL)); | |
| 58 message_ids.insert(std::make_pair( | |
| 59 "do_si", IDS_LIBADDRESSINPUT_I18N_DO_SI)); | |
| 60 message_ids.insert(std::make_pair( | |
| 61 "emirate", IDS_LIBADDRESSINPUT_I18N_EMIRATE)); | |
| 62 message_ids.insert(std::make_pair( | |
| 63 "island", IDS_LIBADDRESSINPUT_I18N_ISLAND)); | |
| 64 message_ids.insert(std::make_pair( | |
| 65 "parish", IDS_LIBADDRESSINPUT_I18N_PARISH)); | |
| 66 message_ids.insert(std::make_pair( | |
| 67 "prefecture", IDS_LIBADDRESSINPUT_I18N_PREFECTURE)); | |
| 68 message_ids.insert(std::make_pair( | |
| 69 "province", IDS_LIBADDRESSINPUT_I18N_PROVINCE)); | |
| 70 message_ids.insert(std::make_pair( | |
| 71 "state", IDS_LIBADDRESSINPUT_I18N_STATE_LABEL)); | |
| 72 return message_ids; | |
| 73 } | 55 } |
| 74 | 56 |
| 75 const NameMessageIdMap& GetAdminAreaMessageIds() { | 57 AddressField ParseToken(char c) { |
|
Evan Stade
2013/12/20 03:55:13
bool ParseToken(char c, AddressField* field) {
...
please use gerrit instead
2013/12/20 22:03:32
Nice! Done.
| |
| 76 static const NameMessageIdMap kAdminAreaMessageIds(InitAdminAreaMessageIds()); | 58 switch (c) { |
| 77 return kAdminAreaMessageIds; | 59 case kCountryToken: |
| 60 return COUNTRY; | |
| 61 case kAdminAreaToken: | |
| 62 return ADMIN_AREA; | |
| 63 case kLocalityToken: | |
| 64 return LOCALITY; | |
| 65 case kDependentLocalityToken: | |
| 66 return DEPENDENT_LOCALITY; | |
| 67 case kSortingCodeToken: | |
| 68 return SORTING_CODE; | |
| 69 case kPostalCodeToken: | |
| 70 return POSTAL_CODE; | |
| 71 case kStreetAddressToken: | |
| 72 return STREET_ADDRESS; | |
| 73 case kOrganizationToken: | |
| 74 return ORGANIZATION; | |
| 75 case kRecipientToken: | |
| 76 return RECIPIENT; | |
| 77 default: | |
| 78 assert(false); | |
| 79 return COUNTRY; | |
| 80 } | |
| 78 } | 81 } |
| 79 | 82 |
| 80 NameMessageIdMap InitPostalCodeMessageIds() { | 83 // Clears |fields|, parses |format|, and adds the format address fields to |
| 81 NameMessageIdMap message_ids; | 84 // |fields|. For example, parses "%S%C%n%D%X" into {{ADMIN_AREA, LOCALITY}, |
| 82 message_ids.insert(std::make_pair( | 85 // {DEPENDENT_LOCALITY, SORTING_CODE}}. |
| 83 "postal", IDS_LIBADDRESSINPUT_I18N_POSTAL_CODE_LABEL)); | 86 void ParseAddressFieldsFormat(const std::string& format, |
| 84 message_ids.insert(std::make_pair( | 87 std::vector<std::vector<AddressField> >* fields) { |
| 85 "zip", IDS_LIBADDRESSINPUT_I18N_ZIP_CODE_LABEL)); | 88 assert(fields != NULL); |
| 86 return message_ids; | 89 fields->clear(); |
| 90 bool begin_newline = true; | |
| 91 for (std::string::const_iterator current = format.begin(), | |
|
Evan Stade
2013/12/20 03:55:13
I dunno, this looks shorter and more idiomatic to
please use gerrit instead
2013/12/20 22:03:32
I'll give you the idiomatic. Done.
This function
| |
| 92 next = format.begin() + 1; | |
| 93 current != format.end() && next != format.end(); | |
| 94 ++current, ++next) { | |
| 95 if (*current != '%') { | |
|
please use gerrit instead
2013/12/20 00:37:43
Inlined IsTokenPrefix().
| |
| 96 continue; | |
| 97 } | |
| 98 if (IsToken(*next)) { | |
| 99 if (begin_newline) { | |
| 100 fields->push_back(std::vector<AddressField>()); | |
| 101 begin_newline = false; | |
| 102 } | |
| 103 fields->back().push_back(ParseToken(*next)); | |
| 104 } else if (*next == 'n') { | |
|
please use gerrit instead
2013/12/20 00:37:43
Inlined IsNewlineToken().
| |
| 105 begin_newline = true; | |
| 106 } | |
| 107 } | |
| 87 } | 108 } |
| 88 | 109 |
| 89 const NameMessageIdMap& GetPostalCodeMessageIds() { | 110 // Clears |fields|, parses |required|, and adds the required fields to |fields|. |
| 90 static const NameMessageIdMap kPostalCodeMessageIds( | 111 // For example, parses "SCDX" into {ADMIN_AREA, LOCALITY, DEPENDENT_LOCALITY, |
| 91 InitPostalCodeMessageIds()); | 112 // SORTING_CODE}. |
| 92 return kPostalCodeMessageIds; | 113 void ParseAddressFieldsRequired(const std::string& required, |
| 114 std::vector<AddressField>* fields) { | |
| 115 assert(fields != NULL); | |
| 116 fields->clear(); | |
| 117 for (std::string::const_iterator token = required.begin(); | |
| 118 token != required.end(); ++token) { | |
| 119 if (IsToken(*token)) { | |
| 120 fields->push_back(ParseToken(*token)); | |
| 121 } | |
| 122 } | |
| 93 } | 123 } |
| 94 | 124 |
| 95 int GetMessageIdFromName(const std::string& name, | 125 int GetAdminAreaMessageId(const std::string& admin_area_type) { |
| 96 const NameMessageIdMap& message_ids) { | 126 if (admin_area_type == "area") { |
| 97 NameMessageIdMap::const_iterator it = message_ids.find(name); | 127 return IDS_LIBADDRESSINPUT_I18N_AREA; |
| 98 return it != message_ids.end() ? it->second : INVALID_MESSAGE_ID; | 128 } |
| 129 if (admin_area_type == "county") { | |
| 130 return IDS_LIBADDRESSINPUT_I18N_COUNTY_LABEL; | |
| 131 } | |
| 132 if (admin_area_type == "department") { | |
| 133 return IDS_LIBADDRESSINPUT_I18N_DEPARTMENT; | |
| 134 } | |
| 135 if (admin_area_type == "district") { | |
| 136 return IDS_LIBADDRESSINPUT_I18N_DEPENDENT_LOCALITY_LABEL; | |
| 137 } | |
| 138 if (admin_area_type == "do_si") { | |
| 139 return IDS_LIBADDRESSINPUT_I18N_DO_SI; | |
| 140 } | |
| 141 if (admin_area_type == "emirate") { | |
| 142 return IDS_LIBADDRESSINPUT_I18N_EMIRATE; | |
| 143 } | |
| 144 if (admin_area_type == "island") { | |
| 145 return IDS_LIBADDRESSINPUT_I18N_ISLAND; | |
| 146 } | |
| 147 if (admin_area_type == "parish") { | |
| 148 return IDS_LIBADDRESSINPUT_I18N_PARISH; | |
| 149 } | |
| 150 if (admin_area_type == "prefecture") { | |
| 151 return IDS_LIBADDRESSINPUT_I18N_PREFECTURE; | |
| 152 } | |
| 153 if (admin_area_type == "province") { | |
| 154 return IDS_LIBADDRESSINPUT_I18N_PROVINCE; | |
| 155 } | |
| 156 if (admin_area_type == "state") { | |
| 157 return IDS_LIBADDRESSINPUT_I18N_STATE_LABEL; | |
| 158 } | |
| 159 return INVALID_MESSAGE_ID; | |
| 160 } | |
| 161 | |
| 162 int GetPostalCodeMessageId(const std::string& postal_code_type) { | |
| 163 if (postal_code_type == "postal") { | |
| 164 return IDS_LIBADDRESSINPUT_I18N_POSTAL_CODE_LABEL; | |
| 165 } | |
| 166 if (postal_code_type == "zip") { | |
| 167 return IDS_LIBADDRESSINPUT_I18N_ZIP_CODE_LABEL; | |
| 168 } | |
| 169 return INVALID_MESSAGE_ID; | |
| 99 } | 170 } |
| 100 | 171 |
| 101 } // namespace | 172 } // namespace |
| 102 | 173 |
| 103 Rule::Rule() | 174 Rule::Rule() |
| 104 : format_(), | 175 : format_(), |
| 176 required_(), | |
| 105 sub_keys_(), | 177 sub_keys_(), |
| 106 languages_(), | 178 languages_(), |
| 107 language_(), | 179 language_(), |
| 180 postal_code_format_(), | |
| 108 admin_area_name_message_id_(INVALID_MESSAGE_ID), | 181 admin_area_name_message_id_(INVALID_MESSAGE_ID), |
| 109 postal_code_name_message_id_(INVALID_MESSAGE_ID) {} | 182 postal_code_name_message_id_(INVALID_MESSAGE_ID) {} |
| 110 | 183 |
| 111 Rule::~Rule() {} | 184 Rule::~Rule() {} |
| 112 | 185 |
| 113 void Rule::CopyFrom(const Rule& rule) { | 186 void Rule::CopyFrom(const Rule& rule) { |
| 114 format_ = rule.format_; | 187 format_ = rule.format_; |
| 188 required_ = rule.required_; | |
| 115 sub_keys_ = rule.sub_keys_; | 189 sub_keys_ = rule.sub_keys_; |
| 116 languages_ = rule.languages_; | 190 languages_ = rule.languages_; |
| 117 language_ = rule.language_; | 191 language_ = rule.language_; |
| 192 postal_code_format_ = rule.postal_code_format_; | |
| 118 admin_area_name_message_id_ = rule.admin_area_name_message_id_; | 193 admin_area_name_message_id_ = rule.admin_area_name_message_id_; |
| 119 postal_code_name_message_id_ = rule.postal_code_name_message_id_; | 194 postal_code_name_message_id_ = rule.postal_code_name_message_id_; |
| 120 } | 195 } |
| 121 | 196 |
| 122 bool Rule::ParseSerializedRule(const std::string& serialized_rule) { | 197 bool Rule::ParseSerializedRule(const std::string& serialized_rule) { |
| 123 scoped_ptr<Json> json(Json::Build()); | 198 scoped_ptr<Json> json(Json::Build()); |
| 124 if (!json->ParseObject(serialized_rule)) { | 199 if (!json->ParseObject(serialized_rule)) { |
| 125 return false; | 200 return false; |
| 126 } | 201 } |
| 127 | 202 |
| 203 static const char kFormatKey[] = "fmt"; | |
|
please use gerrit instead
2013/12/20 00:37:43
Moved the string constants to immediately before t
Evan Stade
2013/12/20 03:55:13
I think you can just inline them at this point.
please use gerrit instead
2013/12/20 22:03:32
I prefer to avoid inlining constants that are used
| |
| 128 if (json->HasStringValueForKey(kFormatKey)) { | 204 if (json->HasStringValueForKey(kFormatKey)) { |
| 129 ParseAddressFieldsFormat(json->GetStringValueForKey(kFormatKey), &format_); | 205 ParseAddressFieldsFormat(json->GetStringValueForKey(kFormatKey), &format_); |
| 130 } | 206 } |
| 131 | 207 |
| 208 static const char kRequiredKey[] = "require"; | |
| 209 if (json->HasStringValueForKey(kRequiredKey)) { | |
| 210 ParseAddressFieldsRequired( | |
| 211 json->GetStringValueForKey(kRequiredKey), &required_); | |
| 212 } | |
| 213 | |
| 214 | |
| 215 // Used as a separator in a list of items. For example, the list of supported | |
| 216 // languages can be "de~fr~it". | |
| 217 static const char kSeparator = '~'; | |
| 218 static const char kSubKeysKey[] = "sub_keys"; | |
| 132 if (json->HasStringValueForKey(kSubKeysKey)) { | 219 if (json->HasStringValueForKey(kSubKeysKey)) { |
| 133 SplitString( | 220 SplitString( |
| 134 json->GetStringValueForKey(kSubKeysKey), kSeparator, &sub_keys_); | 221 json->GetStringValueForKey(kSubKeysKey), kSeparator, &sub_keys_); |
| 135 } | 222 } |
| 136 | 223 |
| 224 static const char kLanguagesKey[] = "languages"; | |
| 137 if (json->HasStringValueForKey(kLanguagesKey)) { | 225 if (json->HasStringValueForKey(kLanguagesKey)) { |
| 138 SplitString( | 226 SplitString( |
| 139 json->GetStringValueForKey(kLanguagesKey), kSeparator, &languages_); | 227 json->GetStringValueForKey(kLanguagesKey), kSeparator, &languages_); |
| 140 } | 228 } |
| 141 | 229 |
| 230 static const char kLanguageKey[] = "lang"; | |
| 142 if (json->HasStringValueForKey(kLanguageKey)) { | 231 if (json->HasStringValueForKey(kLanguageKey)) { |
| 143 language_ = json->GetStringValueForKey(kLanguageKey); | 232 language_ = json->GetStringValueForKey(kLanguageKey); |
| 144 } | 233 } |
| 145 | 234 |
| 146 if (json->HasStringValueForKey(kAdminAreaNameTypeKey)) { | 235 static const char kPostalCodeFormatKey[] = "zip"; |
| 147 admin_area_name_message_id_ = | 236 if (json->HasStringValueForKey(kPostalCodeFormatKey)) { |
| 148 GetMessageIdFromName(json->GetStringValueForKey(kAdminAreaNameTypeKey), | 237 postal_code_format_ = json->GetStringValueForKey(kPostalCodeFormatKey); |
| 149 GetAdminAreaMessageIds()); | |
| 150 } | 238 } |
| 151 | 239 |
| 240 static const char kAdminAreaNameTypeKey[] = "state_name_type"; | |
| 241 if (json->HasStringValueForKey(kAdminAreaNameTypeKey)) { | |
| 242 admin_area_name_message_id_ = GetAdminAreaMessageId( | |
| 243 json->GetStringValueForKey(kAdminAreaNameTypeKey)); | |
| 244 } | |
| 245 | |
| 246 static const char kPostalCodeNameTypeKey[] = "zip_name_type"; | |
| 152 if (json->HasStringValueForKey(kPostalCodeNameTypeKey)) { | 247 if (json->HasStringValueForKey(kPostalCodeNameTypeKey)) { |
| 153 postal_code_name_message_id_ = | 248 postal_code_name_message_id_ = GetPostalCodeMessageId( |
| 154 GetMessageIdFromName(json->GetStringValueForKey(kPostalCodeNameTypeKey), | 249 json->GetStringValueForKey(kPostalCodeNameTypeKey)); |
| 155 GetPostalCodeMessageIds()); | |
| 156 } | 250 } |
| 157 | 251 |
| 158 return true; | 252 return true; |
| 159 } | 253 } |
| 160 | 254 |
| 161 } // namespace addressinput | 255 } // namespace addressinput |
| 162 } // namespace i18n | 256 } // namespace i18n |
| OLD | NEW |