GCC Code Coverage Report


Directory: libs/url/
File: libs/url/src/ipv6_address.cpp
Date: 2024-04-08 19:38:36
Exec Total Coverage
Lines: 125 125 100.0%
Functions: 13 13 100.0%
Branches: 56 62 90.3%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/url
8 //
9
10
11 #include <boost/url/detail/config.hpp>
12 #include <boost/url/ipv6_address.hpp>
13 #include <boost/url/ipv4_address.hpp>
14 #include <boost/url/rfc/ipv6_address_rule.hpp>
15 #include <boost/url/detail/except.hpp>
16 #include <boost/url/grammar/parse.hpp>
17 #include <cstring>
18
19 namespace boost {
20 namespace urls {
21
22 210 ipv6_address::
23 ipv6_address(
24 210 bytes_type const& bytes) noexcept
25 {
26 210 std::memcpy(&addr_,
27 210 bytes.data(), 16);
28 210 }
29
30 4 ipv6_address::
31 ipv6_address(
32 4 ipv4_address const& addr) noexcept
33 {
34 4 auto const v = addr.to_bytes();
35 4 ipv6_address::bytes_type bytes = {
36 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37 4 0xff, 0xff, v[0], v[1], v[2], v[3] } };
38 4 std::memcpy(&addr_, bytes.data(), 16);
39 4 }
40
41 58 ipv6_address::
42 ipv6_address(
43 58 core::string_view s)
44 : ipv6_address(
45 58 parse_ipv6_address(s
46
2/2
✓ Branch 3 taken 57 times.
✓ Branch 4 taken 1 times.
58 ).value(BOOST_URL_POS))
47 {
48 57 }
49
50 core::string_view
51 14 ipv6_address::
52 to_buffer(
53 char* dest,
54 std::size_t dest_size) const
55 {
56
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
14 if(dest_size < max_str_len)
57 1 detail::throw_length_error();
58 13 auto n = print_impl(dest);
59 13 return core::string_view(dest, n);
60 }
61
62 bool
63 3 ipv6_address::
64 is_loopback() const noexcept
65 {
66 3 return *this == loopback();
67 }
68
69 bool
70 3 ipv6_address::
71 is_unspecified() const noexcept
72 {
73 3 return *this == ipv6_address();
74 }
75
76 bool
77 56 ipv6_address::
78 is_v4_mapped() const noexcept
79 {
80 return
81
2/2
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 16 times.
103 addr_[ 0] == 0 && addr_[ 1] == 0 &&
82
3/4
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 29 times.
✓ Branch 5 taken 2 times.
31 addr_[ 2] == 0 && addr_[ 3] == 0 &&
83
3/4
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 2 times.
29 addr_[ 4] == 0 && addr_[ 5] == 0 &&
84
3/4
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 2 times.
27 addr_[ 6] == 0 && addr_[ 7] == 0 &&
85
3/4
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 2 times.
25 addr_[ 8] == 0 && addr_[ 9] == 0 &&
86
4/4
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 9 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 11 times.
115 addr_[10] == 0xff &&
87
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
68 addr_[11] == 0xff;
88 }
89
90 ipv6_address
91 5 ipv6_address::
92 loopback() noexcept
93 {
94 5 ipv6_address a;
95 5 a.addr_[15] = 1;
96 5 return a;
97 }
98
99 std::size_t
100 51 ipv6_address::
101 print_impl(
102 char* dest) const noexcept
103 {
104 auto const count_zeroes =
105 169 []( unsigned char const* first,
106 unsigned char const* const last)
107 {
108 169 std::size_t n = 0;
109
2/2
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 23 times.
448 while(first != last)
110 {
111
2/2
✓ Branch 0 taken 364 times.
✓ Branch 1 taken 61 times.
425 if( first[0] != 0 ||
112
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 85 times.
364 first[1] != 0)
113 break;
114 279 n += 2;
115 279 first += 2;
116 }
117 169 return n;
118 };
119 auto const print_hex =
120 135 []( char* dest,
121 unsigned short v)
122 {
123 135 char const* const dig =
124 "0123456789abcdef";
125
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 87 times.
135 if(v >= 0x1000)
126 {
127 48 *dest++ = dig[v>>12];
128 48 v &= 0x0fff;
129 48 *dest++ = dig[v>>8];
130 48 v &= 0x0ff;
131 48 *dest++ = dig[v>>4];
132 48 v &= 0x0f;
133 48 *dest++ = dig[v];
134 }
135
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 85 times.
87 else if(v >= 0x100)
136 {
137 2 *dest++ = dig[v>>8];
138 2 v &= 0x0ff;
139 2 *dest++ = dig[v>>4];
140 2 v &= 0x0f;
141 2 *dest++ = dig[v];
142 }
143
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 84 times.
85 else if(v >= 0x10)
144 {
145 1 *dest++ = dig[v>>4];
146 1 v &= 0x0f;
147 1 *dest++ = dig[v];
148 }
149 else
150 {
151 84 *dest++ = dig[v];
152 }
153 135 return dest;
154 };
155 51 auto const dest0 = dest;
156 // find longest run of zeroes
157 51 std::size_t best_len = 0;
158 51 int best_pos = -1;
159 51 auto it = addr_.data();
160 auto const v4 =
161 51 is_v4_mapped();
162
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 42 times.
93 auto const end = v4 ?
163 9 (it + addr_.size() - 4)
164 93 : it + addr_.size();
165
2/2
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 51 times.
220 while(it != end)
166 {
167 169 auto n = count_zeroes(
168 it, end);
169
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 58 times.
169 if(n == 0)
170 {
171 111 it += 2;
172 111 continue;
173 }
174
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 6 times.
58 if(n > best_len)
175 {
176 52 best_pos = static_cast<
177 52 int>(it - addr_.data());
178 52 best_len = n;
179 }
180 58 it += n;
181 }
182 51 it = addr_.data();
183
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 21 times.
51 if(best_pos != 0)
184 {
185 30 unsigned short v =
186 30 (it[0] * 256U) + it[1];
187 30 dest = print_hex(dest, v);
188 30 it += 2;
189 }
190 else
191 {
192 21 *dest++ = ':';
193 21 it += best_len;
194
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19 times.
21 if(it == end)
195 2 *dest++ = ':';
196 }
197
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 51 times.
181 while(it != end)
198 {
199 130 *dest++ = ':';
200 130 if(it - addr_.data() ==
201
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 105 times.
130 best_pos)
202 {
203 25 it += best_len;
204
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 10 times.
25 if(it == end)
205 15 *dest++ = ':';
206 25 continue;
207 }
208 105 unsigned short v =
209 105 (it[0] * 256U) + it[1];
210 105 dest = print_hex(dest, v);
211 105 it += 2;
212 }
213
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 42 times.
51 if(v4)
214 {
215 ipv4_address::bytes_type bytes;
216 9 bytes[0] = it[0];
217 9 bytes[1] = it[1];
218 9 bytes[2] = it[2];
219 9 bytes[3] = it[3];
220 9 ipv4_address a(bytes);
221 9 *dest++ = ':';
222 9 dest += a.print_impl(dest);
223 }
224 51 return dest - dest0;
225 }
226
227 void
228 38 ipv6_address::
229 to_string_impl(
230 string_token::arg& t) const
231 {
232 char buf[max_str_len];
233 38 auto const n = print_impl(buf);
234
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
38 char* dest = t.prepare(n);
235 38 std::memcpy(dest, buf, n);
236 38 }
237
238 //------------------------------------------------
239
240 auto
241 204 parse_ipv6_address(
242 core::string_view s) noexcept ->
243 system::result<ipv6_address>
244 {
245 return grammar::parse(
246 204 s, ipv6_address_rule);
247 }
248
249 } // urls
250 } // boost
251
252