LCOV - code coverage report
Current view: top level - boost/url/detail - encode.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 49 77 63.6 %
Date: 2024-01-19 15:42:53 Functions: 3 3 100.0 %

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
       3             : // Copyright (c) 2022 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_DETAIL_ENCODE_HPP
      12             : #define BOOST_URL_DETAIL_ENCODE_HPP
      13             : 
      14             : #include <boost/url/encoding_opts.hpp>
      15             : #include <boost/url/pct_string_view.hpp>
      16             : #include <boost/url/grammar/hexdig_chars.hpp>
      17             : #include <boost/core/ignore_unused.hpp>
      18             : #include <cstdlib>
      19             : 
      20             : namespace boost {
      21             : namespace urls {
      22             : namespace detail {
      23             : 
      24             : constexpr
      25             : char const* const hexdigs[] = {
      26             :     "0123456789ABCDEF",
      27             :     "0123456789abcdef" };
      28             : 
      29             : //------------------------------------------------
      30             : 
      31             : // re-encode is to percent-encode a
      32             : // string that can already contain
      33             : // escapes. Characters not in the
      34             : // unreserved set are escaped, and
      35             : // escapes are passed through unchanged.
      36             : //
      37             : template<class CharSet>
      38             : std::size_t
      39        1065 : re_encoded_size_unsafe(
      40             :     core::string_view s,
      41             :     CharSet const& unreserved,
      42             :     encoding_opts opt) noexcept
      43             : {
      44        1065 :     std::size_t n = 0;
      45        1065 :     auto const end = s.end();
      46        1065 :     auto it = s.begin();
      47        1065 :     if(opt.space_as_plus)
      48             :     {
      49           0 :         while(it != end)
      50             :         {
      51           0 :             if(*it != '%')
      52             :             {
      53           0 :                 if( unreserved(*it)
      54           0 :                     || *it == ' ')
      55           0 :                     n += 1; 
      56             :                 else
      57           0 :                     n += 3;
      58           0 :                 ++it;
      59             :             }
      60             :             else
      61             :             {
      62           0 :                 BOOST_ASSERT(end - it >= 3);
      63           0 :                 BOOST_ASSERT(
      64             :                     grammar::hexdig_value(
      65             :                         it[1]) >= 0);
      66           0 :                 BOOST_ASSERT(
      67             :                     grammar::hexdig_value(
      68             :                         it[2]) >= 0);
      69           0 :                 n += 3;
      70           0 :                 it += 3;
      71             :             }
      72             :         }
      73             :     }
      74             :     else
      75             :     {
      76        4702 :         while(it != end)
      77             :         {
      78        3637 :             if(*it != '%')
      79             :             {
      80        3482 :                 if(unreserved(*it))
      81        3275 :                     n += 1; 
      82             :                 else
      83         207 :                     n += 3;
      84        3482 :                 ++it;
      85             :             }
      86             :             else
      87             :             {
      88         155 :                 BOOST_ASSERT(end - it >= 3);
      89         155 :                 BOOST_ASSERT(
      90             :                     grammar::hexdig_value(
      91             :                         it[1]) >= 0);
      92         155 :                 BOOST_ASSERT(
      93             :                     grammar::hexdig_value(
      94             :                         it[2]) >= 0);
      95         155 :                 n += 3;
      96         155 :                 it += 3;
      97             :             }
      98             :         }
      99             :     }
     100        1065 :     return n;
     101             : }
     102             : 
     103             : // unchecked
     104             : // returns decoded size
     105             : template<class CharSet>
     106             : std::size_t
     107        1271 : re_encode_unsafe(
     108             :     char*& dest_,
     109             :     char const* const end,
     110             :     core::string_view s,
     111             :     CharSet const& unreserved,
     112             :     encoding_opts opt) noexcept
     113             : {
     114        1271 :     char const* const hex =
     115        1271 :         detail::hexdigs[opt.lower_case];
     116        1271 :     auto const encode = [end, hex](
     117             :         char*& dest,
     118             :         unsigned char c) noexcept
     119             :     {
     120         213 :         ignore_unused(end);
     121         213 :         *dest++ = '%';
     122         213 :         BOOST_ASSERT(dest != end);
     123         213 :         *dest++ = hex[c>>4];
     124         213 :         BOOST_ASSERT(dest != end);
     125         213 :         *dest++ = hex[c&0xf];
     126             :     };
     127             :     ignore_unused(end);
     128             : 
     129        1271 :     auto dest = dest_;
     130        1271 :     auto const dest0 = dest;
     131        1271 :     auto const last = s.end();
     132        1271 :     std::size_t dn = 0;
     133        1271 :     auto it = s.begin();
     134             : 
     135        1271 :     if(opt.space_as_plus)
     136             :     {
     137           0 :         while(it != last)
     138             :         {
     139           0 :             BOOST_ASSERT(dest != end);
     140           0 :             if(*it != '%')
     141             :             {
     142           0 :                 if(*it == ' ')
     143             :                 {
     144           0 :                     *dest++ = '+';
     145             :                 }
     146           0 :                 else if(unreserved(*it))
     147             :                 {
     148           0 :                     *dest++ = *it;
     149             :                 }
     150             :                 else
     151             :                 {
     152           0 :                     encode(dest, *it);
     153           0 :                     dn += 2;
     154             :                 }
     155           0 :                 ++it;
     156             :             }
     157             :             else
     158             :             {
     159           0 :                 *dest++ = *it++;
     160           0 :                 BOOST_ASSERT(dest != end);
     161           0 :                 *dest++ = *it++;
     162           0 :                 BOOST_ASSERT(dest != end);
     163           0 :                 *dest++ = *it++;
     164           0 :                 dn += 2;
     165             :             }
     166             :         }
     167             :     }
     168             :     else
     169             :     {
     170        5054 :         while(it != last)
     171             :         {
     172        3783 :             BOOST_ASSERT(dest != end);
     173        3783 :             if(*it != '%')
     174             :             {
     175        3625 :                 if(unreserved(*it))
     176             :                 {
     177        3412 :                     *dest++ = *it;
     178             :                 }
     179             :                 else
     180             :                 {
     181         213 :                     encode(dest, *it);
     182         213 :                     dn += 2;
     183             :                 }
     184        3625 :                 ++it;
     185             :             }
     186             :             else
     187             :             {
     188         158 :                 *dest++ = *it++;
     189         158 :                 BOOST_ASSERT(dest != end);
     190         158 :                 *dest++ = *it++;
     191         158 :                 BOOST_ASSERT(dest != end);
     192         158 :                 *dest++ = *it++;
     193         158 :                 dn += 2;
     194             :             }
     195             :         }
     196             :     }
     197        1271 :     dest_ = dest;
     198        1271 :     return dest - dest0 - dn;
     199             : }
     200             : 
     201             : } // detail
     202             : } // urls
     203             : } // boost
     204             : 
     205             : #endif

Generated by: LCOV version 1.15