1// Copyright (C) 2014 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 <libaddressinput/address_data.h> 16 17#include <libaddressinput/address_field.h> 18#include <libaddressinput/util/basictypes.h> 19 20#include <algorithm> 21#include <cassert> 22#include <cstddef> 23#include <functional> 24#include <ostream> 25#include <string> 26#include <vector> 27 28#include <re2/re2.h> 29 30namespace i18n { 31namespace addressinput { 32 33namespace { 34 35// Mapping from AddressField value to pointer to AddressData member. 36std::string AddressData::*kStringField[] = { 37 &AddressData::region_code, 38 &AddressData::administrative_area, 39 &AddressData::locality, 40 &AddressData::dependent_locality, 41 &AddressData::sorting_code, 42 &AddressData::postal_code, 43 NULL, 44 &AddressData::organization, 45 &AddressData::recipient 46}; 47 48// Mapping from AddressField value to pointer to AddressData member. 49const std::vector<std::string> AddressData::*kVectorStringField[] = { 50 NULL, 51 NULL, 52 NULL, 53 NULL, 54 NULL, 55 NULL, 56 &AddressData::address_line, 57 NULL, 58 NULL 59}; 60 61COMPILE_ASSERT(arraysize(kStringField) == arraysize(kVectorStringField), 62 field_mapping_array_size_mismatch); 63 64// A string is considered to be "empty" not only if it actually is empty, but 65// also if it contains nothing but whitespace. 66bool IsStringEmpty(const std::string& str) { 67 static const RE2 kMatcher("\\S"); 68 return str.empty() || !RE2::PartialMatch(str, kMatcher); 69} 70 71} // namespace 72 73bool AddressData::IsFieldEmpty(AddressField field) const { 74 assert(field >= 0); 75 assert(static_cast<size_t>(field) < arraysize(kStringField)); 76 if (kStringField[field] != NULL) { 77 const std::string& value = GetFieldValue(field); 78 return IsStringEmpty(value); 79 } else { 80 const std::vector<std::string>& value = GetRepeatedFieldValue(field); 81 return std::find_if(value.begin(), 82 value.end(), 83 std::not1(std::ptr_fun(&IsStringEmpty))) == value.end(); 84 } 85} 86 87const std::string& AddressData::GetFieldValue( 88 AddressField field) const { 89 assert(field >= 0); 90 assert(static_cast<size_t>(field) < arraysize(kStringField)); 91 assert(kStringField[field] != NULL); 92 return this->*kStringField[field]; 93} 94 95void AddressData::SetFieldValue(AddressField field, const std::string& value) { 96 assert(field >= 0); 97 assert(static_cast<size_t>(field) < arraysize(kStringField)); 98 assert(kStringField[field] != NULL); 99 (this->*kStringField[field]).assign(value); 100} 101 102const std::vector<std::string>& AddressData::GetRepeatedFieldValue( 103 AddressField field) const { 104 assert(IsRepeatedFieldValue(field)); 105 return this->*kVectorStringField[field]; 106} 107 108bool AddressData::operator==(const AddressData& other) const { 109 return region_code == other.region_code && 110 address_line == other.address_line && 111 administrative_area == other.administrative_area && 112 locality == other.locality && 113 dependent_locality == other.dependent_locality && 114 postal_code == other.postal_code && 115 sorting_code == other.sorting_code && 116 language_code == other.language_code && 117 organization == other.organization && 118 recipient == other.recipient; 119} 120 121// static 122bool AddressData::IsRepeatedFieldValue(AddressField field) { 123 assert(field >= 0); 124 assert(static_cast<size_t>(field) < arraysize(kVectorStringField)); 125 return kVectorStringField[field] != NULL; 126} 127 128} // namespace addressinput 129} // namespace i18n 130 131std::ostream& operator<<(std::ostream& o, 132 const i18n::addressinput::AddressData& address) { 133 o << "region_code: \"" << address.region_code << "\"\n" 134 "administrative_area: \"" << address.administrative_area << "\"\n" 135 "locality: \"" << address.locality << "\"\n" 136 "dependent_locality: \"" << address.dependent_locality << "\"\n" 137 "postal_code: \"" << address.postal_code << "\"\n" 138 "sorting_code: \"" << address.sorting_code << "\"\n"; 139 140 // TODO: Update the field order in the .h file to match the order they are 141 // printed out here, for consistency. 142 for (std::vector<std::string>::const_iterator it = 143 address.address_line.begin(); 144 it != address.address_line.end(); ++it) { 145 o << "address_line: \"" << *it << "\"\n"; 146 } 147 148 o << "language_code: \"" << address.language_code << "\"\n" 149 "organization: \"" << address.organization << "\"\n" 150 "recipient: \"" << address.recipient << "\"\n"; 151 152 return o; 153} 154