1//
2// ip/impl/address.ipp
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_IMPL_ADDRESS_IPP
12#define ASIO_IP_IMPL_ADDRESS_IPP
13
14
15#include "asio/detail/config.hpp"
16#include <typeinfo>
17#include "asio/detail/throw_error.hpp"
18#include "asio/detail/throw_exception.hpp"
19#include "asio/error.hpp"
20#include "asio/ip/address.hpp"
21#include "asio/system_error.hpp"
22
23#include "asio/detail/push_options.hpp"
24
25namespace asio {
26namespace ip {
27
28address::address()
29  : type_(ipv4),
30    ipv4_address_(),
31    ipv6_address_()
32{
33}
34
35address::address(const asio::ip::address_v4& ipv4_address)
36  : type_(ipv4),
37    ipv4_address_(ipv4_address),
38    ipv6_address_()
39{
40}
41
42address::address(const asio::ip::address_v6& ipv6_address)
43  : type_(ipv6),
44    ipv4_address_(),
45    ipv6_address_(ipv6_address)
46{
47}
48
49address::address(const address& other)
50  : type_(other.type_),
51    ipv4_address_(other.ipv4_address_),
52    ipv6_address_(other.ipv6_address_)
53{
54}
55
56address::address(address&& other)
57  : type_(other.type_),
58    ipv4_address_(other.ipv4_address_),
59    ipv6_address_(other.ipv6_address_)
60{
61}
62
63address& address::operator=(const address& other)
64{
65  type_ = other.type_;
66  ipv4_address_ = other.ipv4_address_;
67  ipv6_address_ = other.ipv6_address_;
68  return *this;
69}
70
71address& address::operator=(address&& other)
72{
73  type_ = other.type_;
74  ipv4_address_ = other.ipv4_address_;
75  ipv6_address_ = other.ipv6_address_;
76  return *this;
77}
78
79address& address::operator=(const asio::ip::address_v4& ipv4_address)
80{
81  type_ = ipv4;
82  ipv4_address_ = ipv4_address;
83  ipv6_address_ = asio::ip::address_v6();
84  return *this;
85}
86
87address& address::operator=(const asio::ip::address_v6& ipv6_address)
88{
89  type_ = ipv6;
90  ipv4_address_ = asio::ip::address_v4();
91  ipv6_address_ = ipv6_address;
92  return *this;
93}
94
95asio::ip::address_v4 address::to_v4() const
96{
97  if (type_ != ipv4)
98  {
99    std::bad_cast ex;
100    asio::detail::throw_exception(ex);
101  }
102  return ipv4_address_;
103}
104
105asio::ip::address_v6 address::to_v6() const
106{
107  if (type_ != ipv6)
108  {
109    std::bad_cast ex;
110    asio::detail::throw_exception(ex);
111  }
112  return ipv6_address_;
113}
114
115std::string address::to_string() const
116{
117  if (type_ == ipv6)
118    return ipv6_address_.to_string();
119  return ipv4_address_.to_string();
120}
121
122std::string address::to_string(asio::error_code& ec) const
123{
124  if (type_ == ipv6)
125    return ipv6_address_.to_string(ec);
126  return ipv4_address_.to_string(ec);
127}
128
129address address::from_string(const char* str)
130{
131  asio::error_code ec;
132  address addr = from_string(str, ec);
133  asio::detail::throw_error(ec);
134  return addr;
135}
136
137address address::from_string(const char* str, asio::error_code& ec)
138{
139  asio::ip::address_v6 ipv6_address =
140    asio::ip::address_v6::from_string(str, ec);
141  if (!ec)
142  {
143    address tmp;
144    tmp.type_ = ipv6;
145    tmp.ipv6_address_ = ipv6_address;
146    return tmp;
147  }
148
149  asio::ip::address_v4 ipv4_address =
150    asio::ip::address_v4::from_string(str, ec);
151  if (!ec)
152  {
153    address tmp;
154    tmp.type_ = ipv4;
155    tmp.ipv4_address_ = ipv4_address;
156    return tmp;
157  }
158
159  return address();
160}
161
162address address::from_string(const std::string& str)
163{
164  return from_string(str.c_str());
165}
166
167address address::from_string(const std::string& str,
168    asio::error_code& ec)
169{
170  return from_string(str.c_str(), ec);
171}
172
173bool address::is_loopback() const
174{
175  return (type_ == ipv4)
176    ? ipv4_address_.is_loopback()
177    : ipv6_address_.is_loopback();
178}
179
180bool address::is_unspecified() const
181{
182  return (type_ == ipv4)
183    ? ipv4_address_.is_unspecified()
184    : ipv6_address_.is_unspecified();
185}
186
187bool address::is_multicast() const
188{
189  return (type_ == ipv4)
190    ? ipv4_address_.is_multicast()
191    : ipv6_address_.is_multicast();
192}
193
194bool operator==(const address& a1, const address& a2)
195{
196  if (a1.type_ != a2.type_)
197    return false;
198  if (a1.type_ == address::ipv6)
199    return a1.ipv6_address_ == a2.ipv6_address_;
200  return a1.ipv4_address_ == a2.ipv4_address_;
201}
202
203bool operator<(const address& a1, const address& a2)
204{
205  if (a1.type_ < a2.type_)
206    return true;
207  if (a1.type_ > a2.type_)
208    return false;
209  if (a1.type_ == address::ipv6)
210    return a1.ipv6_address_ < a2.ipv6_address_;
211  return a1.ipv4_address_ < a2.ipv4_address_;
212}
213
214} // namespace ip
215} // namespace asio
216
217#include "asio/detail/pop_options.hpp"
218
219#endif // ASIO_IP_IMPL_ADDRESS_IPP
220