Home | History | Annotate | Download | only in ip
      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.
     64   basic_resolver_iterator()
     65     : index_(0)
     66   {
     67   }
     68 
     69   /// Create an iterator from an addrinfo list returned by getaddrinfo.
     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.
    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>
    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.
    139   const basic_resolver_entry<InternetProtocol>& operator*() const
    140   {
    141     return dereference();
    142   }
    143 
    144   /// Dereference an iterator.
    145   const basic_resolver_entry<InternetProtocol>* operator->() const
    146   {
    147     return &dereference();
    148   }
    149 
    150   /// Increment operator (prefix).
    151   basic_resolver_iterator& operator++()
    152   {
    153     increment();
    154     return *this;
    155   }
    156 
    157   /// Increment operator (postfix).
    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.
    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.
    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:
    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 
    190   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 
    199   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