• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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