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-25 21:00:01 Functions: 100.0 % 13 13

           TLA  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 HIT           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