LCOV - code coverage report
Current view: top level - boost/url/detail - encode.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 50 78 64.1 %
Date: 2024-03-08 17:32:04 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             :         char c0) noexcept
     119             :     {
     120         213 :         auto c = static_cast<unsigned char>(c0);
     121         213 :         ignore_unused(end);
     122         213 :         *dest++ = '%';
     123         213 :         BOOST_ASSERT(dest != end);
     124         213 :         *dest++ = hex[c>>4];
     125         213 :         BOOST_ASSERT(dest != end);
     126         213 :         *dest++ = hex[c&0xf];
     127             :     };
     128             :     ignore_unused(end);
     129             : 
     130        1271 :     auto dest = dest_;
     131        1271 :     auto const dest0 = dest;
     132        1271 :     auto const last = s.end();
     133        1271 :     std::size_t dn = 0;
     134        1271 :     auto it = s.begin();
     135             : 
     136        1271 :     if(opt.space_as_plus)
     137             :     {
     138           0 :         while(it != last)
     139             :         {
     140           0 :             BOOST_ASSERT(dest != end);
     141           0 :             if(*it != '%')
     142             :             {
     143           0 :                 if(*it == ' ')
     144             :                 {
     145           0 :                     *dest++ = '+';
     146             :                 }
     147           0 :                 else if(unreserved(*it))
     148             :                 {
     149           0 :                     *dest++ = *it;
     150             :                 }
     151             :                 else
     152             :                 {
     153           0 :                     encode(dest, *it);
     154           0 :                     dn += 2;
     155             :                 }
     156           0 :                 ++it;
     157             :             }
     158             :             else
     159             :             {
     160           0 :                 *dest++ = *it++;
     161           0 :                 BOOST_ASSERT(dest != end);
     162           0 :                 *dest++ = *it++;
     163           0 :                 BOOST_ASSERT(dest != end);
     164           0 :                 *dest++ = *it++;
     165           0 :                 dn += 2;
     166             :             }
     167             :         }
     168             :     }
     169             :     else
     170             :     {
     171        5054 :         while(it != last)
     172             :         {
     173        3783 :             BOOST_ASSERT(dest != end);
     174        3783 :             if(*it != '%')
     175             :             {
     176        3625 :                 if(unreserved(*it))
     177             :                 {
     178        3412 :                     *dest++ = *it;
     179             :                 }
     180             :                 else
     181             :                 {
     182         213 :                     encode(dest, *it);
     183         213 :                     dn += 2;
     184             :                 }
     185        3625 :                 ++it;
     186             :             }
     187             :             else
     188             :             {
     189         158 :                 *dest++ = *it++;
     190         158 :                 BOOST_ASSERT(dest != end);
     191         158 :                 *dest++ = *it++;
     192         158 :                 BOOST_ASSERT(dest != end);
     193         158 :                 *dest++ = *it++;
     194         158 :                 dn += 2;
     195             :             }
     196             :         }
     197             :     }
     198        1271 :     dest_ = dest;
     199        1271 :     return dest - dest0 - dn;
     200             : }
     201             : 
     202             : } // detail
     203             : } // urls
     204             : } // boost
     205             : 
     206             : #endif

Generated by: LCOV version 1.15