100.00% Lines (47/47) 100.00% Functions (3/3)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3   // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) 3   // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/boostorg/url 8   // Official repository: https://github.com/boostorg/url
9   // 9   //
10   10  
11   #ifndef BOOST_URL_DETAIL_ENCODE_HPP 11   #ifndef BOOST_URL_DETAIL_ENCODE_HPP
12   #define BOOST_URL_DETAIL_ENCODE_HPP 12   #define BOOST_URL_DETAIL_ENCODE_HPP
13   13  
14   #include <boost/url/encoding_opts.hpp> 14   #include <boost/url/encoding_opts.hpp>
15   #include <boost/url/pct_string_view.hpp> 15   #include <boost/url/pct_string_view.hpp>
16   #include <boost/url/grammar/hexdig_chars.hpp> 16   #include <boost/url/grammar/hexdig_chars.hpp>
17   #include <boost/core/ignore_unused.hpp> 17   #include <boost/core/ignore_unused.hpp>
18   #include <cstdlib> 18   #include <cstdlib>
19   19  
20   namespace boost { 20   namespace boost {
21   namespace urls { 21   namespace urls {
22   namespace detail { 22   namespace detail {
23   23  
24   constexpr 24   constexpr
25   char const* const hexdigs[] = { 25   char const* const hexdigs[] = {
26   "0123456789ABCDEF", 26   "0123456789ABCDEF",
27   "0123456789abcdef" }; 27   "0123456789abcdef" };
28   28  
29   //------------------------------------------------ 29   //------------------------------------------------
30   30  
31   // re-encode is to percent-encode a 31   // re-encode is to percent-encode a
32   // string that can already contain 32   // string that can already contain
33   // escapes. Characters not in the 33   // escapes. Characters not in the
34   // unreserved set are escaped, and 34   // unreserved set are escaped, and
35   // escapes are passed through unchanged. 35   // escapes are passed through unchanged.
36   // 36   //
37   template<class CharSet> 37   template<class CharSet>
38   std::size_t 38   std::size_t
HITCBC 39   1724 re_encoded_size_unsafe( 39   1724 re_encoded_size_unsafe(
40   core::string_view s, 40   core::string_view s,
41   CharSet const& unreserved) noexcept 41   CharSet const& unreserved) noexcept
42   { 42   {
HITCBC 43   1724 std::size_t n = 0; 43   1724 std::size_t n = 0;
HITCBC 44   1724 auto it = s.begin(); 44   1724 auto it = s.begin();
HITCBC 45   1724 auto const end = s.end(); 45   1724 auto const end = s.end();
HITCBC 46   7397 while(it != end) 46   7397 while(it != end)
47   { 47   {
HITCBC 48   5673 if(*it != '%') 48   5673 if(*it != '%')
49   { 49   {
HITCBC 50   5443 if( unreserved(*it) ) 50   5443 if( unreserved(*it) )
HITCBC 51   5144 n += 1; 51   5144 n += 1;
52   else 52   else
HITCBC 53   299 n += 3; 53   299 n += 3;
HITCBC 54   5443 ++it; 54   5443 ++it;
55   } 55   }
56   else 56   else
57   { 57   {
HITCBC 58   230 BOOST_ASSERT(end - it >= 3); 58   230 BOOST_ASSERT(end - it >= 3);
HITCBC 59   230 BOOST_ASSERT( 59   230 BOOST_ASSERT(
60   grammar::hexdig_value( 60   grammar::hexdig_value(
61   it[1]) >= 0); 61   it[1]) >= 0);
HITCBC 62   230 BOOST_ASSERT( 62   230 BOOST_ASSERT(
63   grammar::hexdig_value( 63   grammar::hexdig_value(
64   it[2]) >= 0); 64   it[2]) >= 0);
HITCBC 65   230 n += 3; 65   230 n += 3;
HITCBC 66   230 it += 3; 66   230 it += 3;
67   } 67   }
68   } 68   }
HITCBC 69   1724 return n; 69   1724 return n;
70   } 70   }
71   71  
72   // unchecked 72   // unchecked
73   // returns decoded size 73   // returns decoded size
74   template<class CharSet> 74   template<class CharSet>
75   std::size_t 75   std::size_t
HITCBC 76   2138 re_encode_unsafe( 76   2138 re_encode_unsafe(
77   char*& dest_, 77   char*& dest_,
78   char const* const end, 78   char const* const end,
79   core::string_view s, 79   core::string_view s,
80   CharSet const& unreserved) noexcept 80   CharSet const& unreserved) noexcept
81   { 81   {
82   static constexpr bool lower_case = false; 82   static constexpr bool lower_case = false;
HITCBC 83   2138 char const* const hex = detail::hexdigs[lower_case]; 83   2138 char const* const hex = detail::hexdigs[lower_case];
HITCBC 84   2138 auto const encode = [end, hex]( 84   2138 auto const encode = [end, hex](
85   char*& dest, 85   char*& dest,
86   char c0) noexcept 86   char c0) noexcept
87   { 87   {
HITCBC 88   318 auto c = static_cast<unsigned char>(c0); 88   318 auto c = static_cast<unsigned char>(c0);
HITCBC 89   318 ignore_unused(end); 89   318 ignore_unused(end);
HITCBC 90   318 *dest++ = '%'; 90   318 *dest++ = '%';
HITCBC 91   318 BOOST_ASSERT(dest != end); 91   318 BOOST_ASSERT(dest != end);
HITCBC 92   318 *dest++ = hex[c>>4]; 92   318 *dest++ = hex[c>>4];
HITCBC 93   318 BOOST_ASSERT(dest != end); 93   318 BOOST_ASSERT(dest != end);
HITCBC 94   318 *dest++ = hex[c&0xf]; 94   318 *dest++ = hex[c&0xf];
95   }; 95   };
96   ignore_unused(end); 96   ignore_unused(end);
97   97  
HITCBC 98   2138 auto dest = dest_; 98   2138 auto dest = dest_;
HITCBC 99   2138 auto const dest0 = dest; 99   2138 auto const dest0 = dest;
HITCBC 100   2138 auto const last = s.end(); 100   2138 auto const last = s.end();
HITCBC 101   2138 std::size_t dn = 0; 101   2138 std::size_t dn = 0;
HITCBC 102   2138 auto it = s.begin(); 102   2138 auto it = s.begin();
HITCBC 103   8372 while(it != last) 103   8372 while(it != last)
104   { 104   {
HITCBC 105   6234 BOOST_ASSERT(dest != end); 105   6234 BOOST_ASSERT(dest != end);
HITCBC 106   6234 if(*it != '%') 106   6234 if(*it != '%')
107   { 107   {
HITCBC 108   5978 if(unreserved(*it)) 108   5978 if(unreserved(*it))
109   { 109   {
HITCBC 110   5660 *dest++ = *it; 110   5660 *dest++ = *it;
111   } 111   }
112   else 112   else
113   { 113   {
HITCBC 114   318 encode(dest, *it); 114   318 encode(dest, *it);
HITCBC 115   318 dn += 2; 115   318 dn += 2;
116   } 116   }
HITCBC 117   5978 ++it; 117   5978 ++it;
118   } 118   }
119   else 119   else
120   { 120   {
HITCBC 121   256 *dest++ = *it++; 121   256 *dest++ = *it++;
HITCBC 122   256 BOOST_ASSERT(dest != end); 122   256 BOOST_ASSERT(dest != end);
HITCBC 123   256 *dest++ = *it++; 123   256 *dest++ = *it++;
HITCBC 124   256 BOOST_ASSERT(dest != end); 124   256 BOOST_ASSERT(dest != end);
HITCBC 125   256 *dest++ = *it++; 125   256 *dest++ = *it++;
HITCBC 126   256 dn += 2; 126   256 dn += 2;
127   } 127   }
128   } 128   }
HITCBC 129   2138 dest_ = dest; 129   2138 dest_ = dest;
HITCBC 130   2138 return dest - dest0 - dn; 130   2138 return dest - dest0 - dn;
131   } 131   }
132   132  
133   } // detail 133   } // detail
134   } // urls 134   } // urls
135   } // boost 135   } // boost
136   136  
137   #endif 137   #endif