1 // Copyright (C) 2013 Google Inc.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <libaddressinput/address_field.h>
18 #include <libaddressinput/util/scoped_ptr.h>
25 #include "region_data_constants.h"
26 #include "util/json.h"
27 #include "util/string_util.h"
30 namespace addressinput {
34 bool ParseToken(char c, AddressField* field) {
35 assert(field != NULL);
47 *field = DEPENDENT_LOCALITY;
50 *field = SORTING_CODE;
56 *field = STREET_ADDRESS;
59 *field = ORGANIZATION;
69 // Clears |lines|, parses |format|, and adds the address fields and literals to
72 // For example, the address format in Finland is "%O%n%N%n%A%nAX-%Z %C%nÅLAND".
73 // It includes the allowed fields prefixed with %, newlines denoted %n, and the
74 // extra text that should be included on an envelope. It is parsed into:
79 // {"AX-", POSTAL_CODE, " ", LOCALITY},
82 void ParseAddressFieldsFormat(const std::string& format,
83 std::vector<std::vector<FormatElement> >* lines) {
84 assert(lines != NULL);
88 std::vector<std::string> format_parts;
89 SplitString(format, '%', &format_parts);
91 // If the address format starts with a literal, then it will be in the first
92 // element of |format_parts|. This literal does not begin with % and should
93 // not be parsed as a token.
94 if (!format_parts.empty() && !format_parts[0].empty()) {
95 lines->back().push_back(FormatElement(format_parts[0]));
98 // The rest of the elements in |format_parts| begin with %.
99 for (size_t i = 1; i < format_parts.size(); ++i) {
100 if (format_parts[i].empty()) {
104 // The first character after % denotes a field or a newline token.
105 const char control_character = format_parts[i][0];
107 // The rest of the string after the token is a literal.
108 const std::string literal = format_parts[i].substr(1);
110 AddressField field = COUNTRY;
111 if (ParseToken(control_character, &field)) {
112 lines->back().push_back(FormatElement(field));
113 } else if (control_character == 'n') {
114 lines->push_back(std::vector<FormatElement>());
117 if (!literal.empty()) {
118 lines->back().push_back(FormatElement(literal));
123 // Clears |fields|, parses |required|, and adds the required fields to |fields|.
124 // For example, parses "SCDX" into {ADMIN_AREA, LOCALITY, DEPENDENT_LOCALITY,
126 void ParseAddressFieldsRequired(const std::string& required,
127 std::vector<AddressField>* fields) {
128 assert(fields != NULL);
130 for (size_t i = 0; i < required.length(); ++i) {
131 AddressField field = COUNTRY;
132 if (ParseToken(required[i], &field)) {
133 fields->push_back(field);
138 // Finds |target| in |values_to_compare| and sets |selected_value| to the
139 // associated value from |values_to_select|. Returns true if |target| is in
140 // |values_to_compare|. |selected_value| should not be NULL. |values_to_compare|
141 // should not be larger than |values_to_select|.
142 bool GetMatchingValue(const std::string& target,
143 const std::vector<std::string>& values_to_compare,
144 const std::vector<std::string>& values_to_select,
145 std::string* selected_value) {
146 assert(selected_value != NULL);
147 assert(values_to_select.size() >= values_to_compare.size());
148 for (size_t i = 0; i < values_to_compare.size(); ++i) {
149 if (LooseStringCompare(values_to_compare[i], target)) {
150 *selected_value = values_to_select[i];
159 FormatElement::FormatElement(AddressField field)
160 : field(field), literal() {}
162 FormatElement::FormatElement(const std::string& literal)
163 : field(COUNTRY), literal(literal) {
164 assert(!literal.empty());
167 FormatElement::~FormatElement() {}
169 bool FormatElement::operator==(const FormatElement& other) const {
170 return field == other.field && literal == other.literal;
178 const Rule& Rule::GetDefault() {
179 // Allocated once and leaked on shutdown.
180 static Rule* default_rule = NULL;
181 if (default_rule == NULL) {
182 default_rule = new Rule;
183 default_rule->ParseSerializedRule(
184 RegionDataConstants::GetDefaultRegionData());
186 return *default_rule;
189 void Rule::CopyFrom(const Rule& rule) {
192 latin_name_ = rule.latin_name_;
193 format_ = rule.format_;
194 latin_format_ = rule.latin_format_;
195 required_ = rule.required_;
196 sub_keys_ = rule.sub_keys_;
197 languages_ = rule.languages_;
198 input_languages_ = rule.input_languages_;
199 language_ = rule.language_;
200 sub_keys_ = rule.sub_keys_;
201 sub_names_ = rule.sub_names_;
202 sub_lnames_ = rule.sub_lnames_;
203 postal_code_format_ = rule.postal_code_format_;
204 admin_area_name_type_ = rule.admin_area_name_type_;
205 postal_code_name_type_ = rule.postal_code_name_type_;
208 bool Rule::ParseSerializedRule(const std::string& serialized_rule) {
209 scoped_ptr<Json> json(Json::Build());
210 if (!json->ParseObject(serialized_rule)) {
213 ParseJsonRule(*json);
217 void Rule::ParseJsonRule(const Json& json_rule) {
219 if (json_rule.GetStringValueForKey("key", &value)) {
223 if (json_rule.GetStringValueForKey("name", &value)) {
227 if (json_rule.GetStringValueForKey("lname", &value)) {
228 latin_name_.swap(value);
231 if (json_rule.GetStringValueForKey("fmt", &value)) {
232 ParseAddressFieldsFormat(value, &format_);
235 if (json_rule.GetStringValueForKey("lfmt", &value)) {
236 ParseAddressFieldsFormat(value, &latin_format_);
239 if (json_rule.GetStringValueForKey("require", &value)) {
240 ParseAddressFieldsRequired(value, &required_);
243 // Used as a separator in a list of items. For example, the list of supported
244 // languages can be "de~fr~it".
245 static const char kSeparator = '~';
246 if (json_rule.GetStringValueForKey("sub_keys", &value)) {
247 SplitString(value, kSeparator, &sub_keys_);
250 if (json_rule.GetStringValueForKey("sub_names", &value)) {
251 SplitString(value, kSeparator, &sub_names_);
252 assert(sub_names_.size() == sub_keys_.size());
255 if (json_rule.GetStringValueForKey("sub_lnames", &value)) {
256 SplitString(value, kSeparator, &sub_lnames_);
257 assert(sub_lnames_.size() == sub_keys_.size());
260 if (json_rule.GetStringValueForKey("languages", &value)) {
261 SplitString(value, kSeparator, &languages_);
264 if (json_rule.GetStringValueForKey("input_languages", &value)) {
265 SplitString(value, kSeparator, &input_languages_);
268 if (json_rule.GetStringValueForKey("lang", &value)) {
269 language_.swap(value);
272 if (json_rule.GetStringValueForKey("zip", &value)) {
273 postal_code_format_.swap(value);
276 if (json_rule.GetStringValueForKey("state_name_type", &value)) {
277 admin_area_name_type_.swap(value);
280 if (json_rule.GetStringValueForKey("zip_name_type", &value)) {
281 postal_code_name_type_.swap(value);
285 const std::string& Rule::GetIdentityField(IdentityField identity_field) const {
286 switch (identity_field) {
293 case IDENTITY_FIELDS_SIZE:
299 bool Rule::CanonicalizeSubKey(const std::string& user_input,
300 bool keep_input_latin,
301 std::string* sub_key) const {
302 assert(sub_key != NULL);
304 if (sub_keys_.empty()) {
305 *sub_key = user_input;
309 return GetMatchingValue(user_input, sub_keys_, sub_keys_, sub_key) ||
310 GetMatchingValue(user_input, sub_names_, sub_keys_, sub_key) ||
312 GetMatchingValue(user_input, sub_lnames_, sub_lnames_, sub_key)) ||
313 GetMatchingValue(user_input, sub_lnames_, sub_keys_, sub_key);
316 } // namespace addressinput