GCC Code Coverage Report


Directory: libs/url/
File: boost/url/pct_string_view.hpp
Date: 2024-03-05 20:06:57
Exec Total Coverage
Lines: 25 25 100.0%
Functions: 37 41 90.2%
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 34240 pct_string_view(
92 char const* data,
93 std::size_t size,
94 std::size_t dn) noexcept
95 34240 : string_view_base(data, size)
96 34240 , dn_(dn)
97 {
98 34240 }
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 16381 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 friend
267 BOOST_URL_DECL
268 system::result<pct_string_view>
269 make_pct_string_view(
270 core::string_view s) noexcept;
271
272 //--------------------------------------------
273
274 /** Return the decoded size
275
276 This function returns the number of
277 characters in the resulting string if
278 percent escapes were converted into
279 ordinary characters.
280
281 @par Complexity
282 Constant.
283
284 @par Exception Safety
285 Throws nothing.
286 */
287 std::size_t
288 14636 decoded_size() const noexcept
289 {
290 14636 return dn_;
291 }
292
293 /** Return the string as a range of decoded characters
294
295 @par Complexity
296 Constant.
297
298 @par Exception Safety
299 Throws nothing.
300
301 @see
302 @ref decode_view.
303 */
304 decode_view
305 operator*() const noexcept;
306
307 /** Return the string with percent-decoding
308
309 This function converts percent escapes
310 in the string into ordinary characters
311 and returns the result.
312 When called with no arguments, the
313 return type is `std::string`.
314 Otherwise, the return type and style
315 of output is determined by which string
316 token is passed.
317
318 @par Example
319 @code
320 assert( pct_string_view( "Program%20Files" ).decode() == "Program Files" );
321 @endcode
322
323 @par Complexity
324 Linear in `this->size()`.
325
326 @par Exception Safety
327 Calls to allocate may throw.
328 String tokens may throw exceptions.
329
330 @param opt The options for encoding. If
331 this parameter is omitted, the default
332 options are used.
333
334 @param token An optional string token.
335 If this parameter is omitted, then
336 a new `std::string` is returned.
337 Otherwise, the function return type
338 is the result type of the token.
339
340 @see
341 @ref encoding_opts,
342 @ref string_token::return_string.
343 */
344 template<BOOST_URL_STRTOK_TPARAM>
345 BOOST_URL_STRTOK_RETURN
346 3308 decode(
347 encoding_opts opt = {},
348 BOOST_URL_STRTOK_ARG(token)) const
349 {
350 /* If you get a compile error here, it
351 means that the token you passed does
352 not meet the requirements stated
353 in the documentation.
354 */
355 static_assert(
356 string_token::is_token<
357 StringToken>::value,
358 "Type requirements not met");
359
360 3308 decode_impl(token, opt);
361 3308 return token.result();
362 }
363
364 #ifndef BOOST_URL_DOCS
365 // arrow support
366 pct_string_view const*
367 93 operator->() const noexcept
368 {
369 93 return this;
370 }
371 #endif
372
373 //--------------------------------------------
374
375 // VFALCO No idea why this fails in msvc
376 /** Swap
377 */
378 /*BOOST_CXX14_CONSTEXPR*/ void swap(
379 pct_string_view& s ) noexcept
380 {
381 string_view_base::swap(s);
382 std::swap(dn_, s.dn_);
383 }
384 };
385
386 //------------------------------------------------
387
388 #ifndef BOOST_URL_DOCS
389 namespace detail {
390 // obtain modifiable reference to
391 // underlying string, to handle
392 // self-intersection on modifiers.
393 inline
394 core::string_view&
395 578 ref(pct_string_view& s) noexcept
396 {
397 578 return s.s_;
398 }
399
400 } // detail
401 #endif
402
403 //------------------------------------------------
404
405 /** Return a valid percent-encoded string
406
407 If `s` is a valid percent-encoded string,
408 the function returns the buffer as a valid
409 view which may be used to perform decoding
410 or measurements.
411 Otherwise the result contains an error code.
412 Upon success, the returned view references
413 the original character buffer;
414 Ownership is not transferred.
415
416 @par Complexity
417 Linear in `s.size()`.
418
419 @par Exception Safety
420 Throws nothing.
421
422 @param s The string to validate.
423 */
424 BOOST_URL_DECL
425 system::result<pct_string_view>
426 make_pct_string_view(
427 core::string_view s) noexcept;
428
429 #ifndef BOOST_URL_DOCS
430 // VFALCO semi-private for now
431 inline
432 pct_string_view
433 34240 make_pct_string_view_unsafe(
434 char const* data,
435 std::size_t size,
436 std::size_t decoded_size) noexcept
437 {
438 #if 0
439 BOOST_ASSERT(! make_pct_string_view(
440 core::string_view(data, size)).has_error());
441 #endif
442 return pct_string_view(
443 34240 data, size, decoded_size);
444 }
445 #endif
446
447 #ifndef BOOST_URL_DOCS
448 namespace detail {
449 template <>
450 inline
451 core::string_view
452 9845 to_sv(pct_string_view const& s) noexcept
453 {
454 9845 return s.substr();
455 }
456 } // detail
457 #endif
458
459 } // urls
460 } // boost
461
462 #endif
463