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