Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:26

0001 //
0002 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
0003 // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
0004 //
0005 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0006 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 // Official repository: https://github.com/boostorg/url
0009 //
0010 
0011 #ifndef BOOST_URL_DETAIL_ENCODE_HPP
0012 #define BOOST_URL_DETAIL_ENCODE_HPP
0013 
0014 #include <boost/url/encoding_opts.hpp>
0015 #include <boost/url/pct_string_view.hpp>
0016 #include <boost/url/grammar/hexdig_chars.hpp>
0017 #include <boost/core/ignore_unused.hpp>
0018 #include <cstdlib>
0019 
0020 namespace boost {
0021 namespace urls {
0022 namespace detail {
0023 
0024 constexpr
0025 char const* const hexdigs[] = {
0026     "0123456789ABCDEF",
0027     "0123456789abcdef" };
0028 
0029 //------------------------------------------------
0030 
0031 // re-encode is to percent-encode a
0032 // string that can already contain
0033 // escapes. Characters not in the
0034 // unreserved set are escaped, and
0035 // escapes are passed through unchanged.
0036 //
0037 template<class CharSet>
0038 std::size_t
0039 re_encoded_size_unsafe(
0040     core::string_view s,
0041     CharSet const& unreserved,
0042     encoding_opts opt) noexcept
0043 {
0044     std::size_t n = 0;
0045     auto const end = s.end();
0046     auto it = s.begin();
0047     if(opt.space_as_plus)
0048     {
0049         while(it != end)
0050         {
0051             if(*it != '%')
0052             {
0053                 if( unreserved(*it)
0054                     || *it == ' ')
0055                     n += 1; 
0056                 else
0057                     n += 3;
0058                 ++it;
0059             }
0060             else
0061             {
0062                 BOOST_ASSERT(end - it >= 3);
0063                 BOOST_ASSERT(
0064                     grammar::hexdig_value(
0065                         it[1]) >= 0);
0066                 BOOST_ASSERT(
0067                     grammar::hexdig_value(
0068                         it[2]) >= 0);
0069                 n += 3;
0070                 it += 3;
0071             }
0072         }
0073     }
0074     else
0075     {
0076         while(it != end)
0077         {
0078             if(*it != '%')
0079             {
0080                 if(unreserved(*it))
0081                     n += 1; 
0082                 else
0083                     n += 3;
0084                 ++it;
0085             }
0086             else
0087             {
0088                 BOOST_ASSERT(end - it >= 3);
0089                 BOOST_ASSERT(
0090                     grammar::hexdig_value(
0091                         it[1]) >= 0);
0092                 BOOST_ASSERT(
0093                     grammar::hexdig_value(
0094                         it[2]) >= 0);
0095                 n += 3;
0096                 it += 3;
0097             }
0098         }
0099     }
0100     return n;
0101 }
0102 
0103 // unchecked
0104 // returns decoded size
0105 template<class CharSet>
0106 std::size_t
0107 re_encode_unsafe(
0108     char*& dest_,
0109     char const* const end,
0110     core::string_view s,
0111     CharSet const& unreserved,
0112     encoding_opts opt) noexcept
0113 {
0114     char const* const hex =
0115         detail::hexdigs[opt.lower_case];
0116     auto const encode = [end, hex](
0117         char*& dest,
0118         unsigned char c) noexcept
0119     {
0120         ignore_unused(end);
0121         *dest++ = '%';
0122         BOOST_ASSERT(dest != end);
0123         *dest++ = hex[c>>4];
0124         BOOST_ASSERT(dest != end);
0125         *dest++ = hex[c&0xf];
0126     };
0127     ignore_unused(end);
0128 
0129     auto dest = dest_;
0130     auto const dest0 = dest;
0131     auto const last = s.end();
0132     std::size_t dn = 0;
0133     auto it = s.begin();
0134 
0135     if(opt.space_as_plus)
0136     {
0137         while(it != last)
0138         {
0139             BOOST_ASSERT(dest != end);
0140             if(*it != '%')
0141             {
0142                 if(*it == ' ')
0143                 {
0144                     *dest++ = '+';
0145                 }
0146                 else if(unreserved(*it))
0147                 {
0148                     *dest++ = *it;
0149                 }
0150                 else
0151                 {
0152                     encode(dest, *it);
0153                     dn += 2;
0154                 }
0155                 ++it;
0156             }
0157             else
0158             {
0159                 *dest++ = *it++;
0160                 BOOST_ASSERT(dest != end);
0161                 *dest++ = *it++;
0162                 BOOST_ASSERT(dest != end);
0163                 *dest++ = *it++;
0164                 dn += 2;
0165             }
0166         }
0167     }
0168     else
0169     {
0170         while(it != last)
0171         {
0172             BOOST_ASSERT(dest != end);
0173             if(*it != '%')
0174             {
0175                 if(unreserved(*it))
0176                 {
0177                     *dest++ = *it;
0178                 }
0179                 else
0180                 {
0181                     encode(dest, *it);
0182                     dn += 2;
0183                 }
0184                 ++it;
0185             }
0186             else
0187             {
0188                 *dest++ = *it++;
0189                 BOOST_ASSERT(dest != end);
0190                 *dest++ = *it++;
0191                 BOOST_ASSERT(dest != end);
0192                 *dest++ = *it++;
0193                 dn += 2;
0194             }
0195         }
0196     }
0197     dest_ = dest;
0198     return dest - dest0 - dn;
0199 }
0200 
0201 } // detail
0202 } // urls
0203 } // boost
0204 
0205 #endif