TLA 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 HIT 1724 : re_encoded_size_unsafe(
40 : core::string_view s,
41 : CharSet const& unreserved) noexcept
42 : {
43 1724 : std::size_t n = 0;
44 1724 : auto it = s.begin();
45 1724 : auto const end = s.end();
46 7397 : while(it != end)
47 : {
48 5673 : if(*it != '%')
49 : {
50 5443 : if( unreserved(*it) )
51 5144 : n += 1;
52 : else
53 299 : n += 3;
54 5443 : ++it;
55 : }
56 : else
57 : {
58 230 : BOOST_ASSERT(end - it >= 3);
59 230 : BOOST_ASSERT(
60 : grammar::hexdig_value(
61 : it[1]) >= 0);
62 230 : BOOST_ASSERT(
63 : grammar::hexdig_value(
64 : it[2]) >= 0);
65 230 : n += 3;
66 230 : it += 3;
67 : }
68 : }
69 1724 : return n;
70 : }
71 :
72 : // unchecked
73 : // returns decoded size
74 : template<class CharSet>
75 : std::size_t
76 2138 : re_encode_unsafe(
77 : char*& dest_,
78 : char const* const end,
79 : core::string_view s,
80 : CharSet const& unreserved) noexcept
81 : {
82 : static constexpr bool lower_case = false;
83 2138 : char const* const hex = detail::hexdigs[lower_case];
84 2138 : auto const encode = [end, hex](
85 : char*& dest,
86 : char c0) noexcept
87 : {
88 318 : auto c = static_cast<unsigned char>(c0);
89 318 : ignore_unused(end);
90 318 : *dest++ = '%';
91 318 : BOOST_ASSERT(dest != end);
92 318 : *dest++ = hex[c>>4];
93 318 : BOOST_ASSERT(dest != end);
94 318 : *dest++ = hex[c&0xf];
95 : };
96 : ignore_unused(end);
97 :
98 2138 : auto dest = dest_;
99 2138 : auto const dest0 = dest;
100 2138 : auto const last = s.end();
101 2138 : std::size_t dn = 0;
102 2138 : auto it = s.begin();
103 8372 : while(it != last)
104 : {
105 6234 : BOOST_ASSERT(dest != end);
106 6234 : if(*it != '%')
107 : {
108 5978 : if(unreserved(*it))
109 : {
110 5660 : *dest++ = *it;
111 : }
112 : else
113 : {
114 318 : encode(dest, *it);
115 318 : dn += 2;
116 : }
117 5978 : ++it;
118 : }
119 : else
120 : {
121 256 : *dest++ = *it++;
122 256 : BOOST_ASSERT(dest != end);
123 256 : *dest++ = *it++;
124 256 : BOOST_ASSERT(dest != end);
125 256 : *dest++ = *it++;
126 256 : dn += 2;
127 : }
128 : }
129 2138 : dest_ = dest;
130 2138 : return dest - dest0 - dn;
131 : }
132 :
133 : } // detail
134 : } // urls
135 : } // boost
136 :
137 : #endif
|