LCOV - code coverage report
Current view: top level - libs/url/src/ipv6_address.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 130 130
Test Date: 2025-11-10 19:06:20 Functions: 100.0 % 14 14

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

Generated by: LCOV version 2.1