1 // 2 // ip/basic_resolver_iterator.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP 12 #define ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP 13 14 15 #include "asio/detail/config.hpp" 16 #include <cstddef> 17 #include <cstring> 18 #include <iterator> 19 #include <string> 20 #include <vector> 21 #include "asio/detail/shared_ptr.hpp" 22 #include "asio/detail/socket_ops.hpp" 23 #include "asio/detail/socket_types.hpp" 24 #include "asio/ip/basic_resolver_entry.hpp" 25 26 27 #include "asio/detail/push_options.hpp" 28 29 namespace asio { 30 namespace ip { 31 32 /// An iterator over the entries produced by a resolver. 33 /** 34 * The asio::ip::basic_resolver_iterator class template is used to define 35 * iterators over the results returned by a resolver. 36 * 37 * The iterator's value_type, obtained when the iterator is dereferenced, is: 38 * @code const basic_resolver_entry<InternetProtocol> @endcode 39 * 40 * @par Thread Safety 41 * @e Distinct @e objects: Safe.@n 42 * @e Shared @e objects: Unsafe. 43 */ 44 template <typename InternetProtocol> 45 class basic_resolver_iterator 46 { 47 public: 48 /// The type used for the distance between two iterators. 49 typedef std::ptrdiff_t difference_type; 50 51 /// The type of the value pointed to by the iterator. 52 typedef basic_resolver_entry<InternetProtocol> value_type; 53 54 /// The type of the result of applying operator->() to the iterator. 55 typedef const basic_resolver_entry<InternetProtocol>* pointer; 56 57 /// The type of the result of applying operator*() to the iterator. 58 typedef const basic_resolver_entry<InternetProtocol>& reference; 59 60 /// The iterator category. 61 typedef std::forward_iterator_tag iterator_category; 62 63 /// Default constructor creates an end iterator. basic_resolver_iterator()64 basic_resolver_iterator() 65 : index_(0) 66 { 67 } 68 69 /// Create an iterator from an addrinfo list returned by getaddrinfo. create(asio::detail::addrinfo_type * address_info,const std::string & host_name,const std::string & service_name)70 static basic_resolver_iterator create( 71 asio::detail::addrinfo_type* address_info, 72 const std::string& host_name, const std::string& service_name) 73 { 74 basic_resolver_iterator iter; 75 if (!address_info) 76 return iter; 77 78 std::string actual_host_name = host_name; 79 if (address_info->ai_canonname) 80 actual_host_name = address_info->ai_canonname; 81 82 iter.values_.reset(new values_type); 83 84 while (address_info) 85 { 86 if (address_info->ai_family == ASIO_OS_DEF(AF_INET) 87 || address_info->ai_family == ASIO_OS_DEF(AF_INET6)) 88 { 89 using namespace std; // For memcpy. 90 typename InternetProtocol::endpoint endpoint; 91 endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen)); 92 memcpy(endpoint.data(), address_info->ai_addr, 93 address_info->ai_addrlen); 94 iter.values_->push_back( 95 basic_resolver_entry<InternetProtocol>(endpoint, 96 actual_host_name, service_name)); 97 } 98 address_info = address_info->ai_next; 99 } 100 101 return iter; 102 } 103 104 /// Create an iterator from an endpoint, host name and service name. create(const typename InternetProtocol::endpoint & endpoint,const std::string & host_name,const std::string & service_name)105 static basic_resolver_iterator create( 106 const typename InternetProtocol::endpoint& endpoint, 107 const std::string& host_name, const std::string& service_name) 108 { 109 basic_resolver_iterator iter; 110 iter.values_.reset(new values_type); 111 iter.values_->push_back( 112 basic_resolver_entry<InternetProtocol>( 113 endpoint, host_name, service_name)); 114 return iter; 115 } 116 117 /// Create an iterator from a sequence of endpoints, host and service name. 118 template <typename EndpointIterator> create(EndpointIterator begin,EndpointIterator end,const std::string & host_name,const std::string & service_name)119 static basic_resolver_iterator create( 120 EndpointIterator begin, EndpointIterator end, 121 const std::string& host_name, const std::string& service_name) 122 { 123 basic_resolver_iterator iter; 124 if (begin != end) 125 { 126 iter.values_.reset(new values_type); 127 for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter) 128 { 129 iter.values_->push_back( 130 basic_resolver_entry<InternetProtocol>( 131 *ep_iter, host_name, service_name)); 132 } 133 } 134 return iter; 135 } 136 137 138 /// Dereference an iterator. operator *() const139 const basic_resolver_entry<InternetProtocol>& operator*() const 140 { 141 return dereference(); 142 } 143 144 /// Dereference an iterator. operator ->() const145 const basic_resolver_entry<InternetProtocol>* operator->() const 146 { 147 return &dereference(); 148 } 149 150 /// Increment operator (prefix). operator ++()151 basic_resolver_iterator& operator++() 152 { 153 increment(); 154 return *this; 155 } 156 157 /// Increment operator (postfix). operator ++(int)158 basic_resolver_iterator operator++(int) 159 { 160 basic_resolver_iterator tmp(*this); 161 ++*this; 162 return tmp; 163 } 164 165 /// Test two iterators for equality. operator ==(const basic_resolver_iterator & a,const basic_resolver_iterator & b)166 friend bool operator==(const basic_resolver_iterator& a, 167 const basic_resolver_iterator& b) 168 { 169 return a.equal(b); 170 } 171 172 /// Test two iterators for inequality. operator !=(const basic_resolver_iterator & a,const basic_resolver_iterator & b)173 friend bool operator!=(const basic_resolver_iterator& a, 174 const basic_resolver_iterator& b) 175 { 176 return !a.equal(b); 177 } 178 179 private: increment()180 void increment() 181 { 182 if (++index_ == values_->size()) 183 { 184 // Reset state to match a default constructed end iterator. 185 values_.reset(); 186 index_ = 0; 187 } 188 } 189 equal(const basic_resolver_iterator & other) const190 bool equal(const basic_resolver_iterator& other) const 191 { 192 if (!values_ && !other.values_) 193 return true; 194 if (values_ != other.values_) 195 return false; 196 return index_ == other.index_; 197 } 198 dereference() const199 const basic_resolver_entry<InternetProtocol>& dereference() const 200 { 201 return (*values_)[index_]; 202 } 203 204 typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type; 205 asio::detail::shared_ptr<values_type> values_; 206 std::size_t index_; 207 }; 208 209 } // namespace ip 210 } // namespace asio 211 212 #include "asio/detail/pop_options.hpp" 213 214 #endif // ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP 215