GCC Code Coverage Report


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