aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrouslan@chromium.org <rouslan@chromium.org@38ededc0-08b8-5190-f2ac-b31f878777ad>2014-07-31 17:15:09 +0000
committerrouslan@chromium.org <rouslan@chromium.org@38ededc0-08b8-5190-f2ac-b31f878777ad>2014-07-31 17:15:09 +0000
commita11ee5fbaa1a2b6d2bc4424c72e532ef61e43e2d (patch)
tree86e82909b1091220847b77b858159b94354d7f2a
parent3be90f9591d5839b396ca633c5816316e1e72bdd (diff)
downloadsrc-a11ee5fbaa1a2b6d2bc4424c72e532ef61e43e2d.tar.gz
Formatting partial addresses.
This patch formats partial addressess, which can be used in chrome://settings/autofill to display a list of addresses with incomplete data, for example. Sample outputs: "CH-8001 Zurich" "CH-8001" "Zurich" "Los Angeles, CA 90291" "Los Angeles, CA" "CA 90291" "Los Angeles 90291" "90291" "Los Angeles" "CA 90291" R=lararennie@google.com, roubert@google.com Review URL: https://codereview.appspot.com/117900044 git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@324 38ededc0-08b8-5190-f2ac-b31f878777ad
-rw-r--r--cpp/src/address_formatter.cc52
-rw-r--r--cpp/test/address_formatter_test.cc144
2 files changed, 186 insertions, 10 deletions
diff --git a/cpp/src/address_formatter.cc b/cpp/src/address_formatter.cc
index 8d416d1..b54cbac 100644
--- a/cpp/src/address_formatter.cc
+++ b/cpp/src/address_formatter.cc
@@ -100,10 +100,10 @@ std::string GetLineSeparatorForLanguage(const std::string& language_tag) {
arraysize(kLanguagesThatUseAnArabicComma)) {
return kArabicCommaSeparator;
}
- // Either the language is a latin-script language, or no language was
+ // Either the language is a Latin-script language, or no language was
// specified. In the latter case we still return ", " as the most common
// separator in use. In countries that don't use this, e.g. Thailand,
- // addresses are often written in latin script where this would still be
+ // addresses are often written in Latin script where this would still be
// appropriate, so this is a reasonable default in the absence of information.
return kCommaSeparator;
}
@@ -139,23 +139,55 @@ void GetFormattedNationalAddress(
Language language(address_data.language_code);
- // If latinized rules are available and the |language_code| of this address is
- // explicitly tagged as being Latin, then use the latinized formatting rules.
+ // If Latin-script rules are available and the |language_code| of this address
+ // is explicitly tagged as being Latin, then use the Latin-script formatting
+ // rules.
const std::vector<FormatElement>& format =
language.has_latin_script && !rule.GetLatinFormat().empty()
? rule.GetLatinFormat()
: rule.GetFormat();
+ // Address format without the unnecessary elements (based on which address
+ // fields are empty). We assume all literal strings that are not at the start
+ // or end of a line are separators, and therefore only relevant if the
+ // surrounding fields are filled in. This works with the data we have
+ // currently.
+ std::vector<FormatElement> pruned_format;
+ for (std::vector<FormatElement>::const_iterator
+ element_it = format.begin();
+ element_it != format.end();
+ ++element_it) {
+ // Always keep the newlines.
+ if (element_it->IsNewline() ||
+ // Always keep the non-empty address fields.
+ (element_it->IsField() &&
+ !address_data.IsFieldEmpty(element_it->GetField())) ||
+ // Only keep literals that satisfy these 2 conditions:
+ (!element_it->IsField() &&
+ // (1) Not preceding an empty field.
+ (element_it + 1 == format.end() ||
+ !(element_it + 1)->IsField() ||
+ !address_data.IsFieldEmpty((element_it + 1)->GetField())) &&
+ // (2) Not following a removed field.
+ (element_it == format.begin() ||
+ !(element_it - 1)->IsField() ||
+ (!pruned_format.empty() && pruned_format.back().IsField())))) {
+ pruned_format.push_back(*element_it);
+ }
+ }
+
std::string line;
- for (size_t i = 0; i < format.size(); ++i) {
- FormatElement element = format[i];
- if (element.IsNewline()) {
+ for (std::vector<FormatElement>::const_iterator
+ element_it = pruned_format.begin();
+ element_it != pruned_format.end();
+ ++element_it) {
+ if (element_it->IsNewline()) {
if (!line.empty()) {
lines->push_back(line);
line.clear();
}
- } else if (element.IsField()) {
- AddressField field = element.GetField();
+ } else if (element_it->IsField()) {
+ AddressField field = element_it->GetField();
if (field == STREET_ADDRESS) {
// The field "street address" represents the street address lines of an
// address, so there can be multiple values.
@@ -173,7 +205,7 @@ void GetFormattedNationalAddress(
line.append(address_data.GetFieldValue(field));
}
} else {
- line.append(element.GetLiteral());
+ line.append(element_it->GetLiteral());
}
}
if (!line.empty()) {
diff --git a/cpp/test/address_formatter_test.cc b/cpp/test/address_formatter_test.cc
index 5422492..c656ec8 100644
--- a/cpp/test/address_formatter_test.cc
+++ b/cpp/test/address_formatter_test.cc
@@ -220,4 +220,148 @@ TEST(AddressFormatterTest, GetFormattedNationalAddress_InlineStreetAddress) {
EXPECT_EQ(expected, lines);
}
+TEST(AddressFormatterTest,
+ GetFormattedNationalAddressMissingFields_LiteralsAroundField) {
+ AddressData address;
+ address.region_code = "CH";
+ std::vector<std::string> expected;
+ std::vector<std::string> lines;
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.locality = "Zurich";
+ expected.push_back("Zurich");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.postal_code = "8001";
+ expected.back().assign("CH-8001 Zurich");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.locality.clear();
+ expected.back().assign("CH-8001");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
+ GetFormattedNationalAddressMissingFields_LiteralsBetweenFields) {
+ AddressData address;
+ address.region_code = "US";
+ std::vector<std::string> expected;
+ std::vector<std::string> lines;
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.administrative_area = "CA";
+ expected.push_back("CA");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.locality = "Los Angeles";
+ expected.back().assign("Los Angeles, CA");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.postal_code = "90291";
+ expected.back().assign("Los Angeles, CA 90291");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.administrative_area.clear();
+ expected.back().assign("Los Angeles 90291");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.locality.clear();
+ address.administrative_area = "CA";
+ expected.back().assign("CA 90291");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
+ GetFormattedNationalAddressMissingFields_LiteralOnSeparateLine) {
+ AddressData address;
+ address.region_code = "AX";
+ std::vector<std::string> expected;
+ expected.push_back("\xC3\x85LAND"); /* ÅLAND */
+ std::vector<std::string> lines;
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.locality = "City";
+ expected.insert(expected.begin(), "City");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.postal_code = "123";
+ expected.front().assign("AX-123 City");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
+ GetFormattedNationalAddressMissingFields_LiteralBeforeField) {
+ AddressData address;
+ address.region_code = "JP";
+ address.language_code = "ja";
+ std::vector<std::string> expected;
+ std::vector<std::string> lines;
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.postal_code = "123";
+ expected.push_back("\xE3\x80\x92" "123"); /* 〒123 */
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.administrative_area = "Prefecture";
+ expected.push_back("Prefecture");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.postal_code.clear();
+ expected.erase(expected.begin());
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
+ GetFormattedNationalAddressMissingFields_DuplicateField) {
+ AddressData address;
+ address.region_code = "CI";
+ std::vector<std::string> expected;
+ std::vector<std::string> lines;
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.sorting_code = "123";
+ expected.push_back("123 123");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.address_line.push_back("456 Main St");
+ expected.back().assign("123 456 Main St 123");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.locality = "Yamoussoukro";
+ expected.back().assign("123 456 Main St Yamoussoukro 123");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.sorting_code.erase();
+ expected.back().assign("456 Main St Yamoussoukro");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+
+ address.address_line.clear();
+ expected.back().assign("Yamoussoukro");
+ GetFormattedNationalAddress(address, &lines);
+ EXPECT_EQ(expected, lines);
+}
+
+
} // namespace