GCC Code Coverage Report


Directory: libs/url/
File: boost/url/pct_string_view.hpp
Date: 2024-08-19 20:08:56
Exec Total Coverage
Lines: 25 25 100.0%
Functions: 39 42 92.9%
Branches: 1 2 50.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2022 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_PCT_STRING_VIEW_HPP
11 #define BOOST_URL_PCT_STRING_VIEW_HPP
12
13 #include <boost/url/detail/config.hpp>
14 #include <boost/url/encoding_opts.hpp>
15 #include <boost/url/error_types.hpp>
16 #include <boost/core/detail/string_view.hpp>
17 #include <boost/url/grammar/string_token.hpp>
18 #include <boost/url/grammar/string_view_base.hpp>
19 #include <cstddef>
20 #include <iterator>
21 #include <string>
22 #include <type_traits>
23 #include <utility>
24
25 namespace boost {
26 namespace urls {
27
28 //------------------------------------------------
29
30 #ifndef BOOST_URL_DOCS
31 class decode_view;
32 class pct_string_view;
33
34 pct_string_view
35 make_pct_string_view_unsafe(
36 char const*, std::size_t,
37 std::size_t) noexcept;
38
39 namespace detail {
40 core::string_view&
41 ref(pct_string_view& s) noexcept;
42 } // detail
43 #endif
44
45 //------------------------------------------------
46
47 /** A reference to a valid percent-encoded string
48
49 Objects of this type behave like a
50 `core::string_view` and have the same interface,
51 but offer an additional invariant: they can
52 only be constructed from strings containing
53 valid percent-escapes.
54
55 Attempting construction from a string
56 containing invalid or malformed percent
57 escapes results in an exception.
58
59 @par Operators
60 The following operators are supported between
61 @ref pct_string_view and any object that is
62 convertible to `core::string_view`
63
64 @code
65 bool operator==( pct_string_view, pct_string_view ) noexcept;
66 bool operator!=( pct_string_view, pct_string_view ) noexcept;
67 bool operator<=( pct_string_view, pct_string_view ) noexcept;
68 bool operator< ( pct_string_view, pct_string_view ) noexcept;
69 bool operator> ( pct_string_view, pct_string_view ) noexcept;
70 bool operator>=( pct_string_view, pct_string_view ) noexcept;
71 @endcode
72 */
73 class pct_string_view final
74 : public grammar::string_view_base
75 {
76 std::size_t dn_ = 0;
77
78 #ifndef BOOST_URL_DOCS
79 friend
80 pct_string_view
81 make_pct_string_view_unsafe(
82 char const*, std::size_t,
83 std::size_t) noexcept;
84
85 friend
86 core::string_view&
87 detail::ref(pct_string_view&) noexcept;
88 #endif
89
90 // unsafe
91 34583 pct_string_view(
92 char const* data,
93 std::size_t size,
94 std::size_t dn) noexcept
95 34583 : string_view_base(data, size)
96 34583 , dn_(dn)
97 {
98 34583 }
99
100 BOOST_URL_DECL
101 void
102 decode_impl(
103 string_token::arg& dest,
104 encoding_opts opt) const;
105
106 public:
107 /** Constructor
108
109 Default constructed string are empty.
110
111 @par Complexity
112 Constant.
113
114 @par Exception Safety
115 Throws nothing.
116 */
117 16491 constexpr pct_string_view() = default;
118
119 /** Constructor
120
121 The copy references the same
122 underlying character buffer.
123 Ownership is not transferred.
124
125 @par Postconditions
126 @code
127 this->data() == other.data()
128 @endcode
129
130 @par Complexity
131 Constant.
132
133 @par Exception Safety
134 Throws nothing.
135
136 @par other The string to copy.
137 */
138 constexpr
139 pct_string_view(
140 pct_string_view const& other) = default;
141
142 /** Constructor
143
144 The newly constructed string references
145 the specified character buffer.
146 Ownership is not transferred.
147
148 @par Postconditions
149 @code
150 this->data() == core::string_view(s).data()
151 @endcode
152
153 @par Complexity
154 Linear in `core::string_view(s).size()`.
155
156 @par Exception Safety
157 Exceptions thrown on invalid input.
158
159 @throw system_error
160 The string contains an invalid percent encoding.
161
162 @tparam String A type convertible to `core::string_view`
163
164 @param s The string to construct from.
165 */
166 template<
167 class String
168 #ifndef BOOST_URL_DOCS
169 , class = typename std::enable_if<
170 std::is_convertible<
171 String,
172 core::string_view
173 >::value>::type
174 #endif
175 >
176 1862 pct_string_view(
177 String const& s)
178 : pct_string_view(
179 1862 detail::to_sv(s))
180 {
181 1752 }
182
183 /** Constructor (deleted)
184 */
185 pct_string_view(
186 std::nullptr_t) = delete;
187
188 /** Constructor
189
190 The newly constructed string references
191 the specified character buffer. Ownership
192 is not transferred.
193
194 @par Postconditions
195 @code
196 this->data() == s && this->size() == len
197 @endcode
198
199 @par Complexity
200 Linear in `len`.
201
202 @par Exception Safety
203 Exceptions thrown on invalid input.
204
205 @throw system_error
206 The string contains an invalid percent encoding.
207
208 @param s, len The string to construct from.
209 */
210 182 pct_string_view(
211 char const* s,
212 std::size_t len)
213 182 : pct_string_view(
214
1/2
✓ Branch 2 taken 182 times.
✗ Branch 3 not taken.
182 core::string_view(s, len))
215 {
216 182 }
217
218 /** Constructor
219
220 The newly constructed string references
221 the specified character buffer. Ownership
222 is not transferred.
223
224 @par Postconditions
225 @code
226 this->data() == s.data() && this->size() == s.size()
227 @endcode
228
229 @par Complexity
230 Linear in `s.size()`.
231
232 @par Exception Safety
233 Exceptions thrown on invalid input.
234
235 @throw system_error
236 The string contains an invalid percent encoding.
237
238 @param s The string to construct from.
239 */
240 BOOST_URL_DECL
241 pct_string_view(
242 core::string_view s);
243
244 /** Assignment
245
246 The copy references the same
247 underlying character buffer.
248 Ownership is not transferred.
249
250 @par Postconditions
251 @code
252 this->data() == other.data()
253 @endcode
254
255 @par Complexity
256 Constant.
257
258 @par Exception Safety
259 Throws nothing.
260
261 @par other The string to copy.
262 */
263 pct_string_view& operator=(
264 pct_string_view const& other) = default;
265
266 /** Return a valid percent-encoded string
267
268 If `s` is a valid percent-encoded string,
269 the function returns the buffer as a valid
270 view which may be used to perform decoding
271 or measurements.
272 Otherwise the result contains an error code.
273 Upon success, the returned view references
274 the original character buffer;
275 Ownership is not transferred.
276
277 @par Complexity
278 Linear in `s.size()`.
279
280 @par Exception Safety
281 Throws nothing.
282
283 @param s The string to validate.
284 */
285 friend
286 BOOST_URL_DECL
287 system::result<pct_string_view>
288 make_pct_string_view(
289 core::string_view s) noexcept;
290
291 //--------------------------------------------
292
293 /** Return the decoded size
294
295 This function returns the number of
296 characters in the resulting string if
297 percent escapes were converted into
298 ordinary characters.
299
300 @par Complexity
301 Constant.
302
303 @par Exception Safety
304 Throws nothing.
305 */
306 std::size_t
307 14698 decoded_size() const noexcept
308 {
309 14698 return dn_;
310 }
311
312 /** Return the string as a range of decoded characters
313
314 @par Complexity
315 Constant.
316
317 @par Exception Safety
318 Throws nothing.
319
320 @see
321 @ref decode_view.
322 */
323 decode_view
324 operator*() const noexcept;
325
326 /** Return the string with percent-decoding
327
328 This function converts percent escapes
329 in the string into ordinary characters
330 and returns the result.
331 When called with no arguments, the
332 return type is `std::string`.
333 Otherwise, the return type and style
334 of output is determined by which string
335 token is passed.
336
337 @par Example
338 @code
339 assert( pct_string_view( "Program%20Files" ).decode() == "Program Files" );
340 @endcode
341
342 @par Complexity
343 Linear in `this->size()`.
344
345 @par Exception Safety
346 Calls to allocate may throw.
347 String tokens may throw exceptions.
348
349 @param opt The options for encoding. If
350 this parameter is omitted, the default
351 options are used.
352
353 @param token An optional string token.
354 If this parameter is omitted, then
355 a new `std::string` is returned.
356 Otherwise, the function return type
357 is the result type of the token.
358
359 @see
360 @ref encoding_opts,
361 @ref string_token::return_string.
362 */
363 template<BOOST_URL_STRTOK_TPARAM>
364 BOOST_URL_STRTOK_RETURN
365 3317 decode(
366 encoding_opts opt = {},
367 BOOST_URL_STRTOK_ARG(token)) const
368 {
369 /* If you get a compile error here, it
370 means that the token you passed does
371 not meet the requirements stated
372 in the documentation.
373 */
374 static_assert(
375 string_token::is_token<
376 StringToken>::value,
377 "Type requirements not met");
378
379 3317 decode_impl(token, opt);
380 3317 return token.result();
381 }
382
383 #ifndef BOOST_URL_DOCS
384 /// Arrow support
385 pct_string_view const*
386 93 operator->() const noexcept
387 {
388 93 return this;
389 }
390 #endif
391
392 //--------------------------------------------
393
394 // VFALCO No idea why this fails in msvc
395 /** Swap
396 */
397 /*BOOST_CXX14_CONSTEXPR*/ void swap(
398 pct_string_view& s ) noexcept
399 {
400 string_view_base::swap(s);
401 std::swap(dn_, s.dn_);
402 }
403 };
404
405 //------------------------------------------------
406
407 #ifndef BOOST_URL_DOCS
408 namespace detail {
409 // obtain modifiable reference to
410 // underlying string, to handle
411 // self-intersection on modifiers.
412 inline
413 core::string_view&
414 578 ref(pct_string_view& s) noexcept
415 {
416 578 return s.s_;
417 }
418
419 } // detail
420 #endif
421
422 //------------------------------------------------
423
424 /** Return a valid percent-encoded string
425
426 If `s` is a valid percent-encoded string,
427 the function returns the buffer as a valid
428 view which may be used to perform decoding
429 or measurements.
430 Otherwise the result contains an error code.
431 Upon success, the returned view references
432 the original character buffer;
433 Ownership is not transferred.
434
435 @par Complexity
436 Linear in `s.size()`.
437
438 @par Exception Safety
439 Throws nothing.
440
441 @param s The string to validate.
442 */
443 BOOST_URL_DECL
444 system::result<pct_string_view>
445 make_pct_string_view(
446 core::string_view s) noexcept;
447
448 #ifndef BOOST_URL_DOCS
449 // VFALCO semi-private for now
450 inline
451 pct_string_view
452 34583 make_pct_string_view_unsafe(
453 char const* data,
454 std::size_t size,
455 std::size_t decoded_size) noexcept
456 {
457 #if 0
458 BOOST_ASSERT(! make_pct_string_view(
459 core::string_view(data, size)).has_error());
460 #endif
461 return pct_string_view(
462 34583 data, size, decoded_size);
463 }
464 #endif
465
466 #ifndef BOOST_URL_DOCS
467 namespace detail {
468 template <>
469 inline
470 core::string_view
471 9865 to_sv(pct_string_view const& s) noexcept
472 {
473 9865 return s.substr();
474 }
475 } // detail
476 #endif
477
478 } // urls
479 } // boost
480
481 #endif
482