LCOV - code coverage report
Current view: top level - url/rfc/impl - ipv6_address_rule.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 111 111
Test Date: 2026-02-13 15:53:22 Functions: 100.0 % 2 2

            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
        

Generated by: LCOV version 2.3