Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/boostorg/url
9 : //
10 :
11 : #ifndef BOOST_URL_RFC_IMPL_IPV6_ADDRESS_RULE_HPP
12 : #define BOOST_URL_RFC_IMPL_IPV6_ADDRESS_RULE_HPP
13 :
14 : #include <boost/url/detail/config.hpp>
15 : #include <boost/url/rfc/ipv4_address_rule.hpp>
16 : #include <boost/url/rfc/detail/h16_rule.hpp>
17 : #include <boost/url/grammar/charset.hpp>
18 : #include <boost/url/grammar/hexdig_chars.hpp>
19 : #include <boost/url/grammar/error.hpp>
20 : #include <boost/url/grammar/parse.hpp>
21 : #include <boost/assert.hpp>
22 : #include <cstring>
23 :
24 : namespace boost {
25 : namespace urls {
26 :
27 : namespace detail {
28 :
29 : inline BOOST_URL_CXX20_CONSTEXPR
30 : bool
31 65 : maybe_octet(
32 : unsigned char const* p) noexcept
33 : {
34 65 : unsigned short word =
35 : static_cast<unsigned short>(
36 65 : p[0]) * 256 +
37 : static_cast<unsigned short>(
38 65 : p[1]);
39 65 : if(word > 0x255)
40 7 : return false;
41 58 : if(((word >> 4) & 0xf) > 9)
42 1 : return false;
43 57 : if((word & 0xf) > 9)
44 2 : return false;
45 55 : return true;
46 : }
47 :
48 : } // detail
49 :
50 : inline BOOST_URL_CXX20_CONSTEXPR
51 : auto
52 292 : implementation_defined::ipv6_address_rule_t::
53 : parse(
54 : char const*& it,
55 : char const* const end
56 : ) const noexcept ->
57 : system::result<ipv6_address>
58 : {
59 292 : int n = 8;
60 292 : int b = -1;
61 292 : bool c = false;
62 292 : auto prev = it;
63 : ipv6_address::bytes_type bytes;
64 292 : system::result<detail::h16_rule_t::value_type> rv;
65 : for(;;)
66 : {
67 1358 : if(it == end)
68 : {
69 91 : if(b != -1)
70 : {
71 85 : break;
72 : }
73 6 : BOOST_ASSERT(n > 0);
74 6 : BOOST_URL_CONSTEXPR_RETURN_EC(
75 : grammar::error::invalid);
76 : }
77 1267 : if(*it == ':')
78 : {
79 804 : ++it;
80 804 : if(it == end)
81 : {
82 5 : BOOST_URL_CONSTEXPR_RETURN_EC(
83 : grammar::error::invalid);
84 : }
85 799 : if(*it == ':')
86 : {
87 196 : if(b == -1)
88 : {
89 193 : ++it;
90 193 : --n;
91 193 : b = n;
92 193 : if(n == 0)
93 2 : break;
94 191 : c = false;
95 191 : continue;
96 : }
97 3 : BOOST_URL_CONSTEXPR_RETURN_EC(
98 : grammar::error::invalid);
99 : }
100 603 : if(c)
101 : {
102 597 : prev = it;
103 597 : rv = grammar::parse(
104 : it, end,
105 : detail::h16_rule);
106 597 : if(! rv)
107 5 : return rv.error();
108 592 : bytes[2*(8-n)+0] = rv->hi;
109 592 : bytes[2*(8-n)+1] = rv->lo;
110 592 : --n;
111 592 : if(n == 0)
112 51 : break;
113 541 : continue;
114 : }
115 6 : BOOST_URL_CONSTEXPR_RETURN_EC(
116 : grammar::error::invalid);
117 : }
118 463 : if(*it == '.')
119 : {
120 75 : if(b == -1 && n > 1)
121 : {
122 10 : BOOST_URL_CONSTEXPR_RETURN_EC(
123 : grammar::error::invalid);
124 : }
125 65 : if(! detail::maybe_octet(
126 65 : &bytes[2*(7-n)]))
127 : {
128 10 : BOOST_URL_CONSTEXPR_RETURN_EC(
129 : grammar::error::invalid);
130 : }
131 55 : it = prev;
132 55 : auto rv1 = grammar::parse(
133 : it, end, ipv4_address_rule);
134 55 : if(! rv1)
135 22 : return rv1.error();
136 33 : auto v4 = *rv1;
137 : auto const b4 =
138 33 : v4.to_bytes();
139 33 : bytes[2*(7-n)+0] = b4[0];
140 33 : bytes[2*(7-n)+1] = b4[1];
141 33 : bytes[2*(7-n)+2] = b4[2];
142 33 : bytes[2*(7-n)+3] = b4[3];
143 33 : --n;
144 33 : break;
145 : }
146 : auto d =
147 388 : grammar::hexdig_value(*it);
148 388 : if( b != -1 &&
149 : d < 0)
150 : {
151 33 : break;
152 : }
153 355 : if(! c)
154 : {
155 351 : prev = it;
156 351 : rv = grammar::parse(
157 : it, end,
158 : detail::h16_rule);
159 351 : if(! rv)
160 16 : return rv.error();
161 335 : bytes[2*(8-n)+0] = rv->hi;
162 335 : bytes[2*(8-n)+1] = rv->lo;
163 335 : --n;
164 335 : if(n == 0)
165 1 : break;
166 334 : c = true;
167 334 : continue;
168 : }
169 4 : BOOST_URL_CONSTEXPR_RETURN_EC(
170 : grammar::error::invalid);
171 1066 : }
172 205 : if(b == -1)
173 50 : return ipv6_address{bytes};
174 155 : if(b == n)
175 : {
176 34 : auto const i =
177 34 : 2 * (7 - n);
178 34 : std::memset(
179 34 : &bytes[i],
180 34 : 0, 16 - i);
181 : }
182 121 : else if(b == 7)
183 : {
184 45 : auto const i =
185 45 : 2 * (b - n);
186 90 : std::memmove(
187 45 : &bytes[16 - i],
188 45 : &bytes[2],
189 : i);
190 45 : std::memset(
191 45 : &bytes[0],
192 45 : 0, 16 - i);
193 : }
194 : else
195 : {
196 76 : auto const i0 =
197 76 : 2 * (7 - b);
198 76 : auto const i1 =
199 76 : 2 * (b - n);
200 152 : std::memmove(
201 76 : &bytes[16 - i1],
202 76 : &bytes[i0 + 2],
203 : i1);
204 76 : std::memset(
205 76 : &bytes[i0],
206 76 : 0, 16 - (i0 + i1));
207 : }
208 155 : return ipv6_address{bytes};
209 : }
210 :
211 : } // urls
212 : } // boost
213 :
214 :
215 : #endif
|