include/boost/url/impl/encode.hpp

76.8% Lines (370/482) 85.0% List of functions (17/20)
encode.hpp
f(x) Functions (20)
Function Calls Lines Blocks
unsigned long boost::urls::encoded_size<boost::urls::encode_test::test_chars>(boost::core::basic_string_view<char>, boost::urls::encode_test::test_chars const&, boost::urls::encoding_opts) :31 43x 84.6% 81.0% unsigned long boost::urls::encoded_size<boost::urls::grammar::lut_chars>(boost::core::basic_string_view<char>, boost::urls::grammar::lut_chars const&, boost::urls::encoding_opts) :31 5476x 57.7% 81.0% unsigned long boost::urls::encoded_size<boost::urls::space_as_plus_test_chars<false, false> >(boost::core::basic_string_view<char>, boost::urls::space_as_plus_test_chars<false, false> const&, boost::urls::encoding_opts) :31 1x 61.5% 58.0% unsigned long boost::urls::encoded_size<boost::urls::space_as_plus_test_chars<false, true> >(boost::core::basic_string_view<char>, boost::urls::space_as_plus_test_chars<false, true> const&, boost::urls::encoding_opts) :31 1x 61.5% 58.0% unsigned long boost::urls::encoded_size<boost::urls::space_as_plus_test_chars<true, false> >(boost::core::basic_string_view<char>, boost::urls::space_as_plus_test_chars<true, false> const&, boost::urls::encoding_opts) :31 1x 61.5% 58.0% unsigned long boost::urls::encoded_size<boost::urls::space_as_plus_test_chars<true, true> >(boost::core::basic_string_view<char>, boost::urls::space_as_plus_test_chars<true, true> const&, boost::urls::encoding_opts) :31 1x 61.5% 58.0% boost::urls::encoded_size<boost::urls::grammar::lut_chars>(boost::core::basic_string_view<char>, boost::urls::grammar::lut_chars const&, boost::urls::encoding_opts)::{lambda(boost::urls::grammar::lut_chars const&, char)#1}::operator()(boost::urls::grammar::lut_chars const&, char) const :76 0 0.0% 0.0% boost::urls::encoded_size<boost::urls::grammar::lut_chars>(boost::core::basic_string_view<char>, boost::urls::grammar::lut_chars const&, boost::urls::encoding_opts)::{lambda(boost::urls::grammar::lut_chars const&, char)#2}::operator()(boost::urls::grammar::lut_chars const&, char) const :77 20081x 50.0% 100.0% boost::urls::encoded_size<boost::urls::grammar::lut_chars>(boost::core::basic_string_view<char>, boost::urls::grammar::lut_chars const&, boost::urls::encoding_opts)::{lambda(boost::urls::grammar::lut_chars const&, char)#3}::operator()(boost::urls::grammar::lut_chars const&, char) const :79 0 0.0% 0.0% boost::urls::encoded_size<boost::urls::grammar::lut_chars>(boost::core::basic_string_view<char>, boost::urls::grammar::lut_chars const&, boost::urls::encoding_opts)::{lambda(boost::urls::grammar::lut_chars const&, char)#4}::operator()(boost::urls::grammar::lut_chars const&, char) const :80 0 87.5% 0.0% unsigned long boost::urls::encode<boost::urls::encode_test::test_chars>(char*, unsigned long, boost::core::basic_string_view<char>, boost::urls::encode_test::test_chars const&, boost::urls::encoding_opts) :102 56x 100.0% 98.0% unsigned long boost::urls::encode<boost::urls::grammar::lut_chars>(char*, unsigned long, boost::core::basic_string_view<char>, boost::urls::grammar::lut_chars const&, boost::urls::encoding_opts) :102 21762x 51.2% 90.0% boost::urls::encode<boost::urls::grammar::lut_chars>(char*, unsigned long, boost::core::basic_string_view<char>, boost::urls::grammar::lut_chars const&, boost::urls::encoding_opts)::{lambda(char*&, unsigned char)#1}::operator()(char*&, unsigned char) const :122 244630x 92.9% 100.0% unsigned long boost::urls::encode_unsafe<boost::urls::encode_test::test_chars>(char*, unsigned long, boost::core::basic_string_view<char>, boost::urls::encode_test::test_chars const&, boost::urls::encoding_opts) :195 17x 100.0% 91.0% unsigned long boost::urls::encode_unsafe<boost::urls::grammar::lut_chars>(char*, unsigned long, boost::core::basic_string_view<char>, boost::urls::grammar::lut_chars const&, boost::urls::encoding_opts) :195 1548x 100.0% 85.0% unsigned long boost::urls::encode_unsafe<boost::urls::space_as_plus_test_chars<false, false> >(char*, unsigned long, boost::core::basic_string_view<char>, boost::urls::space_as_plus_test_chars<false, false> const&, boost::urls::encoding_opts) :195 1x 75.0% 67.0% unsigned long boost::urls::encode_unsafe<boost::urls::space_as_plus_test_chars<false, true> >(char*, unsigned long, boost::core::basic_string_view<char>, boost::urls::space_as_plus_test_chars<false, true> const&, boost::urls::encoding_opts) :195 1x 75.0% 67.0% unsigned long boost::urls::encode_unsafe<boost::urls::space_as_plus_test_chars<true, false> >(char*, unsigned long, boost::core::basic_string_view<char>, boost::urls::space_as_plus_test_chars<true, false> const&, boost::urls::encoding_opts) :195 1x 75.0% 67.0% unsigned long boost::urls::encode_unsafe<boost::urls::space_as_plus_test_chars<true, true> >(char*, unsigned long, boost::core::basic_string_view<char>, boost::urls::space_as_plus_test_chars<true, true> const&, boost::urls::encoding_opts) :195 1x 75.0% 67.0% boost::urls::encode_unsafe<boost::urls::grammar::lut_chars>(char*, unsigned long, boost::core::basic_string_view<char>, boost::urls::grammar::lut_chars const&, boost::urls::encoding_opts)::{lambda(char*&, unsigned char)#1}::operator()(char*&, unsigned char) const :215 677x 97.0% 67.0%
Line TLA Hits 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/core/detail/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 5523x encoded_size(
32 core::string_view s,
33 CS const& allowed,
34 encoding_opts opt) noexcept
35 {
36 /*
37 If you get a compilation error here, it
38 means that the value you passed does
39 not meet the requirements stated in
40 the documentation.
41 */
42 BOOST_CORE_STATIC_ASSERT(
43 grammar::is_charset<CS>::value);
44
45 5523x std::size_t n = 0;
46 5523x auto it = s.data();
47 5523x auto const last = it + s.size();
48
49 5523x if (!opt.space_as_plus)
50 {
51 25592x while (it != last)
52 {
53 22571x char const c = *it;
54 22571x if (allowed(c))
55 {
56 19533x ++n;
57 }
58 else
59 {
60 3038x n += 3;
61 }
62 22571x ++it;
63 }
64 }
65 else
66 {
67 // '+' is always encoded (thus
68 // spending 3 chars) even if
69 // allowed because "%2B" and
70 // "+" have different meanings
71 // when space as plus is enabled
72 using FNT = bool (*)(CS const& allowed, char);
73 2502x FNT takes_one_char =
74 5004x allowed('+') ?
75 2500x (allowed(' ') ?
76 1x FNT([](CS const& allowed, char c){ return allowed(c) && c != '+'; }) :
77 22580x FNT([](CS const& allowed, char c){ return (allowed(c) || c == ' ') && c != '+'; })) :
78 2x (allowed(' ') ?
79 1x FNT([](CS const& allowed, char c){ return allowed(c); }) :
80 1x FNT([](CS const& allowed, char c){ return allowed(c) || c == ' '; }));
81 22624x while (it != last)
82 {
83 20122x char const c = *it;
84 20122x if (takes_one_char(allowed, c))
85 {
86 16975x ++n;
87 }
88 else
89 {
90 3147x n += 3;
91 }
92 20122x ++it;
93 }
94 }
95 5523x return n;
96 }
97
98 //------------------------------------------------
99
100 template<BOOST_URL_CONSTRAINT(grammar::CharSet) CS>
101 std::size_t
102 21818x encode(
103 char* dest,
104 std::size_t size,
105 core::string_view s,
106 CS const& allowed,
107 encoding_opts opt)
108 {
109 /* If you get a compilation error here, it
110 means that the value you passed does
111 not meet the requirements stated in
112 the documentation.
113 */
114 BOOST_CORE_STATIC_ASSERT(
115 grammar::is_charset<CS>::value);
116
117 // '%' must be reserved
118 21818x BOOST_ASSERT(!allowed('%'));
119
120 21818x char const* const hex =
121 21818x detail::hexdigs[opt.lower_case];
122 266448x auto const encode = [hex](
123 char*& dest,
124 unsigned char c) noexcept
125 {
126 244630x *dest++ = '%';
127 244630x *dest++ = hex[c>>4];
128 244630x *dest++ = hex[c&0xf];
129 };
130
131 21818x auto it = s.data();
132 21818x auto const end = dest + size;
133 21818x auto const last = it + s.size();
134 21818x auto const dest0 = dest;
135
136 21818x if (!opt.space_as_plus)
137 {
138 1303128x while(it != last)
139 {
140 1294002x char const c = *it;
141 1294002x if (allowed(c))
142 {
143 1048403x if(dest == end)
144 6102x return dest - dest0;
145 1042301x *dest++ = c;
146 1042301x ++it;
147 1042301x continue;
148 }
149 245599x if (end - dest < 3)
150 4088x return dest - dest0;
151 241511x encode(dest, c);
152 241511x ++it;
153 }
154 9126x return dest - dest0;
155 }
156 else
157 {
158 22594x while (it != last)
159 {
160 20106x char const c = *it;
161 20106x if (c == ' ')
162 {
163 262x if(dest == end)
164 2x return dest - dest0;
165 260x *dest++ = '+';
166 260x ++it;
167 260x continue;
168 }
169 36537x else if (
170 19844x allowed(c) &&
171 c != '+')
172 {
173 16696x if(dest == end)
174 3x return dest - dest0;
175 16693x *dest++ = c;
176 16693x ++it;
177 16693x continue;
178 }
179 3148x if(end - dest < 3)
180 9x return dest - dest0;
181 3139x encode(dest, c);
182 3139x ++it;
183 }
184 }
185 2488x return dest - dest0;
186 }
187
188 //------------------------------------------------
189
190 // unsafe encode just
191 // asserts on the output buffer
192 //
193 template<BOOST_URL_CONSTRAINT(grammar::CharSet) CS>
194 std::size_t
195 1569x encode_unsafe(
196 char* dest,
197 std::size_t size,
198 core::string_view s,
199 CS const& allowed,
200 encoding_opts opt)
201 {
202 BOOST_CORE_STATIC_ASSERT(
203 grammar::is_charset<CS>::value);
204
205 // '%' must be reserved
206 1569x BOOST_ASSERT(!allowed('%'));
207
208 1569x auto it = s.data();
209 1569x auto const last = it + s.size();
210 1569x auto const end = dest + size;
211 ignore_unused(end);
212
213 1569x char const* const hex =
214 1569x detail::hexdigs[opt.lower_case];
215 2923x auto const encode = [end, hex](
216 char*& dest,
217 unsigned char c) noexcept
218 {
219 677x ignore_unused(end);
220 677x *dest++ = '%';
221 677x BOOST_ASSERT(dest != end);
222 677x *dest++ = hex[c>>4];
223 677x BOOST_ASSERT(dest != end);
224 677x *dest++ = hex[c&0xf];
225 };
226
227 1569x auto const dest0 = dest;
228 1569x if (!opt.space_as_plus)
229 {
230 8140x while(it != last)
231 {
232 6584x BOOST_ASSERT(dest != end);
233 6584x char const c = *it;
234 6584x if(allowed(c))
235 {
236 5899x *dest++ = c;
237 }
238 else
239 {
240 685x encode(dest, c);
241 }
242 6584x ++it;
243 }
244 }
245 else
246 {
247 53x while(it != last)
248 {
249 40x BOOST_ASSERT(dest != end);
250 40x char const c = *it;
251 40x if (c == ' ')
252 {
253 9x *dest++ = '+';
254 }
255 31x else if (
256 31x allowed(c) &&
257 c != '+')
258 {
259 23x *dest++ = c;
260 }
261 else
262 {
263 8x encode(dest, c);
264 }
265 40x ++it;
266 }
267 }
268 1569x return dest - dest0;
269 }
270
271 //------------------------------------------------
272
273 template<
274 BOOST_URL_CONSTRAINT(string_token::StringToken) StringToken,
275 BOOST_URL_CONSTRAINT(grammar::CharSet) CS>
276 BOOST_URL_STRTOK_RETURN
277 28x encode(
278 core::string_view s,
279 CS const& allowed,
280 encoding_opts opt,
281 StringToken&& token)
282 {
283 BOOST_CORE_STATIC_ASSERT(
284 grammar::is_charset<CS>::value);
285
286 28x auto const n = encoded_size(
287 s, allowed, opt);
288 28x auto p = token.prepare(n);
289 28x if(n > 0)
290 26x encode_unsafe(
291 p, n, s, allowed, opt);
292 28x return token.result();
293 }
294
295 } // urls
296 } // boost
297
298 #endif
299