All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ipv6_address.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2009 zooml.com
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22 #include "ipv6_address.h"
23 #include "ip_address.h"
24 #include <sstream>
25 #include <stdexcept>
26 namespace te
27 {
28  namespace common
29  {
30  namespace uri
31  {
32  const char ipv6_address::SEPARATOR_CHAR = ':';
34  hextets_[0] = 0;
35  hextets_[1] = 0;
36  hextets_[2] = 0;
37  hextets_[3] = 0;
38  hextets_[4] = 0;
39  hextets_[5] = 0;
40  hextets_[6] = 0;
41  hextets_[7] = 0;
42  }
43  ipv6_address::ipv6_address(const std::string& v) {
44  std::string::const_iterator first = v.begin();
45  if (!parse(first, v.end(), *this) || first != v.end())
46  throw std::invalid_argument("invalid IP v6 address: \"" + v + "\"");
47  }
48  bool ipv6_address::is_null() const {
49  return !hextets_[0] && !hextets_[1] && !hextets_[2] && !hextets_[3] &&
50  !hextets_[4] && !hextets_[5] && !hextets_[6] && !hextets_[7];
51  }
52  bool ipv6_address::zero_run(size_t& first, size_t& last) const {
53  first = std::string::npos;
54  size_t len = 0;
55  size_t curi;
56  size_t curn = 0;
57  for (size_t i = 0;; ++i)
58  if (i == 8 || hextets_[i]) { // Broke run.
59  if (len < curn) { // New longest.
60  first = curi;
61  len = curn;
62  }
63  if (i == 8)
64  break;
65  curn = 0;
66  } else { // 0 hextet.
67  if (!curn) // Start.
68  curi = i;
69  ++curn;
70  }
71  if (!len) {
72  last = first;
73  return false;
74  }
75  last = first + len;
76  return true;
77  }
78  std::string ipv6_address::string(bool compress) const {
79  std::ostringstream oss;
80  write(oss, compress);
81  return oss.str();
82  }
83  std::ostream& ipv6_address::write(std::ostream& os, bool compress) const {
84  size_t zfirst;
85  size_t zlast;
86  if (compress)
87  zero_run(zfirst, zlast);
88  else {
89  zfirst = std::string::npos;
90  zlast = std::string::npos;
91  }
92  for (size_t i = 0; i < 8; ++i)
93  if (i < zfirst || zlast <= i) {
94  if (i)
95  os << SEPARATOR_CHAR;
96  os << std::hex << std::uppercase << hextets_[i];
97  } else if (i == zfirst)
98  os << SEPARATOR_CHAR;
99  if (zlast == 8)
100  os << SEPARATOR_CHAR;
101  return os;
102  }
103  bool parse(std::string::const_iterator& first, std::string::const_iterator last, unsigned short& v) {
104  std::string::const_iterator f = first;
105  unsigned int tmp = 0;
106  size_t i = 0;
107  for (; i < 4; ++i, ++f) {
108  if (f == last)
109  break;
110  unsigned int c = (unsigned int)*f;
111  if ('0' <= c && c <= '9')
112  tmp = (tmp << 4) + (c - '0');
113  else if ('A' <= c && c <= 'F')
114  tmp = (tmp << 4) + (c - 'A' + 10);
115  else if ('a' <= c && c <= 'f')
116  tmp = (tmp << 4) + (c - 'a' + 10);
117  else
118  break;
119  }
120  if (!i)
121  return false;
122  v = tmp;
123  first = f;
124  return true;
125  }
126  bool parse(std::string::const_iterator& first, std::string::const_iterator last, ipv6_address& v) {
127  std::string::const_iterator f = first;
128  ipv6_address ip;
129  size_t elide;
130  bool elided = false;
131  size_t i = 0;
132  std::string::const_iterator digits;
133  for (; i < 8; ++i) {
134  if (f == last)
135  break;
136  if (i && (*f != ipv6_address::SEPARATOR_CHAR || ++f == last)) // Need separator.
137  break;
138  if (*f == ipv6_address::SEPARATOR_CHAR) { // Elide.
139  if (elided) // Cannot have 2 elides.
140  return false;
141  ip.hextets_[i] = 0;
142  elide = i;
143  elided = true;
144  if (!i)
145  ++f;
146  } else {
147  std::string::const_iterator anchor = f;
148  if (!parse(f, last, ip.hextets_[i]))
149  break;
150  if (i < 7 && f != last && *f == ip_address::SEPARATOR_CHAR) { // Might be v4.
151  ip_address v4;
152  if (parse(anchor, last, v4)) { // Got it.
153  ip.hextets_[i++] = ((unsigned int)v4.octets_[0] << 8) | v4.octets_[1];
154  ip.hextets_[i++] = ((unsigned int)v4.octets_[2] << 8) | v4.octets_[3];
155  f = anchor;
156  break;
157  }
158  }
159  }
160  }
161  if (i == 8) // At most 1 elided hextet, already zeroed.
162  v = ip;
163  else { // Need to insert zeros.
164  if (!elided)
165  return false;
166  size_t j = 0;
167  size_t zeros = 8 - i;
168  for (i = 0; i < 8; ++i) {
169  unsigned short u;
170  if (elide < i && zeros) {
171  u = 0;
172  --zeros;
173  } else
174  u = ip.hextets_[j++];
175  v.hextets_[i] = u;
176  }
177  }
178  first = f;
179  return true;
180  }
181  }
182  }
183 }
friend bool TECOMMONEXPORT parse(std::string::const_iterator &first, std::string::const_iterator last, ipv6_address &v)
Parse IP v6 address, returning whether found or not and advancing first and setting address if found...
unsigned char octets_[4]
Definition: ip_address.h:61
bool parse(std::string::const_iterator &first, std::string::const_iterator last, authority &v)
Parse URI authority, returning whether found or not and advancing first and setting authority if foun...
Definition: authority.cpp:156
std::ostream & write(std::ostream &os, bool compress=false) const
Stream out.
ipv6_address()
Construct null.
bool zero_run(size_t &first, size_t &last) const
bool is_null() const
Test if null (all 0's).
unsigned short hextets_[8]
Definition: ipv6_address.h:73
static const char SEPARATOR_CHAR
separator (':')
Definition: ipv6_address.h:69
static const char SEPARATOR_CHAR
separator ('.')
Definition: ip_address.h:57
std::string string(bool compress=false) const
Calculate string representation.