Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / asio / ip / basic_resolver_iterator.hpp
1 //
2 // ip/basic_resolver_iterator.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2017 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 BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP
12 #define BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP
13
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18 #include <boost/asio/detail/config.hpp>
19 #include <cstddef>
20 #include <cstring>
21 #include <iterator>
22 #include <string>
23 #include <vector>
24 #include <boost/asio/detail/shared_ptr.hpp>
25 #include <boost/asio/detail/socket_ops.hpp>
26 #include <boost/asio/detail/socket_types.hpp>
27 #include <boost/asio/ip/basic_resolver_entry.hpp>
28
29 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
30 # include <boost/asio/detail/winrt_utils.hpp>
31 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
32
33 #include <boost/asio/detail/push_options.hpp>
34
35 namespace boost {
36 namespace asio {
37 namespace ip {
38
39 /// An iterator over the entries produced by a resolver.
40 /**
41  * The boost::asio::ip::basic_resolver_iterator class template is used to define
42  * iterators over the results returned by a resolver.
43  *
44  * The iterator's value_type, obtained when the iterator is dereferenced, is:
45  * @code const basic_resolver_entry<InternetProtocol> @endcode
46  *
47  * @par Thread Safety
48  * @e Distinct @e objects: Safe.@n
49  * @e Shared @e objects: Unsafe.
50  */
51 template <typename InternetProtocol>
52 class basic_resolver_iterator
53 {
54 public:
55   /// The type used for the distance between two iterators.
56   typedef std::ptrdiff_t difference_type;
57
58   /// The type of the value pointed to by the iterator.
59   typedef basic_resolver_entry<InternetProtocol> value_type;
60
61   /// The type of the result of applying operator->() to the iterator.
62   typedef const basic_resolver_entry<InternetProtocol>* pointer;
63
64   /// The type of the result of applying operator*() to the iterator.
65   typedef const basic_resolver_entry<InternetProtocol>& reference;
66
67   /// The iterator category.
68   typedef std::forward_iterator_tag iterator_category;
69
70   /// Default constructor creates an end iterator.
71   basic_resolver_iterator()
72     : index_(0)
73   {
74   }
75
76   /// Create an iterator from an addrinfo list returned by getaddrinfo.
77   static basic_resolver_iterator create(
78       boost::asio::detail::addrinfo_type* address_info,
79       const std::string& host_name, const std::string& service_name)
80   {
81     basic_resolver_iterator iter;
82     if (!address_info)
83       return iter;
84
85     std::string actual_host_name = host_name;
86     if (address_info->ai_canonname)
87       actual_host_name = address_info->ai_canonname;
88
89     iter.values_.reset(new values_type);
90
91     while (address_info)
92     {
93       if (address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET)
94           || address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET6))
95       {
96         using namespace std; // For memcpy.
97         typename InternetProtocol::endpoint endpoint;
98         endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen));
99         memcpy(endpoint.data(), address_info->ai_addr,
100             address_info->ai_addrlen);
101         iter.values_->push_back(
102             basic_resolver_entry<InternetProtocol>(endpoint,
103               actual_host_name, service_name));
104       }
105       address_info = address_info->ai_next;
106     }
107
108     return iter;
109   }
110
111   /// Create an iterator from an endpoint, host name and service name.
112   static basic_resolver_iterator create(
113       const typename InternetProtocol::endpoint& endpoint,
114       const std::string& host_name, const std::string& service_name)
115   {
116     basic_resolver_iterator iter;
117     iter.values_.reset(new values_type);
118     iter.values_->push_back(
119         basic_resolver_entry<InternetProtocol>(
120           endpoint, host_name, service_name));
121     return iter;
122   }
123
124   /// Create an iterator from a sequence of endpoints, host and service name.
125   template <typename EndpointIterator>
126   static basic_resolver_iterator create(
127       EndpointIterator begin, EndpointIterator end,
128       const std::string& host_name, const std::string& service_name)
129   {
130     basic_resolver_iterator iter;
131     if (begin != end)
132     {
133       iter.values_.reset(new values_type);
134       for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter)
135       {
136         iter.values_->push_back(
137             basic_resolver_entry<InternetProtocol>(
138               *ep_iter, host_name, service_name));
139       }
140     }
141     return iter;
142   }
143
144 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
145   /// Create an iterator from a Windows Runtime list of EndpointPair objects.
146   static basic_resolver_iterator create(
147       Windows::Foundation::Collections::IVectorView<
148         Windows::Networking::EndpointPair^>^ endpoints,
149       const boost::asio::detail::addrinfo_type& hints,
150       const std::string& host_name, const std::string& service_name)
151   {
152     basic_resolver_iterator iter;
153     if (endpoints->Size)
154     {
155       iter.values_.reset(new values_type);
156       for (unsigned int i = 0; i < endpoints->Size; ++i)
157       {
158         auto pair = endpoints->GetAt(i);
159
160         if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET)
161             && pair->RemoteHostName->Type
162               != Windows::Networking::HostNameType::Ipv4)
163           continue;
164
165         if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET6)
166             && pair->RemoteHostName->Type
167               != Windows::Networking::HostNameType::Ipv6)
168           continue;
169
170         iter.values_->push_back(
171             basic_resolver_entry<InternetProtocol>(
172               typename InternetProtocol::endpoint(
173                 ip::address::from_string(
174                   boost::asio::detail::winrt_utils::string(
175                     pair->RemoteHostName->CanonicalName)),
176                 boost::asio::detail::winrt_utils::integer(
177                   pair->RemoteServiceName)),
178               host_name, service_name));
179       }
180     }
181     return iter;
182   }
183 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
184
185   /// Dereference an iterator.
186   const basic_resolver_entry<InternetProtocol>& operator*() const
187   {
188     return dereference();
189   }
190
191   /// Dereference an iterator.
192   const basic_resolver_entry<InternetProtocol>* operator->() const
193   {
194     return &dereference();
195   }
196
197   /// Increment operator (prefix).
198   basic_resolver_iterator& operator++()
199   {
200     increment();
201     return *this;
202   }
203
204   /// Increment operator (postfix).
205   basic_resolver_iterator operator++(int)
206   {
207     basic_resolver_iterator tmp(*this);
208     ++*this;
209     return tmp;
210   }
211
212   /// Test two iterators for equality.
213   friend bool operator==(const basic_resolver_iterator& a,
214       const basic_resolver_iterator& b)
215   {
216     return a.equal(b);
217   }
218
219   /// Test two iterators for inequality.
220   friend bool operator!=(const basic_resolver_iterator& a,
221       const basic_resolver_iterator& b)
222   {
223     return !a.equal(b);
224   }
225
226 private:
227   void increment()
228   {
229     if (++index_ == values_->size())
230     {
231       // Reset state to match a default constructed end iterator.
232       values_.reset();
233       index_ = 0;
234     }
235   }
236
237   bool equal(const basic_resolver_iterator& other) const
238   {
239     if (!values_ && !other.values_)
240       return true;
241     if (values_ != other.values_)
242       return false;
243     return index_ == other.index_;
244   }
245
246   const basic_resolver_entry<InternetProtocol>& dereference() const
247   {
248     return (*values_)[index_];
249   }
250
251   typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
252   boost::asio::detail::shared_ptr<values_type> values_;
253   std::size_t index_;
254 };
255
256 } // namespace ip
257 } // namespace asio
258 } // namespace boost
259
260 #include <boost/asio/detail/pop_options.hpp>
261
262 #endif // BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP