123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- //
- // Copyright (c) 2019 Vinnie Falco ([email protected])
- // Copyright (c) 2022 Alan de Freitas ([email protected])
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // Official repository: https://github.com/boostorg/url
- //
- #ifndef BOOST_URL_DETAIL_ENCODE_HPP
- #define BOOST_URL_DETAIL_ENCODE_HPP
- #include <boost/url/encoding_opts.hpp>
- #include <boost/url/pct_string_view.hpp>
- #include <boost/url/grammar/hexdig_chars.hpp>
- #include <boost/core/ignore_unused.hpp>
- #include <cstdlib>
- namespace boost {
- namespace urls {
- namespace detail {
- constexpr
- char const* const hexdigs[] = {
- "0123456789ABCDEF",
- "0123456789abcdef" };
- //------------------------------------------------
- // re-encode is to percent-encode a
- // string that can already contain
- // escapes. Characters not in the
- // unreserved set are escaped, and
- // escapes are passed through unchanged.
- //
- template<class CharSet>
- std::size_t
- re_encoded_size_unsafe(
- core::string_view s,
- CharSet const& unreserved,
- encoding_opts opt) noexcept
- {
- std::size_t n = 0;
- auto const end = s.end();
- auto it = s.begin();
- if(opt.space_as_plus)
- {
- while(it != end)
- {
- if(*it != '%')
- {
- if( unreserved(*it)
- || *it == ' ')
- n += 1;
- else
- n += 3;
- ++it;
- }
- else
- {
- BOOST_ASSERT(end - it >= 3);
- BOOST_ASSERT(
- grammar::hexdig_value(
- it[1]) >= 0);
- BOOST_ASSERT(
- grammar::hexdig_value(
- it[2]) >= 0);
- n += 3;
- it += 3;
- }
- }
- }
- else
- {
- while(it != end)
- {
- if(*it != '%')
- {
- if(unreserved(*it))
- n += 1;
- else
- n += 3;
- ++it;
- }
- else
- {
- BOOST_ASSERT(end - it >= 3);
- BOOST_ASSERT(
- grammar::hexdig_value(
- it[1]) >= 0);
- BOOST_ASSERT(
- grammar::hexdig_value(
- it[2]) >= 0);
- n += 3;
- it += 3;
- }
- }
- }
- return n;
- }
- // unchecked
- // returns decoded size
- template<class CharSet>
- std::size_t
- re_encode_unsafe(
- char*& dest_,
- char const* const end,
- core::string_view s,
- CharSet const& unreserved,
- encoding_opts opt) noexcept
- {
- char const* const hex =
- detail::hexdigs[opt.lower_case];
- auto const encode = [end, hex](
- char*& dest,
- char c0) noexcept
- {
- auto c = static_cast<unsigned char>(c0);
- ignore_unused(end);
- *dest++ = '%';
- BOOST_ASSERT(dest != end);
- *dest++ = hex[c>>4];
- BOOST_ASSERT(dest != end);
- *dest++ = hex[c&0xf];
- };
- ignore_unused(end);
- auto dest = dest_;
- auto const dest0 = dest;
- auto const last = s.end();
- std::size_t dn = 0;
- auto it = s.begin();
- if(opt.space_as_plus)
- {
- while(it != last)
- {
- BOOST_ASSERT(dest != end);
- if(*it != '%')
- {
- if(*it == ' ')
- {
- *dest++ = '+';
- }
- else if(unreserved(*it))
- {
- *dest++ = *it;
- }
- else
- {
- encode(dest, *it);
- dn += 2;
- }
- ++it;
- }
- else
- {
- *dest++ = *it++;
- BOOST_ASSERT(dest != end);
- *dest++ = *it++;
- BOOST_ASSERT(dest != end);
- *dest++ = *it++;
- dn += 2;
- }
- }
- }
- else
- {
- while(it != last)
- {
- BOOST_ASSERT(dest != end);
- if(*it != '%')
- {
- if(unreserved(*it))
- {
- *dest++ = *it;
- }
- else
- {
- encode(dest, *it);
- dn += 2;
- }
- ++it;
- }
- else
- {
- *dest++ = *it++;
- BOOST_ASSERT(dest != end);
- *dest++ = *it++;
- BOOST_ASSERT(dest != end);
- *dest++ = *it++;
- dn += 2;
- }
- }
- }
- dest_ = dest;
- return dest - dest0 - dn;
- }
- } // detail
- } // urls
- } // boost
- #endif
|