From e44b60b2f13cd40ca783937f0b1a418bd8510921 Mon Sep 17 00:00:00 2001 From: "rouslan@chromium.org" Date: Thu, 14 Nov 2013 23:04:51 +0000 Subject: [cpp] Address fields This patch is part of a series of patches that enable showing an address input form. This patch adds an AddressField enum and functions to parse it from a format string. git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@157 38ededc0-08b8-5190-f2ac-b31f878777ad --- cpp/include/libaddressinput/address_field.h | 46 ++++++++++++++++ cpp/libaddressinput.gyp | 3 ++ cpp/src/address_field.cc | 59 ++++++++++++++++++++ cpp/src/address_field_util.cc | 83 +++++++++++++++++++++++++++++ cpp/src/address_field_util.h | 42 +++++++++++++++ cpp/test/address_field_util_test.cc | 73 +++++++++++++++++++++++++ 6 files changed, 306 insertions(+) create mode 100644 cpp/include/libaddressinput/address_field.h create mode 100644 cpp/src/address_field.cc create mode 100644 cpp/src/address_field_util.cc create mode 100644 cpp/src/address_field_util.h create mode 100644 cpp/test/address_field_util_test.cc diff --git a/cpp/include/libaddressinput/address_field.h b/cpp/include/libaddressinput/address_field.h new file mode 100644 index 0000000..aed7332 --- /dev/null +++ b/cpp/include/libaddressinput/address_field.h @@ -0,0 +1,46 @@ +// Copyright (C) 2013 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef I18N_ADDRESSINPUT_ADDRESS_FIELD_H_ +#define I18N_ADDRESSINPUT_ADDRESS_FIELD_H_ + +#include + +namespace i18n { +namespace addressinput { + +// Address field types, ordered by size, from largest to smallest. +enum AddressField { + COUNTRY, // Country code. + ADMIN_AREA, // Administrative area such as a state, province, + // island, etc. + LOCALITY, // City or locality. + DEPENDENT_LOCALITY, // Dependent locality (may be an inner-city district or + // a suburb). + SORTING_CODE, // Sorting code. + POSTAL_CODE, // Zip or postal code. + STREET_ADDRESS, // Street address lines. + ORGANIZATION, // Organization. + RECIPIENT // Name. +}; + +// Produces human-readable output in logging, for example in unit tests. Prints +// what you would expect for valid fields, e.g. "COUNTRY" for COUNTRY. For +// invalid values, prints "[INVALID]". +std::ostream& operator<<(std::ostream& o, AddressField field); + +} // namespace addressinput +} // namespace i18n + +#endif // I18N_ADDRESSINPUT_ADDRESS_FIELD_H_ diff --git a/cpp/libaddressinput.gyp b/cpp/libaddressinput.gyp index 2574bd8..a9dbe99 100644 --- a/cpp/libaddressinput.gyp +++ b/cpp/libaddressinput.gyp @@ -31,6 +31,8 @@ 'target_name': 'libaddressinput', 'type': '<(component)', 'sources': [ + 'src/address_field.cc', + 'src/address_field_util.cc', 'src/region_data_constants.cc', 'src/util/json.cc', ], @@ -43,6 +45,7 @@ 'target_name': 'unit_tests', 'type': 'executable', 'sources': [ + 'test/address_field_util_test.cc', 'test/region_data_constants_test.cc', 'test/util/json_test.cc', ], diff --git a/cpp/src/address_field.cc b/cpp/src/address_field.cc new file mode 100644 index 0000000..92360ee --- /dev/null +++ b/cpp/src/address_field.cc @@ -0,0 +1,59 @@ +// Copyright (C) 2013 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include + +namespace i18n { +namespace addressinput { + +std::ostream& operator<<(std::ostream& o, AddressField field) { + switch (field) { + case COUNTRY: + o << "COUNTRY"; + break; + case ADMIN_AREA: + o << "ADMIN_AREA"; + break; + case LOCALITY: + o << "LOCALITY"; + break; + case DEPENDENT_LOCALITY: + o << "DEPENDENT_LOCALITY"; + break; + case SORTING_CODE: + o << "SORTING_CODE"; + break; + case POSTAL_CODE: + o << "POSTAL_CODE"; + break; + case STREET_ADDRESS: + o << "STREET_ADDRESS"; + break; + case ORGANIZATION: + o << "ORGANIZATION"; + break; + case RECIPIENT: + o << "RECIPIENT"; + break; + default: + o << "[INVALID]"; + break; + } + return o; +} + +} // namespace addressinput +} // namespace i18n diff --git a/cpp/src/address_field_util.cc b/cpp/src/address_field_util.cc new file mode 100644 index 0000000..cb14794 --- /dev/null +++ b/cpp/src/address_field_util.cc @@ -0,0 +1,83 @@ +// Copyright (C) 2013 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "address_field_util.h" + +#include + +#include +#include +#include +#include +#include + +namespace i18n { +namespace addressinput { + +namespace { + +std::map InitFields() { + std::map fields; + fields.insert(std::make_pair('R', COUNTRY)); + fields.insert(std::make_pair('S', ADMIN_AREA)); + fields.insert(std::make_pair('C', LOCALITY)); + fields.insert(std::make_pair('D', DEPENDENT_LOCALITY)); + fields.insert(std::make_pair('x', SORTING_CODE)); + fields.insert(std::make_pair('Z', POSTAL_CODE)); + fields.insert(std::make_pair('A', STREET_ADDRESS)); + fields.insert(std::make_pair('O', ORGANIZATION)); + fields.insert(std::make_pair('N', RECIPIENT)); + // An extension of AddressField enum used only internally: + fields.insert(std::make_pair( + 'n', static_cast(NEWLINE))); + return fields; +} + +const std::map& GetFields() { + static const std::map kFields(InitFields()); + return kFields; +} + +bool IsTokenPrefix(char c) { + return c == '%'; +} + +bool IsToken(char c) { + return GetFields().find(c) != GetFields().end(); +} + +AddressField ParseToken(char c) { + std::map::const_iterator it = GetFields().find(c); + assert(it != GetFields().end()); + return it->second; +} + +} // namespace + +void ParseAddressFieldsFormat(const std::string& format, + std::vector* fields) { + assert(fields != NULL); + fields->clear(); + for (std::string::const_iterator current = format.begin(), + next = format.begin() + 1; + current != format.end() && next != format.end(); + ++current, ++next) { + if (IsTokenPrefix(*current) && IsToken(*next)) { + fields->push_back(ParseToken(*next)); + } + } +} + +} // namespace addressinput +} // namespace i18n diff --git a/cpp/src/address_field_util.h b/cpp/src/address_field_util.h new file mode 100644 index 0000000..e55b950 --- /dev/null +++ b/cpp/src/address_field_util.h @@ -0,0 +1,42 @@ +// Copyright (C) 2013 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef I18N_ADDRESSINPUT_ADDRESS_FIELD_UTIL_H_ +#define I18N_ADDRESSINPUT_ADDRESS_FIELD_UTIL_H_ + +#include + +#include +#include + +namespace i18n { +namespace addressinput { + +// An extension of AddressField enum used only internally. The values are +// negative to avoid clashing with the values in AddressField. +enum { + NEWLINE = -1 +}; + +// Clears |fields|, parses |format|, and adds the format address fields to +// |fields|. The |fields| may also contain NEWLINE elements. For example, parses +// "%S%C%n%D%X" into {ADMIN_AREA, LOCALITY, NEWLINE, DEPENDENT_LOCALITY, +// SORTING_CODE}. +void ParseAddressFieldsFormat(const std::string& format, + std::vector* fields); + +} // namespace addressinput +} // namespace i18n + +#endif // I18N_ADDRESSINPUT_ADDRESS_FIELD_UTIL_H_ diff --git a/cpp/test/address_field_util_test.cc b/cpp/test/address_field_util_test.cc new file mode 100644 index 0000000..ce2ad77 --- /dev/null +++ b/cpp/test/address_field_util_test.cc @@ -0,0 +1,73 @@ +// Copyright (C) 2013 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "address_field_util.h" + +#include + +#include +#include + +#include + +namespace { + +using i18n::addressinput::AddressField; +using i18n::addressinput::COUNTRY; +using i18n::addressinput::LOCALITY; +using i18n::addressinput::NEWLINE; +using i18n::addressinput::ORGANIZATION; +using i18n::addressinput::ParseAddressFieldsFormat; +using i18n::addressinput::POSTAL_CODE; +using i18n::addressinput::RECIPIENT; +using i18n::addressinput::STREET_ADDRESS; + +TEST(AddressFieldUtilTest, ParseNewlineFormat) { + std::vector actual; + ParseAddressFieldsFormat("%O%n%N%n%A%nAX-%Z %C%nĂ…LAND", &actual); + + std::vector expected; + expected.push_back(ORGANIZATION); + expected.push_back(static_cast(NEWLINE)); + expected.push_back(RECIPIENT); + expected.push_back(static_cast(NEWLINE)); + expected.push_back(STREET_ADDRESS); + expected.push_back(static_cast(NEWLINE)); + expected.push_back(POSTAL_CODE); + expected.push_back(LOCALITY); + expected.push_back(static_cast(NEWLINE)); + + EXPECT_EQ(expected, actual); +} + +TEST(AddressFieldUtilTest, DoubleTokenPrefixIsIgnored) { + std::vector actual; + ParseAddressFieldsFormat("%%R", &actual); + std::vector expected(1, COUNTRY); + EXPECT_EQ(expected, actual); +} + +TEST(AddressFieldUtilTest, PrefixWithoutTokenIsIgnored) { + std::vector actual; + ParseAddressFieldsFormat("%", &actual); + EXPECT_TRUE(actual.empty()); +} + +TEST(AddressFieldUtilTest, EmptyString) { + std::vector fields; + ParseAddressFieldsFormat(std::string(), &fields); + EXPECT_TRUE(fields.empty()); +} + +} // namespace -- cgit v1.2.3