LCOV - code coverage report
Current view: top level - /jenkins/workspace/boost-root/libs/url/src - ipv6_address.cpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 125 125
Test Date: 2026-02-13 15:53:22 Functions: 100.0 % 13 13

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

Generated by: LCOV version 2.3