Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1000)

Side by Side Diff: third_party/libaddressinput/chromium/cpp/src/rule.cc

Issue 389863002: Remove Chrome's own version of libaddressinput in favor of the upstream. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (C) 2013 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 "rule.h"
16
17 #include <libaddressinput/address_field.h>
18 #include <libaddressinput/util/scoped_ptr.h>
19
20 #include <cassert>
21 #include <cstddef>
22 #include <string>
23 #include <vector>
24
25 #include "region_data_constants.h"
26 #include "util/json.h"
27 #include "util/string_util.h"
28
29 namespace i18n {
30 namespace addressinput {
31
32 namespace {
33
34 bool ParseToken(char c, AddressField* field) {
35 assert(field != NULL);
36 switch (c) {
37 case 'R':
38 *field = COUNTRY;
39 return true;
40 case 'S':
41 *field = ADMIN_AREA;
42 return true;
43 case 'C':
44 *field = LOCALITY;
45 return true;
46 case 'D':
47 *field = DEPENDENT_LOCALITY;
48 return true;
49 case 'X':
50 *field = SORTING_CODE;
51 return true;
52 case 'Z':
53 *field = POSTAL_CODE;
54 return true;
55 case 'A':
56 *field = STREET_ADDRESS;
57 return true;
58 case 'N':
59 *field = RECIPIENT;
60 return true;
61 default:
62 return false;
63 }
64 }
65
66 // Clears |lines|, parses |format|, and adds the address fields and literals to
67 // |lines|.
68 //
69 // For example, the address format in Finland is "%O%n%N%n%A%nAX-%Z %C%nÅLAND".
70 // It includes the allowed fields prefixed with %, newlines denoted %n, and the
71 // extra text that should be included on an envelope. It is parsed into:
72 // {
73 // {RECIPIENT},
74 // {STREET_ADDRESS},
75 // {"AX-", POSTAL_CODE, " ", LOCALITY},
76 // {"ÅLAND"}
77 // }
78 void ParseAddressFieldsFormat(const std::string& format,
79 std::vector<std::vector<FormatElement> >* lines) {
80 assert(lines != NULL);
81 lines->clear();
82 lines->resize(1);
83
84 std::vector<std::string> format_parts;
85 SplitString(format, '%', &format_parts);
86
87 // If the address format starts with a literal, then it will be in the first
88 // element of |format_parts|. This literal does not begin with % and should
89 // not be parsed as a token.
90 if (!format_parts.empty() && !format_parts[0].empty()) {
91 lines->back().push_back(FormatElement(format_parts[0]));
92 }
93
94 // The rest of the elements in |format_parts| begin with %.
95 for (size_t i = 1; i < format_parts.size(); ++i) {
96 if (format_parts[i].empty()) {
97 continue;
98 }
99
100 // The first character after % denotes a field or a newline token.
101 const char control_character = format_parts[i][0];
102
103 // The rest of the string after the token is a literal.
104 const std::string literal = format_parts[i].substr(1);
105
106 AddressField field = COUNTRY;
107 if (ParseToken(control_character, &field)) {
108 lines->back().push_back(FormatElement(field));
109 } else if (control_character == 'n' && !lines->back().empty()) {
110 lines->push_back(std::vector<FormatElement>());
111 }
112
113 if (!literal.empty()) {
114 lines->back().push_back(FormatElement(literal));
115 }
116 }
117 }
118
119 // Clears |fields|, parses |required|, and adds the required fields to |fields|.
120 // For example, parses "SCDX" into {ADMIN_AREA, LOCALITY, DEPENDENT_LOCALITY,
121 // SORTING_CODE}.
122 void ParseAddressFieldsRequired(const std::string& required,
123 std::vector<AddressField>* fields) {
124 assert(fields != NULL);
125 fields->clear();
126 for (size_t i = 0; i < required.length(); ++i) {
127 AddressField field = COUNTRY;
128 if (ParseToken(required[i], &field)) {
129 fields->push_back(field);
130 }
131 }
132 }
133
134 // Finds |target| in |values_to_compare| and sets |selected_value| to the
135 // associated value from |values_to_select|. Returns true if |target| is in
136 // |values_to_compare|. |selected_value| should not be NULL. |values_to_compare|
137 // should not be larger than |values_to_select|.
138 bool GetMatchingValue(const std::string& target,
139 const std::vector<std::string>& values_to_compare,
140 const std::vector<std::string>& values_to_select,
141 std::string* selected_value) {
142 assert(selected_value != NULL);
143 assert(values_to_select.size() >= values_to_compare.size());
144 for (size_t i = 0; i < values_to_compare.size(); ++i) {
145 if (LooseStringCompare(values_to_compare[i], target)) {
146 *selected_value = values_to_select[i];
147 return true;
148 }
149 }
150 return false;
151 }
152
153 } // namespace
154
155 FormatElement::FormatElement(AddressField field)
156 : field(field), literal() {}
157
158 FormatElement::FormatElement(const std::string& literal)
159 : field(COUNTRY), literal(literal) {
160 assert(!literal.empty());
161 }
162
163 FormatElement::~FormatElement() {}
164
165 bool FormatElement::operator==(const FormatElement& other) const {
166 return field == other.field && literal == other.literal;
167 }
168
169 Rule::Rule() {}
170
171 Rule::~Rule() {}
172
173 // static
174 const Rule& Rule::GetDefault() {
175 // Allocated once and leaked on shutdown.
176 static Rule* default_rule = NULL;
177 if (default_rule == NULL) {
178 default_rule = new Rule;
179 default_rule->ParseSerializedRule(
180 RegionDataConstants::GetDefaultRegionData());
181 }
182 return *default_rule;
183 }
184
185 void Rule::CopyFrom(const Rule& rule) {
186 key_ = rule.key_;
187 name_ = rule.name_;
188 latin_name_ = rule.latin_name_;
189 format_ = rule.format_;
190 latin_format_ = rule.latin_format_;
191 required_ = rule.required_;
192 sub_keys_ = rule.sub_keys_;
193 languages_ = rule.languages_;
194 input_languages_ = rule.input_languages_;
195 language_ = rule.language_;
196 sub_keys_ = rule.sub_keys_;
197 sub_names_ = rule.sub_names_;
198 sub_lnames_ = rule.sub_lnames_;
199 postal_code_format_ = rule.postal_code_format_;
200 admin_area_name_type_ = rule.admin_area_name_type_;
201 postal_code_name_type_ = rule.postal_code_name_type_;
202 }
203
204 bool Rule::ParseSerializedRule(const std::string& serialized_rule) {
205 scoped_ptr<Json> json(Json::Build());
206 if (!json->ParseObject(serialized_rule)) {
207 return false;
208 }
209 ParseJsonRule(*json);
210 return true;
211 }
212
213 void Rule::ParseJsonRule(const Json& json_rule) {
214 std::string value;
215 if (json_rule.GetStringValueForKey("key", &value)) {
216 key_.swap(value);
217 }
218
219 if (json_rule.GetStringValueForKey("name", &value)) {
220 name_.swap(value);
221 }
222
223 if (json_rule.GetStringValueForKey("lname", &value)) {
224 latin_name_.swap(value);
225 }
226
227 if (json_rule.GetStringValueForKey("fmt", &value)) {
228 ParseAddressFieldsFormat(value, &format_);
229 }
230
231 if (json_rule.GetStringValueForKey("lfmt", &value)) {
232 ParseAddressFieldsFormat(value, &latin_format_);
233 }
234
235 if (json_rule.GetStringValueForKey("require", &value)) {
236 ParseAddressFieldsRequired(value, &required_);
237 }
238
239 // Used as a separator in a list of items. For example, the list of supported
240 // languages can be "de~fr~it".
241 static const char kSeparator = '~';
242 if (json_rule.GetStringValueForKey("sub_keys", &value)) {
243 SplitString(value, kSeparator, &sub_keys_);
244 }
245
246 if (json_rule.GetStringValueForKey("sub_names", &value)) {
247 SplitString(value, kSeparator, &sub_names_);
248 assert(sub_names_.size() == sub_keys_.size());
249 }
250
251 if (json_rule.GetStringValueForKey("sub_lnames", &value)) {
252 SplitString(value, kSeparator, &sub_lnames_);
253 assert(sub_lnames_.size() == sub_keys_.size());
254 }
255
256 if (json_rule.GetStringValueForKey("languages", &value)) {
257 SplitString(value, kSeparator, &languages_);
258 }
259
260 if (json_rule.GetStringValueForKey("input_languages", &value)) {
261 SplitString(value, kSeparator, &input_languages_);
262 }
263
264 if (json_rule.GetStringValueForKey("lang", &value)) {
265 language_.swap(value);
266 }
267
268 if (json_rule.GetStringValueForKey("zip", &value)) {
269 postal_code_format_.swap(value);
270 }
271
272 if (json_rule.GetStringValueForKey("state_name_type", &value)) {
273 admin_area_name_type_.swap(value);
274 }
275
276 if (json_rule.GetStringValueForKey("zip_name_type", &value)) {
277 postal_code_name_type_.swap(value);
278 }
279 }
280
281 const std::string& Rule::GetIdentityField(IdentityField identity_field) const {
282 switch (identity_field) {
283 case KEY:
284 return key_;
285 case NAME:
286 return name_;
287 case LATIN_NAME:
288 return latin_name_;
289 case IDENTITY_FIELDS_SIZE:
290 assert(false);
291 }
292 return key_;
293 }
294
295 bool Rule::CanonicalizeSubKey(const std::string& user_input,
296 bool keep_input_latin,
297 std::string* sub_key) const {
298 assert(sub_key != NULL);
299
300 if (sub_keys_.empty()) {
301 *sub_key = user_input;
302 return true;
303 }
304
305 return GetMatchingValue(user_input, sub_keys_, sub_keys_, sub_key) ||
306 GetMatchingValue(user_input, sub_names_, sub_keys_, sub_key) ||
307 (keep_input_latin &&
308 GetMatchingValue(user_input, sub_lnames_, sub_lnames_, sub_key)) ||
309 GetMatchingValue(user_input, sub_lnames_, sub_keys_, sub_key);
310 }
311
312 } // namespace addressinput
313 } // namespace i18n
OLDNEW
« no previous file with comments | « third_party/libaddressinput/chromium/cpp/src/rule.h ('k') | third_party/libaddressinput/chromium/cpp/src/ruleset.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698