1 ////////////////////////////////////////////////////////////////////////////////
3 // Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included
13 // in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // http://www.opensource.org/licenses/mit-license.php
25 ////////////////////////////////////////////////////////////////////////////////
31 static bool isPort (const std::string&, unsigned int&);
32 static bool isChar (const std::string&, char, unsigned int&);
33 static bool isEOS (const std::string&, unsigned int&);
34 static bool isIPv4Block (const std::string&, unsigned int&);
35 static bool isIPv4BlockSet (const std::string&, unsigned int&);
36 static bool isIPv6Block (const std::string&, unsigned int&);
37 static bool isIPv6BlockSet (const std::string&, unsigned int&);
39 ////////////////////////////////////////////////////////////////////////////////
40 static bool isPort (const std::string& input, unsigned int& c)
43 while (std::isdigit (input[c]))
46 return c - start > 0 &&
50 ////////////////////////////////////////////////////////////////////////////////
51 static bool isChar (const std::string& input, char character, unsigned int& c)
53 if (input[c] == character)
62 ////////////////////////////////////////////////////////////////////////////////
63 static bool isEOS (const std::string& input, unsigned int& c)
65 return c >= input.length ();
68 ////////////////////////////////////////////////////////////////////////////////
69 static bool isIPv4Block (const std::string& input, unsigned int& c)
72 while (std::isdigit (input[c]))
78 auto byte = std::stoi (input.substr (start, c - start));
87 ////////////////////////////////////////////////////////////////////////////////
88 static bool isIPv4BlockSet (const std::string& input, unsigned int& c)
92 if (isIPv4Block (input, c) &&
93 isChar (input, '.', c) &&
94 isIPv4Block (input, c) &&
95 isChar (input, '.', c) &&
96 isIPv4Block (input, c) &&
97 isChar (input, '.', c) &&
98 isIPv4Block (input, c))
108 ////////////////////////////////////////////////////////////////////////////////
109 static bool isIPv6Block (const std::string& input, unsigned int& c)
112 while (std::isxdigit (input[c]))
125 ////////////////////////////////////////////////////////////////////////////////
126 // at least one non-empty block, or '::'
127 // at least two colons
129 static bool isIPv6BlockSet (const std::string& input, unsigned int& c)
132 int count_colons {0};
133 int count_blocks {0};
137 if (isEOS (input, c))
145 else if (isChar (input, ':', c))
148 else if (isIPv4BlockSet (input, c))
151 else if (isIPv6Block (input, c))
154 else if (isChar (input, '.', c) ||
155 isChar (input, ']', c))
165 if (count_colons >= 2 &&
167 ((count_blocks == 0 && input.substr (start, c) == "::") || count_blocks >= 1) &&
177 ////////////////////////////////////////////////////////////////////////////////
180 bool isIPv4Address (const std::string& input, std::string& address, int& port)
183 if (isIPv4BlockSet (input, c))
186 if (isChar (input, ':', c))
187 if (! isPort (input, c))
190 if (isEOS (input, c))
192 address = input.substr (0, std::min (c, colon));
193 if (! isEOS (input, colon))
194 port = std::stoi (input.substr (colon + 1));
203 ////////////////////////////////////////////////////////////////////////////////
204 // [<address>]:<port>
206 bool isIPv6Address (const std::string& input, std::string& address, int& port)
210 if (isChar (input, '[', c) &&
211 isIPv6BlockSet (input, c) &&
212 isChar (input, ']', c))
215 if (isChar (input, ':', c) &&
219 address = input.substr (1, colon - 2);
220 port = std::stoi (input.substr (colon + 1));
226 if (isIPv6BlockSet (input, c) &&
237 ////////////////////////////////////////////////////////////////////////////////