100.00% Lines (111/111)
100.00% Functions (2/2)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | |||||
| 3 | // Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com) | 3 | // Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com) | |||||
| 4 | // | 4 | // | |||||
| 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 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) | 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 7 | // | 7 | // | |||||
| 8 | // Official repository: https://github.com/boostorg/url | 8 | // Official repository: https://github.com/boostorg/url | |||||
| 9 | // | 9 | // | |||||
| 10 | 10 | |||||||
| 11 | #ifndef BOOST_URL_RFC_IMPL_IPV6_ADDRESS_RULE_HPP | 11 | #ifndef BOOST_URL_RFC_IMPL_IPV6_ADDRESS_RULE_HPP | |||||
| 12 | #define BOOST_URL_RFC_IMPL_IPV6_ADDRESS_RULE_HPP | 12 | #define BOOST_URL_RFC_IMPL_IPV6_ADDRESS_RULE_HPP | |||||
| 13 | 13 | |||||||
| 14 | #include <boost/url/detail/config.hpp> | 14 | #include <boost/url/detail/config.hpp> | |||||
| 15 | #include <boost/url/rfc/ipv4_address_rule.hpp> | 15 | #include <boost/url/rfc/ipv4_address_rule.hpp> | |||||
| 16 | #include <boost/url/rfc/detail/h16_rule.hpp> | 16 | #include <boost/url/rfc/detail/h16_rule.hpp> | |||||
| 17 | #include <boost/url/grammar/charset.hpp> | 17 | #include <boost/url/grammar/charset.hpp> | |||||
| 18 | #include <boost/url/grammar/hexdig_chars.hpp> | 18 | #include <boost/url/grammar/hexdig_chars.hpp> | |||||
| 19 | #include <boost/url/grammar/error.hpp> | 19 | #include <boost/url/grammar/error.hpp> | |||||
| 20 | #include <boost/url/grammar/parse.hpp> | 20 | #include <boost/url/grammar/parse.hpp> | |||||
| 21 | #include <boost/assert.hpp> | 21 | #include <boost/assert.hpp> | |||||
| 22 | #include <cstring> | 22 | #include <cstring> | |||||
| 23 | 23 | |||||||
| 24 | namespace boost { | 24 | namespace boost { | |||||
| 25 | namespace urls { | 25 | namespace urls { | |||||
| 26 | 26 | |||||||
| 27 | namespace detail { | 27 | namespace detail { | |||||
| 28 | 28 | |||||||
| 29 | // return `true` if the hex | 29 | // return `true` if the hex | |||||
| 30 | // word could be 0..255 if | 30 | // word could be 0..255 if | |||||
| 31 | // interpreted as decimal | 31 | // interpreted as decimal | |||||
| 32 | BOOST_URL_CXX20_CONSTEXPR_OR_INLINE | 32 | BOOST_URL_CXX20_CONSTEXPR_OR_INLINE | |||||
| 33 | bool | 33 | bool | |||||
| HITCBC | 34 | 65 | maybe_octet( | 34 | 65 | maybe_octet( | ||
| 35 | unsigned char const* p) noexcept | 35 | unsigned char const* p) noexcept | |||||
| 36 | { | 36 | { | |||||
| HITCBC | 37 | 65 | unsigned short word = | 37 | 65 | unsigned short word = | ||
| 38 | static_cast<unsigned short>( | 38 | static_cast<unsigned short>( | |||||
| HITCBC | 39 | 65 | p[0]) * 256 + | 39 | 65 | p[0]) * 256 + | ||
| 40 | static_cast<unsigned short>( | 40 | static_cast<unsigned short>( | |||||
| HITCBC | 41 | 65 | p[1]); | 41 | 65 | p[1]); | ||
| HITCBC | 42 | 65 | if(word > 0x255) | 42 | 65 | if(word > 0x255) | ||
| HITCBC | 43 | 7 | return false; | 43 | 7 | return false; | ||
| HITCBC | 44 | 58 | if(((word >> 4) & 0xf) > 9) | 44 | 58 | if(((word >> 4) & 0xf) > 9) | ||
| HITCBC | 45 | 1 | return false; | 45 | 1 | return false; | ||
| HITCBC | 46 | 57 | if((word & 0xf) > 9) | 46 | 57 | if((word & 0xf) > 9) | ||
| HITCBC | 47 | 2 | return false; | 47 | 2 | return false; | ||
| HITCBC | 48 | 55 | return true; | 48 | 55 | return true; | ||
| 49 | } | 49 | } | |||||
| 50 | 50 | |||||||
| 51 | } // detail | 51 | } // detail | |||||
| 52 | 52 | |||||||
| 53 | BOOST_URL_CXX20_CONSTEXPR_OR_INLINE | 53 | BOOST_URL_CXX20_CONSTEXPR_OR_INLINE | |||||
| 54 | auto | 54 | auto | |||||
| HITCBC | 55 | 346 | implementation_defined::ipv6_address_rule_t:: | 55 | 346 | implementation_defined::ipv6_address_rule_t:: | ||
| 56 | parse( | 56 | parse( | |||||
| 57 | char const*& it, | 57 | char const*& it, | |||||
| 58 | char const* const end | 58 | char const* const end | |||||
| 59 | ) const noexcept -> | 59 | ) const noexcept -> | |||||
| 60 | system::result<ipv6_address> | 60 | system::result<ipv6_address> | |||||
| 61 | { | 61 | { | |||||
| HITCBC | 62 | 346 | int n = 8; // words needed | 62 | 346 | int n = 8; // words needed | ||
| HITCBC | 63 | 346 | int b = -1; // value of n | 63 | 346 | int b = -1; // value of n | ||
| 64 | // when '::' seen | 64 | // when '::' seen | |||||
| HITCBC | 65 | 346 | bool c = false; // need colon | 65 | 346 | bool c = false; // need colon | ||
| HITCBC | 66 | 346 | auto prev = it; | 66 | 346 | auto prev = it; | ||
| 67 | ipv6_address::bytes_type bytes; | 67 | ipv6_address::bytes_type bytes; | |||||
| HITCBC | 68 | 346 | system::result<detail::h16_rule_t::value_type> rv; | 68 | 346 | system::result<detail::h16_rule_t::value_type> rv; | ||
| 69 | for(;;) | 69 | for(;;) | |||||
| 70 | { | 70 | { | |||||
| HITCBC | 71 | 1746 | if(it == end) | 71 | 1746 | if(it == end) | ||
| 72 | { | 72 | { | |||||
| HITCBC | 73 | 92 | if(b != -1) | 73 | 92 | if(b != -1) | ||
| 74 | { | 74 | { | |||||
| 75 | // end in "::" | 75 | // end in "::" | |||||
| HITCBC | 76 | 86 | break; | 76 | 86 | break; | ||
| 77 | } | 77 | } | |||||
| HITCBC | 78 | 6 | BOOST_ASSERT(n > 0); | 78 | 6 | BOOST_ASSERT(n > 0); | ||
| 79 | // not enough words | 79 | // not enough words | |||||
| HITCBC | 80 | 6 | BOOST_URL_CONSTEXPR_RETURN_EC( | 80 | 6 | BOOST_URL_CONSTEXPR_RETURN_EC( | ||
| 81 | grammar::error::invalid); | 81 | grammar::error::invalid); | |||||
| 82 | } | 82 | } | |||||
| HITCBC | 83 | 1654 | if(*it == ':') | 83 | 1654 | if(*it == ':') | ||
| 84 | { | 84 | { | |||||
| HITCBC | 85 | 1129 | ++it; | 85 | 1129 | ++it; | ||
| HITCBC | 86 | 1129 | if(it == end) | 86 | 1129 | if(it == end) | ||
| 87 | { | 87 | { | |||||
| 88 | // expected ':' | 88 | // expected ':' | |||||
| HITCBC | 89 | 5 | BOOST_URL_CONSTEXPR_RETURN_EC( | 89 | 5 | BOOST_URL_CONSTEXPR_RETURN_EC( | ||
| 90 | grammar::error::invalid); | 90 | grammar::error::invalid); | |||||
| 91 | } | 91 | } | |||||
| HITCBC | 92 | 1124 | if(*it == ':') | 92 | 1124 | if(*it == ':') | ||
| 93 | { | 93 | { | |||||
| HITCBC | 94 | 205 | if(b == -1) | 94 | 205 | if(b == -1) | ||
| 95 | { | 95 | { | |||||
| 96 | // first "::" | 96 | // first "::" | |||||
| HITCBC | 97 | 202 | ++it; | 97 | 202 | ++it; | ||
| HITCBC | 98 | 202 | --n; | 98 | 202 | --n; | ||
| HITCBC | 99 | 202 | b = n; | 99 | 202 | b = n; | ||
| HITCBC | 100 | 202 | if(n == 0) | 100 | 202 | if(n == 0) | ||
| HITCBC | 101 | 2 | break; | 101 | 2 | break; | ||
| HITCBC | 102 | 200 | c = false; | 102 | 200 | c = false; | ||
| HITCBC | 103 | 200 | continue; | 103 | 200 | continue; | ||
| 104 | } | 104 | } | |||||
| 105 | // extra "::" found | 105 | // extra "::" found | |||||
| HITCBC | 106 | 3 | BOOST_URL_CONSTEXPR_RETURN_EC( | 106 | 3 | BOOST_URL_CONSTEXPR_RETURN_EC( | ||
| 107 | grammar::error::invalid); | 107 | grammar::error::invalid); | |||||
| 108 | } | 108 | } | |||||
| HITCBC | 109 | 919 | if(c) | 109 | 919 | if(c) | ||
| 110 | { | 110 | { | |||||
| HITCBC | 111 | 913 | prev = it; | 111 | 913 | prev = it; | ||
| HITCBC | 112 | 913 | rv = grammar::parse( | 112 | 913 | rv = grammar::parse( | ||
| 113 | it, end, | 113 | it, end, | |||||
| 114 | detail::h16_rule); | 114 | detail::h16_rule); | |||||
| HITCBC | 115 | 913 | if(! rv) | 115 | 913 | if(! rv) | ||
| HITCBC | 116 | 5 | return rv.error(); | 116 | 5 | return rv.error(); | ||
| HITCBC | 117 | 908 | bytes[2*(8-n)+0] = rv->hi; | 117 | 908 | bytes[2*(8-n)+0] = rv->hi; | ||
| HITCBC | 118 | 908 | bytes[2*(8-n)+1] = rv->lo; | 118 | 908 | bytes[2*(8-n)+1] = rv->lo; | ||
| HITCBC | 119 | 908 | --n; | 119 | 908 | --n; | ||
| HITCBC | 120 | 908 | if(n == 0) | 120 | 908 | if(n == 0) | ||
| HITCBC | 121 | 96 | break; | 121 | 96 | break; | ||
| HITCBC | 122 | 812 | continue; | 122 | 812 | continue; | ||
| 123 | } | 123 | } | |||||
| 124 | // expected h16 | 124 | // expected h16 | |||||
| HITCBC | 125 | 6 | BOOST_URL_CONSTEXPR_RETURN_EC( | 125 | 6 | BOOST_URL_CONSTEXPR_RETURN_EC( | ||
| 126 | grammar::error::invalid); | 126 | grammar::error::invalid); | |||||
| 127 | } | 127 | } | |||||
| HITCBC | 128 | 525 | if(*it == '.') | 128 | 525 | if(*it == '.') | ||
| 129 | { | 129 | { | |||||
| HITCBC | 130 | 75 | if(b == -1 && n > 1) | 130 | 75 | if(b == -1 && n > 1) | ||
| 131 | { | 131 | { | |||||
| 132 | // not enough h16 | 132 | // not enough h16 | |||||
| HITCBC | 133 | 10 | BOOST_URL_CONSTEXPR_RETURN_EC( | 133 | 10 | BOOST_URL_CONSTEXPR_RETURN_EC( | ||
| 134 | grammar::error::invalid); | 134 | grammar::error::invalid); | |||||
| 135 | } | 135 | } | |||||
| HITCBC | 136 | 65 | if(! detail::maybe_octet( | 136 | 65 | if(! detail::maybe_octet( | ||
| HITCBC | 137 | 65 | &bytes[2*(7-n)])) | 137 | 65 | &bytes[2*(7-n)])) | ||
| 138 | { | 138 | { | |||||
| 139 | // invalid octet | 139 | // invalid octet | |||||
| HITCBC | 140 | 10 | BOOST_URL_CONSTEXPR_RETURN_EC( | 140 | 10 | BOOST_URL_CONSTEXPR_RETURN_EC( | ||
| 141 | grammar::error::invalid); | 141 | grammar::error::invalid); | |||||
| 142 | } | 142 | } | |||||
| 143 | // rewind the h16 and | 143 | // rewind the h16 and | |||||
| 144 | // parse it as ipv4 | 144 | // parse it as ipv4 | |||||
| HITCBC | 145 | 55 | it = prev; | 145 | 55 | it = prev; | ||
| HITCBC | 146 | 55 | auto rv1 = grammar::parse( | 146 | 55 | auto rv1 = grammar::parse( | ||
| 147 | it, end, ipv4_address_rule); | 147 | it, end, ipv4_address_rule); | |||||
| HITCBC | 148 | 55 | if(! rv1) | 148 | 55 | if(! rv1) | ||
| HITCBC | 149 | 22 | return rv1.error(); | 149 | 22 | return rv1.error(); | ||
| HITCBC | 150 | 33 | auto v4 = *rv1; | 150 | 33 | auto v4 = *rv1; | ||
| 151 | auto const b4 = | 151 | auto const b4 = | |||||
| HITCBC | 152 | 33 | v4.to_bytes(); | 152 | 33 | v4.to_bytes(); | ||
| HITCBC | 153 | 33 | bytes[2*(7-n)+0] = b4[0]; | 153 | 33 | bytes[2*(7-n)+0] = b4[0]; | ||
| HITCBC | 154 | 33 | bytes[2*(7-n)+1] = b4[1]; | 154 | 33 | bytes[2*(7-n)+1] = b4[1]; | ||
| HITCBC | 155 | 33 | bytes[2*(7-n)+2] = b4[2]; | 155 | 33 | bytes[2*(7-n)+2] = b4[2]; | ||
| HITCBC | 156 | 33 | bytes[2*(7-n)+3] = b4[3]; | 156 | 33 | bytes[2*(7-n)+3] = b4[3]; | ||
| HITCBC | 157 | 33 | --n; | 157 | 33 | --n; | ||
| HITCBC | 158 | 33 | break; | 158 | 33 | break; | ||
| 159 | } | 159 | } | |||||
| 160 | auto d = | 160 | auto d = | |||||
| HITCBC | 161 | 450 | grammar::hexdig_value(*it); | 161 | 450 | grammar::hexdig_value(*it); | ||
| HITCBC | 162 | 450 | if( b != -1 && | 162 | 450 | if( b != -1 && | ||
| 163 | d < 0) | 163 | d < 0) | |||||
| 164 | { | 164 | { | |||||
| 165 | // ends in "::" | 165 | // ends in "::" | |||||
| HITCBC | 166 | 41 | break; | 166 | 41 | break; | ||
| 167 | } | 167 | } | |||||
| HITCBC | 168 | 409 | if(! c) | 168 | 409 | if(! c) | ||
| 169 | { | 169 | { | |||||
| HITCBC | 170 | 405 | prev = it; | 170 | 405 | prev = it; | ||
| HITCBC | 171 | 405 | rv = grammar::parse( | 171 | 405 | rv = grammar::parse( | ||
| 172 | it, end, | 172 | it, end, | |||||
| 173 | detail::h16_rule); | 173 | detail::h16_rule); | |||||
| HITCBC | 174 | 405 | if(! rv) | 174 | 405 | if(! rv) | ||
| HITCBC | 175 | 16 | return rv.error(); | 175 | 16 | return rv.error(); | ||
| HITCBC | 176 | 389 | bytes[2*(8-n)+0] = rv->hi; | 176 | 389 | bytes[2*(8-n)+0] = rv->hi; | ||
| HITCBC | 177 | 389 | bytes[2*(8-n)+1] = rv->lo; | 177 | 389 | bytes[2*(8-n)+1] = rv->lo; | ||
| HITCBC | 178 | 389 | --n; | 178 | 389 | --n; | ||
| HITCBC | 179 | 389 | if(n == 0) | 179 | 389 | if(n == 0) | ||
| HITCBC | 180 | 1 | break; | 180 | 1 | break; | ||
| HITCBC | 181 | 388 | c = true; | 181 | 388 | c = true; | ||
| HITCBC | 182 | 388 | continue; | 182 | 388 | continue; | ||
| 183 | } | 183 | } | |||||
| 184 | // ':' divides a word | 184 | // ':' divides a word | |||||
| HITCBC | 185 | 4 | BOOST_URL_CONSTEXPR_RETURN_EC( | 185 | 4 | BOOST_URL_CONSTEXPR_RETURN_EC( | ||
| 186 | grammar::error::invalid); | 186 | grammar::error::invalid); | |||||
| HITCBC | 187 | 1400 | } | 187 | 1400 | } | ||
| HITCBC | 188 | 259 | if(b == -1) | 188 | 259 | if(b == -1) | ||
| HITCBC | 189 | 95 | return ipv6_address{bytes}; | 189 | 95 | return ipv6_address{bytes}; | ||
| HITCBC | 190 | 164 | if(b == n) | 190 | 164 | if(b == n) | ||
| 191 | { | 191 | { | |||||
| 192 | // "::" last | 192 | // "::" last | |||||
| HITCBC | 193 | 35 | auto const i = | 193 | 35 | auto const i = | ||
| HITCBC | 194 | 35 | 2 * (7 - n); | 194 | 35 | 2 * (7 - n); | ||
| HITCBC | 195 | 35 | std::memset( | 195 | 35 | std::memset( | ||
| HITCBC | 196 | 35 | &bytes[i], | 196 | 35 | &bytes[i], | ||
| HITCBC | 197 | 35 | 0, 16 - i); | 197 | 35 | 0, 16 - i); | ||
| 198 | } | 198 | } | |||||
| HITCBC | 199 | 129 | else if(b == 7) | 199 | 129 | else if(b == 7) | ||
| 200 | { | 200 | { | |||||
| 201 | // "::" first | 201 | // "::" first | |||||
| HITCBC | 202 | 52 | auto const i = | 202 | 52 | auto const i = | ||
| HITCBC | 203 | 52 | 2 * (b - n); | 203 | 52 | 2 * (b - n); | ||
| HITCBC | 204 | 104 | std::memmove( | 204 | 104 | std::memmove( | ||
| HITCBC | 205 | 52 | &bytes[16 - i], | 205 | 52 | &bytes[16 - i], | ||
| HITCBC | 206 | 52 | &bytes[2], | 206 | 52 | &bytes[2], | ||
| 207 | i); | 207 | i); | |||||
| HITCBC | 208 | 52 | std::memset( | 208 | 52 | std::memset( | ||
| HITCBC | 209 | 52 | &bytes[0], | 209 | 52 | &bytes[0], | ||
| HITCBC | 210 | 52 | 0, 16 - i); | 210 | 52 | 0, 16 - i); | ||
| 211 | } | 211 | } | |||||
| 212 | else | 212 | else | |||||
| 213 | { | 213 | { | |||||
| 214 | // "::" in middle | 214 | // "::" in middle | |||||
| HITCBC | 215 | 77 | auto const i0 = | 215 | 77 | auto const i0 = | ||
| HITCBC | 216 | 77 | 2 * (7 - b); | 216 | 77 | 2 * (7 - b); | ||
| HITCBC | 217 | 77 | auto const i1 = | 217 | 77 | auto const i1 = | ||
| HITCBC | 218 | 77 | 2 * (b - n); | 218 | 77 | 2 * (b - n); | ||
| HITCBC | 219 | 154 | std::memmove( | 219 | 154 | std::memmove( | ||
| HITCBC | 220 | 77 | &bytes[16 - i1], | 220 | 77 | &bytes[16 - i1], | ||
| HITCBC | 221 | 77 | &bytes[i0 + 2], | 221 | 77 | &bytes[i0 + 2], | ||
| 222 | i1); | 222 | i1); | |||||
| HITCBC | 223 | 77 | std::memset( | 223 | 77 | std::memset( | ||
| HITCBC | 224 | 77 | &bytes[i0], | 224 | 77 | &bytes[i0], | ||
| HITCBC | 225 | 77 | 0, 16 - (i0 + i1)); | 225 | 77 | 0, 16 - (i0 + i1)); | ||
| 226 | } | 226 | } | |||||
| HITCBC | 227 | 164 | return ipv6_address{bytes}; | 227 | 164 | return ipv6_address{bytes}; | ||
| 228 | } | 228 | } | |||||
| 229 | 229 | |||||||
| 230 | } // urls | 230 | } // urls | |||||
| 231 | } // boost | 231 | } // boost | |||||
| 232 | 232 | |||||||
| 233 | 233 | |||||||
| 234 | #endif | 234 | #endif | |||||