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 30 namespace i18n { 31 namespace addressinput { 32 33 namespace { 34 35 // Mapping from AddressField value to pointer to AddressData member. 36 std::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. 49 const 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 61 COMPILE_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. 66 bool IsStringEmpty(const std::string& str) { 67 static const RE2 kMatcher("\\S"); 68 return str.empty() || !RE2::PartialMatch(str, kMatcher); 69 } 70 71 } // namespace 72 73 bool 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 87 const 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 95 void 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 102 const std::vector<std::string>& AddressData::GetRepeatedFieldValue( 103 AddressField field) const { 104 assert(IsRepeatedFieldValue(field)); 105 return this->*kVectorStringField[field]; 106 } 107 108 bool 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 122 bool 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 131 std::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