1 //
2 // ip/address_v6_iterator.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //                         Oliver Kowalke (oliver dot kowalke at gmail dot com)
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 //
11 
12 #ifndef BOOST_ASIO_IP_ADDRESS_V6_ITERATOR_HPP
13 #define BOOST_ASIO_IP_ADDRESS_V6_ITERATOR_HPP
14 
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 # pragma once
17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 
19 #include <boost/asio/detail/config.hpp>
20 #include <boost/asio/ip/address_v6.hpp>
21 
22 #include <boost/asio/detail/push_options.hpp>
23 
24 namespace boost {
25 namespace asio {
26 namespace ip {
27 
28 template <typename> class basic_address_iterator;
29 
30 /// An input iterator that can be used for traversing IPv6 addresses.
31 /**
32  * In addition to satisfying the input iterator requirements, this iterator
33  * also supports decrement.
34  *
35  * @par Thread Safety
36  * @e Distinct @e objects: Safe.@n
37  * @e Shared @e objects: Unsafe.
38  */
39 template <> class basic_address_iterator<address_v6>
40 {
41 public:
42   /// The type of the elements pointed to by the iterator.
43   typedef address_v6 value_type;
44 
45   /// Distance between two iterators.
46   typedef std::ptrdiff_t difference_type;
47 
48   /// The type of a pointer to an element pointed to by the iterator.
49   typedef const address_v6* pointer;
50 
51   /// The type of a reference to an element pointed to by the iterator.
52   typedef const address_v6& reference;
53 
54   /// Denotes that the iterator satisfies the input iterator requirements.
55   typedef std::input_iterator_tag iterator_category;
56 
57   /// Construct an iterator that points to the specified address.
basic_address_iterator(const address_v6 & addr)58   basic_address_iterator(const address_v6& addr) BOOST_ASIO_NOEXCEPT
59     : address_(addr)
60   {
61   }
62 
63   /// Copy constructor.
basic_address_iterator(const basic_address_iterator & other)64   basic_address_iterator(
65       const basic_address_iterator& other) BOOST_ASIO_NOEXCEPT
66     : address_(other.address_)
67   {
68   }
69 
70 #if defined(BOOST_ASIO_HAS_MOVE)
71   /// Move constructor.
basic_address_iterator(basic_address_iterator && other)72   basic_address_iterator(basic_address_iterator&& other) BOOST_ASIO_NOEXCEPT
73     : address_(BOOST_ASIO_MOVE_CAST(address_v6)(other.address_))
74   {
75   }
76 #endif // defined(BOOST_ASIO_HAS_MOVE)
77 
78   /// Assignment operator.
operator =(const basic_address_iterator & other)79   basic_address_iterator& operator=(
80       const basic_address_iterator& other) BOOST_ASIO_NOEXCEPT
81   {
82     address_ = other.address_;
83     return *this;
84   }
85 
86 #if defined(BOOST_ASIO_HAS_MOVE)
87   /// Move assignment operator.
operator =(basic_address_iterator && other)88   basic_address_iterator& operator=(
89       basic_address_iterator&& other) BOOST_ASIO_NOEXCEPT
90   {
91     address_ = BOOST_ASIO_MOVE_CAST(address_v6)(other.address_);
92     return *this;
93   }
94 #endif // defined(BOOST_ASIO_HAS_MOVE)
95 
96   /// Dereference the iterator.
operator *() const97   const address_v6& operator*() const BOOST_ASIO_NOEXCEPT
98   {
99     return address_;
100   }
101 
102   /// Dereference the iterator.
operator ->() const103   const address_v6* operator->() const BOOST_ASIO_NOEXCEPT
104   {
105     return &address_;
106   }
107 
108   /// Pre-increment operator.
operator ++()109   basic_address_iterator& operator++() BOOST_ASIO_NOEXCEPT
110   {
111     for (int i = 15; i >= 0; --i)
112     {
113       if (address_.addr_.s6_addr[i] < 0xFF)
114       {
115         ++address_.addr_.s6_addr[i];
116         break;
117       }
118 
119       address_.addr_.s6_addr[i] = 0;
120     }
121 
122     return *this;
123   }
124 
125   /// Post-increment operator.
operator ++(int)126   basic_address_iterator operator++(int) BOOST_ASIO_NOEXCEPT
127   {
128     basic_address_iterator tmp(*this);
129     ++*this;
130     return tmp;
131   }
132 
133   /// Pre-decrement operator.
operator --()134   basic_address_iterator& operator--() BOOST_ASIO_NOEXCEPT
135   {
136     for (int i = 15; i >= 0; --i)
137     {
138       if (address_.addr_.s6_addr[i] > 0)
139       {
140         --address_.addr_.s6_addr[i];
141         break;
142       }
143 
144       address_.addr_.s6_addr[i] = 0xFF;
145     }
146 
147     return *this;
148   }
149 
150   /// Post-decrement operator.
operator --(int)151   basic_address_iterator operator--(int)
152   {
153     basic_address_iterator tmp(*this);
154     --*this;
155     return tmp;
156   }
157 
158   /// Compare two addresses for equality.
operator ==(const basic_address_iterator & a,const basic_address_iterator & b)159   friend bool operator==(const basic_address_iterator& a,
160       const basic_address_iterator& b)
161   {
162     return a.address_ == b.address_;
163   }
164 
165   /// Compare two addresses for inequality.
operator !=(const basic_address_iterator & a,const basic_address_iterator & b)166   friend bool operator!=(const basic_address_iterator& a,
167       const basic_address_iterator& b)
168   {
169     return a.address_ != b.address_;
170   }
171 
172 private:
173   address_v6 address_;
174 };
175 
176 /// An input iterator that can be used for traversing IPv6 addresses.
177 typedef basic_address_iterator<address_v6> address_v6_iterator;
178 
179 } // namespace ip
180 } // namespace asio
181 } // namespace boost
182 
183 #include <boost/asio/detail/pop_options.hpp>
184 
185 #endif // BOOST_ASIO_IP_ADDRESS_V6_ITERATOR_HPP
186