diff options
author | rouslan@chromium.org <rouslan@chromium.org@38ededc0-08b8-5190-f2ac-b31f878777ad> | 2014-07-31 17:15:09 +0000 |
---|---|---|
committer | rouslan@chromium.org <rouslan@chromium.org@38ededc0-08b8-5190-f2ac-b31f878777ad> | 2014-07-31 17:15:09 +0000 |
commit | a11ee5fbaa1a2b6d2bc4424c72e532ef61e43e2d (patch) | |
tree | 86e82909b1091220847b77b858159b94354d7f2a | |
parent | 3be90f9591d5839b396ca633c5816316e1e72bdd (diff) | |
download | src-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.cc | 52 | ||||
-rw-r--r-- | cpp/test/address_formatter_test.cc | 144 |
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 |