LCOV - code coverage report
Current view: top level - boost/url/impl/encode.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 99 99
Test Date: 2025-01-10 18:07:09 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              : #ifndef BOOST_URL_IMPL_ENCODE_HPP
      11              : #define BOOST_URL_IMPL_ENCODE_HPP
      12              : 
      13              : #include "boost/url/grammar/token_rule.hpp"
      14              : #include <boost/assert.hpp>
      15              : #include <boost/static_assert.hpp>
      16              : #include <boost/url/detail/encode.hpp>
      17              : #include <boost/url/detail/except.hpp>
      18              : #include <boost/url/encoding_opts.hpp>
      19              : #include <boost/url/grammar/charset.hpp>
      20              : #include <boost/url/grammar/hexdig_chars.hpp>
      21              : #include <boost/url/grammar/string_token.hpp>
      22              : #include <boost/url/grammar/type_traits.hpp>
      23              : 
      24              : namespace boost {
      25              : namespace urls {
      26              : 
      27              : //------------------------------------------------
      28              : 
      29              : template<BOOST_URL_CONSTRAINT(grammar::CharSet) CS>
      30              : std::size_t
      31          855 : encoded_size(
      32              :     core::string_view s,
      33              :     CS const& unreserved,
      34              :     encoding_opts opt) noexcept
      35              : {
      36              : /*  If you get a compile error here, it
      37              :     means that the value you passed does
      38              :     not meet the requirements stated in
      39              :     the documentation.
      40              : */
      41              :     BOOST_STATIC_ASSERT(
      42              :         grammar::is_charset<CS>::value);
      43              : 
      44          855 :     std::size_t n = 0;
      45          855 :     auto it = s.data();
      46          855 :     auto const last = it + s.size();
      47              : 
      48          877 :     if(! opt.space_as_plus ||
      49           22 :         unreserved(' '))
      50              :     {
      51         4748 :         while(it != last)
      52              :         {
      53         3915 :             if(unreserved(*it))
      54         3764 :                 n += 1;
      55              :             else
      56          151 :                 n += 3;
      57         3915 :             ++it;
      58              :         }
      59              :     }
      60              :     else
      61              :     {
      62           66 :         while(it != last)
      63              :         {
      64           44 :             auto c = *it;
      65           44 :             if(unreserved(c))
      66           26 :                 ++n;
      67           18 :             else if(c == ' ')
      68            9 :                 ++n;
      69              :             else
      70            9 :                 n += 3;
      71           44 :             ++it;
      72              :         }
      73              :     }
      74          855 :     return n;
      75              : }
      76              : 
      77              : //------------------------------------------------
      78              : 
      79              : template<BOOST_URL_CONSTRAINT(grammar::CharSet) CS>
      80              : std::size_t
      81          543 : encode(
      82              :     char* dest,
      83              :     std::size_t size,
      84              :     core::string_view s,
      85              :     CS const& unreserved,
      86              :     encoding_opts opt)
      87              : {
      88              : /*  If you get a compile error here, it
      89              :     means that the value you passed does
      90              :     not meet the requirements stated in
      91              :     the documentation.
      92              : */
      93              :     BOOST_STATIC_ASSERT(
      94              :         grammar::is_charset<CS>::value);
      95              : 
      96              :     // '%' must be reserved
      97          543 :     BOOST_ASSERT(! unreserved('%'));
      98              : 
      99          543 :     char const* const hex =
     100          543 :         detail::hexdigs[opt.lower_case];
     101          653 :     auto const encode = [hex](
     102              :         char*& dest,
     103              :         unsigned char c) noexcept
     104              :     {
     105          110 :         *dest++ = '%';
     106          110 :         *dest++ = hex[c>>4];
     107          110 :         *dest++ = hex[c&0xf];
     108              :     };
     109              : 
     110          543 :     auto it = s.data();
     111          543 :     auto const end = dest + size;
     112          543 :     auto const last = it + s.size();
     113          543 :     auto const dest0 = dest;
     114          543 :     auto const end3 = end - 3;
     115              : 
     116          543 :     if(! opt.space_as_plus)
     117              :     {
     118         3286 :         while(it != last)
     119              :         {
     120         2787 :             if(unreserved(*it))
     121              :             {
     122         2668 :                 if(dest == end)
     123            3 :                     return dest - dest0;
     124         2665 :                 *dest++ = *it++;
     125         2665 :                 continue;
     126              :             }
     127          119 :             if(dest > end3)
     128           15 :                 return dest - dest0;
     129          104 :             encode(dest, *it++);
     130              :         }
     131          499 :         return dest - dest0;
     132              :     }
     133           26 :     else if(! unreserved(' '))
     134              :     {
     135              :         // VFALCO space is usually reserved,
     136              :         // and we depend on this for an
     137              :         // optimization. if this assert
     138              :         // goes off we can split the loop
     139              :         // below into two versions.
     140           26 :         BOOST_ASSERT(! unreserved(' '));
     141              : 
     142           52 :         while(it != last)
     143              :         {
     144           40 :             if(unreserved(*it))
     145              :             {
     146           16 :                 if(dest == end)
     147            3 :                     return dest - dest0;
     148           13 :                 *dest++ = *it++;
     149           13 :                 continue;
     150              :             }
     151           24 :             if(*it == ' ')
     152              :             {
     153            9 :                 if(dest == end)
     154            2 :                     return dest - dest0;
     155            7 :                 *dest++ = '+';
     156            7 :                 ++it;
     157            7 :                 continue;
     158              :             }
     159           15 :             if(dest > end3)
     160            9 :                 return dest - dest0;
     161            6 :             encode(dest, *it++);
     162              :         }
     163              :     }
     164           12 :     return dest - dest0;
     165              : }
     166              : 
     167              : //------------------------------------------------
     168              : 
     169              : // unsafe encode just
     170              : // asserts on the output buffer
     171              : //
     172              : template<BOOST_URL_CONSTRAINT(grammar::CharSet) CS>
     173              : std::size_t
     174          175 : encode_unsafe(
     175              :     char* dest,
     176              :     std::size_t size,
     177              :     core::string_view s,
     178              :     CS const& unreserved,
     179              :     encoding_opts opt)
     180              : {
     181              :     BOOST_STATIC_ASSERT(
     182              :         grammar::is_charset<CS>::value);
     183              : 
     184              :     // '%' must be reserved
     185          175 :     BOOST_ASSERT(! unreserved('%'));
     186              : 
     187          175 :     auto it = s.data();
     188          175 :     auto const last = it + s.size();
     189          175 :     auto const end = dest + size;
     190              :     ignore_unused(end);
     191              : 
     192          175 :     char const* const hex =
     193          175 :         detail::hexdigs[opt.lower_case];
     194          267 :     auto const encode = [end, hex](
     195              :         char*& dest,
     196              :         unsigned char c) noexcept
     197              :     {
     198           46 :         ignore_unused(end);
     199           46 :         *dest++ = '%';
     200           46 :         BOOST_ASSERT(dest != end);
     201           46 :         *dest++ = hex[c>>4];
     202           46 :         BOOST_ASSERT(dest != end);
     203           46 :         *dest++ = hex[c&0xf];
     204              :     };
     205              : 
     206          175 :     auto const dest0 = dest;
     207          175 :     if(! opt.space_as_plus)
     208              :     {
     209          605 :         while(it != last)
     210              :         {
     211          439 :             BOOST_ASSERT(dest != end);
     212          439 :             if(unreserved(*it))
     213          396 :                 *dest++ = *it++;
     214              :             else
     215           43 :                 encode(dest, *it++);
     216              :         }
     217              :     }
     218              :     else
     219              :     {
     220              :         // VFALCO space is usually reserved,
     221              :         // and we depend on this for an
     222              :         // optimization. if this assert
     223              :         // goes off we can split the loop
     224              :         // below into two versions.
     225            9 :         BOOST_ASSERT(! unreserved(' '));
     226              : 
     227           37 :         while(it != last)
     228              :         {
     229           28 :             BOOST_ASSERT(dest != end);
     230           28 :             if(unreserved(*it))
     231              :             {
     232           20 :                 *dest++ = *it++;
     233              :             }
     234            8 :             else if(*it == ' ')
     235              :             {
     236            5 :                 *dest++ = '+';
     237            5 :                 ++it;
     238              :             }
     239              :             else
     240              :             {
     241            3 :                 encode(dest, *it++);
     242              :             }
     243              :         }
     244              :     }
     245          175 :     return dest - dest0;
     246              : }
     247              : 
     248              : //------------------------------------------------
     249              : 
     250              : template<
     251              :     BOOST_URL_CONSTRAINT(string_token::StringToken) StringToken,
     252              :     BOOST_URL_CONSTRAINT(grammar::CharSet) CS>
     253              : BOOST_URL_STRTOK_RETURN
     254           24 : encode(
     255              :     core::string_view s,
     256              :     CS const& unreserved,
     257              :     encoding_opts opt,
     258              :     StringToken&& token) noexcept
     259              : {
     260              :     BOOST_STATIC_ASSERT(
     261              :         grammar::is_charset<CS>::value);
     262              : 
     263           24 :     auto const n = encoded_size(
     264              :         s, unreserved, opt);
     265           24 :     auto p = token.prepare(n);
     266           24 :     if(n > 0)
     267           22 :         encode_unsafe(
     268              :             p, n, s, unreserved, opt);
     269           24 :     return token.result();
     270              : }
     271              : 
     272              : } // urls
     273              : } // boost
     274              : 
     275              : #endif
        

Generated by: LCOV version 2.1