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