1e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// Copyright (C) 2014 Google Inc. 2e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// 3e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// Licensed under the Apache License, Version 2.0 (the "License"); 4e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// you may not use this file except in compliance with the License. 5e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// You may obtain a copy of the License at 6e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// 7e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// http://www.apache.org/licenses/LICENSE-2.0 8e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// 9e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// Unless required by applicable law or agreed to in writing, software 10e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// distributed under the License is distributed on an "AS IS" BASIS, 11e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// See the License for the specific language governing permissions and 13e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// limitations under the License. 14e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 15e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <libaddressinput/address_data.h> 16e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 17e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <libaddressinput/address_field.h> 18e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <libaddressinput/util/basictypes.h> 19e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 20e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <algorithm> 21e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <cassert> 22e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <cstddef> 23e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <functional> 246e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com#include <ostream> 25e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <string> 26e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <vector> 27e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 28ea5e77397b59d94af3591644c3dc23dc6f9ba22eroubert@google.com#include <re2/re2.h> 29ea5e77397b59d94af3591644c3dc23dc6f9ba22eroubert@google.com 30e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comnamespace i18n { 31e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comnamespace addressinput { 32e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 33e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comnamespace { 34e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 35e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// Mapping from AddressField value to pointer to AddressData member. 362fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.orgstd::string AddressData::*kStringField[] = { 37e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com &AddressData::region_code, 38e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com &AddressData::administrative_area, 39e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com &AddressData::locality, 40e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com &AddressData::dependent_locality, 41e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com &AddressData::sorting_code, 42e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com &AddressData::postal_code, 43e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com NULL, 44b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org &AddressData::organization, 45e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com &AddressData::recipient 46e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com}; 47e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 48e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// Mapping from AddressField value to pointer to AddressData member. 49e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comconst std::vector<std::string> AddressData::*kVectorStringField[] = { 50e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com NULL, 51e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com NULL, 52e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com NULL, 53e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com NULL, 54e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com NULL, 55e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com NULL, 56e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com &AddressData::address_line, 57b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org NULL, 58e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com NULL 59e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com}; 60e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 61e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comCOMPILE_ASSERT(arraysize(kStringField) == arraysize(kVectorStringField), 62e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com field_mapping_array_size_mismatch); 63e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 64ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com// A string is considered to be "empty" not only if it actually is empty, but 65ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com// also if it contains nothing but whitespace. 66ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.combool IsStringEmpty(const std::string& str) { 67ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com static const RE2 kMatcher("\\S"); 68ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com return str.empty() || !RE2::PartialMatch(str, kMatcher); 69ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com} 70ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com 71e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com} // namespace 72e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 73e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.combool AddressData::IsFieldEmpty(AddressField field) const { 74e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com assert(field >= 0); 75e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com assert(static_cast<size_t>(field) < arraysize(kStringField)); 76e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com if (kStringField[field] != NULL) { 77e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com const std::string& value = GetFieldValue(field); 78ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com return IsStringEmpty(value); 79e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com } else { 80e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com const std::vector<std::string>& value = GetRepeatedFieldValue(field); 81000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com return std::find_if(value.begin(), 82000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com value.end(), 83000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com std::not1(std::ptr_fun(&IsStringEmpty))) == value.end(); 84e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com } 85e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com} 86e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 87e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comconst std::string& AddressData::GetFieldValue( 88e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com AddressField field) const { 89e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com assert(field >= 0); 90e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com assert(static_cast<size_t>(field) < arraysize(kStringField)); 91e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com assert(kStringField[field] != NULL); 92e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com return this->*kStringField[field]; 93e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com} 94e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 952fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.orgvoid AddressData::SetFieldValue(AddressField field, const std::string& value) { 962fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org assert(field >= 0); 972fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org assert(static_cast<size_t>(field) < arraysize(kStringField)); 982fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org assert(kStringField[field] != NULL); 992fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org (this->*kStringField[field]).assign(value); 1002fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org} 1012fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org 102e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comconst std::vector<std::string>& AddressData::GetRepeatedFieldValue( 103e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com AddressField field) const { 104b61f18aac9eba56eff3bae712371924567f89d15roubert@google.com assert(IsRepeatedFieldValue(field)); 105e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com return this->*kVectorStringField[field]; 106e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com} 107e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com 1086e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.combool AddressData::operator==(const AddressData& other) const { 109000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com return region_code == other.region_code && 110000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com address_line == other.address_line && 111000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com administrative_area == other.administrative_area && 112000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com locality == other.locality && 113000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com dependent_locality == other.dependent_locality && 114000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com postal_code == other.postal_code && 115000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com sorting_code == other.sorting_code && 116b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org language_code == other.language_code && 117b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org organization == other.organization && 118b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org recipient == other.recipient; 1196e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com} 1206e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com 121e66bf12636bf12067bd8b199b8e6c1035315d2aakeghani@google.com// static 122e66bf12636bf12067bd8b199b8e6c1035315d2aakeghani@google.combool AddressData::IsRepeatedFieldValue(AddressField field) { 123b61f18aac9eba56eff3bae712371924567f89d15roubert@google.com assert(field >= 0); 124b61f18aac9eba56eff3bae712371924567f89d15roubert@google.com assert(static_cast<size_t>(field) < arraysize(kVectorStringField)); 125b61f18aac9eba56eff3bae712371924567f89d15roubert@google.com return kVectorStringField[field] != NULL; 126e66bf12636bf12067bd8b199b8e6c1035315d2aakeghani@google.com} 127e66bf12636bf12067bd8b199b8e6c1035315d2aakeghani@google.com 128e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com} // namespace addressinput 129e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com} // namespace i18n 1306e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com 1316e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.comstd::ostream& operator<<(std::ostream& o, 1326e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com const i18n::addressinput::AddressData& address) { 1336e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com o << "region_code: \"" << address.region_code << "\"\n" 1346e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com "administrative_area: \"" << address.administrative_area << "\"\n" 1356e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com "locality: \"" << address.locality << "\"\n" 1366e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com "dependent_locality: \"" << address.dependent_locality << "\"\n" 1376e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com "postal_code: \"" << address.postal_code << "\"\n" 1386e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com "sorting_code: \"" << address.sorting_code << "\"\n"; 1396e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com 1406e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com // TODO: Update the field order in the .h file to match the order they are 1416e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com // printed out here, for consistency. 1426e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com for (std::vector<std::string>::const_iterator it = 1436e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com address.address_line.begin(); 1446e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com it != address.address_line.end(); ++it) { 1456e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com o << "address_line: \"" << *it << "\"\n"; 1466e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com } 1476e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com 1486e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com o << "language_code: \"" << address.language_code << "\"\n" 149b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org "organization: \"" << address.organization << "\"\n" 1506e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com "recipient: \"" << address.recipient << "\"\n"; 1516e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com 1526e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com return o; 1536e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com} 154