| // |
| // ip/basic_resolver_iterator.hpp |
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| // |
| // Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
| // |
| // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| // |
| |
| #ifndef BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP |
| #define BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
| # pragma once |
| #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
| |
| #include <boost/asio/detail/config.hpp> |
| #include <boost/iterator.hpp> |
| #include <cstring> |
| #include <string> |
| #include <vector> |
| #include <boost/asio/detail/shared_ptr.hpp> |
| #include <boost/asio/detail/socket_ops.hpp> |
| #include <boost/asio/detail/socket_types.hpp> |
| #include <boost/asio/ip/basic_resolver_entry.hpp> |
| |
| #include <boost/asio/detail/push_options.hpp> |
| |
| namespace boost { |
| namespace asio { |
| namespace ip { |
| |
| /// An iterator over the entries produced by a resolver. |
| /** |
| * The boost::asio::ip::basic_resolver_iterator class template is used to define |
| * iterators over the results returned by a resolver. |
| * |
| * The iterator's value_type, obtained when the iterator is dereferenced, is: |
| * @code const basic_resolver_entry<InternetProtocol> @endcode |
| * |
| * @par Thread Safety |
| * @e Distinct @e objects: Safe.@n |
| * @e Shared @e objects: Unsafe. |
| */ |
| template <typename InternetProtocol> |
| class basic_resolver_iterator |
| #if defined(GENERATING_DOCUMENTATION) |
| : public std::iterator< |
| #else // defined(GENERATING_DOCUMENTATION) |
| : public boost::iterator< |
| #endif // defined(GENERATING_DOCUMENTATION) |
| std::forward_iterator_tag, |
| const basic_resolver_entry<InternetProtocol> > |
| { |
| public: |
| /// Default constructor creates an end iterator. |
| basic_resolver_iterator() |
| : index_(0) |
| { |
| } |
| |
| /// Create an iterator from an addrinfo list returned by getaddrinfo. |
| static basic_resolver_iterator create( |
| boost::asio::detail::addrinfo_type* address_info, |
| const std::string& host_name, const std::string& service_name) |
| { |
| basic_resolver_iterator iter; |
| if (!address_info) |
| return iter; |
| |
| std::string actual_host_name = host_name; |
| if (address_info->ai_canonname) |
| actual_host_name = address_info->ai_canonname; |
| |
| iter.values_.reset(new values_type); |
| |
| while (address_info) |
| { |
| if (address_info->ai_family == PF_INET |
| || address_info->ai_family == PF_INET6) |
| { |
| using namespace std; // For memcpy. |
| typename InternetProtocol::endpoint endpoint; |
| endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen)); |
| memcpy(endpoint.data(), address_info->ai_addr, |
| address_info->ai_addrlen); |
| iter.values_->push_back( |
| basic_resolver_entry<InternetProtocol>(endpoint, |
| actual_host_name, service_name)); |
| } |
| address_info = address_info->ai_next; |
| } |
| |
| return iter; |
| } |
| |
| /// Create an iterator from an endpoint, host name and service name. |
| static basic_resolver_iterator create( |
| const typename InternetProtocol::endpoint& endpoint, |
| const std::string& host_name, const std::string& service_name) |
| { |
| basic_resolver_iterator iter; |
| iter.values_.reset(new values_type); |
| iter.values_->push_back( |
| basic_resolver_entry<InternetProtocol>( |
| endpoint, host_name, service_name)); |
| return iter; |
| } |
| |
| /// Dereference an iterator. |
| const basic_resolver_entry<InternetProtocol>& operator*() const |
| { |
| return dereference(); |
| } |
| |
| /// Dereference an iterator. |
| const basic_resolver_entry<InternetProtocol>* operator->() const |
| { |
| return &dereference(); |
| } |
| |
| /// Increment operator (prefix). |
| basic_resolver_iterator& operator++() |
| { |
| increment(); |
| return *this; |
| } |
| |
| /// Increment operator (postfix). |
| basic_resolver_iterator operator++(int) |
| { |
| basic_resolver_iterator tmp(*this); |
| ++*this; |
| return tmp; |
| } |
| |
| /// Test two iterators for equality. |
| friend bool operator==(const basic_resolver_iterator& a, |
| const basic_resolver_iterator& b) |
| { |
| return a.equal(b); |
| } |
| |
| /// Test two iterators for inequality. |
| friend bool operator!=(const basic_resolver_iterator& a, |
| const basic_resolver_iterator& b) |
| { |
| return !a.equal(b); |
| } |
| |
| private: |
| void increment() |
| { |
| if (++index_ == values_->size()) |
| { |
| // Reset state to match a default constructed end iterator. |
| values_.reset(); |
| index_ = 0; |
| } |
| } |
| |
| bool equal(const basic_resolver_iterator& other) const |
| { |
| if (!values_ && !other.values_) |
| return true; |
| if (values_ != other.values_) |
| return false; |
| return index_ == other.index_; |
| } |
| |
| const basic_resolver_entry<InternetProtocol>& dereference() const |
| { |
| return (*values_)[index_]; |
| } |
| |
| typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type; |
| boost::asio::detail::shared_ptr<values_type> values_; |
| std::size_t index_; |
| }; |
| |
| } // namespace ip |
| } // namespace asio |
| } // namespace boost |
| |
| #include <boost/asio/detail/pop_options.hpp> |
| |
| #endif // BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP |