GCC Code Coverage Report


Directory: libs/url/
File: boost/url/grammar/string_token.hpp
Date: 2024-08-19 20:08:56
Exec Total Coverage
Lines: 42 43 97.7%
Functions: 16 16 100.0%
Branches: 3 4 75.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_STRING_TOKEN_HPP
11 #define BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
12
13 #include <boost/url/detail/config.hpp>
14 #include <boost/core/detail/string_view.hpp>
15 #include <boost/url/detail/except.hpp>
16 #include <memory>
17 #include <string>
18
19 namespace boost {
20 namespace urls {
21 namespace string_token {
22
23 /** Base class for string tokens, and algorithm parameters
24
25 This abstract interface provides a means
26 for an algorithm to generically obtain a
27 modifiable, contiguous character buffer
28 of prescribed size. As the author of an
29 algorithm simply declare an rvalue
30 reference as a parameter type.
31
32 <br>
33
34 Instances of this type are intended only
35 to be used once and then destroyed.
36
37 @par Example
38 The declared function accepts any
39 temporary instance of `arg` to be
40 used for writing:
41 @code
42 void algorithm( string_token::arg&& dest );
43 @endcode
44
45 To implement the interface for your type
46 or use-case, derive from the class and
47 implement the prepare function.
48 */
49 struct arg
50 {
51 /** Return a modifiable character buffer
52
53 This function attempts to obtain a
54 character buffer with space for at
55 least `n` characters. Upon success,
56 a pointer to the beginning of the
57 buffer is returned. Ownership is not
58 transferred; the caller should not
59 attempt to free the storage. The
60 buffer shall remain valid until
61 `this` is destroyed.
62
63 @note
64 This function may only be called once.
65 After invoking the function, the only
66 valid operation is destruction.
67 */
68 virtual char* prepare(std::size_t n) = 0;
69
70 /// Virtual destructor
71 6744 virtual ~arg() = default;
72
73 /// Default constructor
74 3372 arg() = default;
75
76 /// Default move constructor
77 arg(arg&&) = default;
78
79 /// Deleted copy constructor
80 arg(arg const&) = delete;
81
82 /// Deleted move assignment
83 arg& operator=(arg&&) = delete;
84
85 /// Deleted copy assignment
86 arg& operator=(arg const&) = delete;
87 };
88
89 //------------------------------------------------
90
91 /** Metafunction returning true if T is a StringToken
92 */
93 #ifdef BOOST_URL_DOCS
94 template<class T>
95 using is_token = __see_below__;
96 #else
97 namespace see_below {
98 /** Metafunction returning true if T is a StringToken
99 */
100 template<class T, class = void>
101 struct is_token : std::false_type {};
102
103 /** Metafunction returning true if T is a StringToken
104 */
105 template<class T>
106 struct is_token<T, void_t<
107 decltype(std::declval<T&>().prepare(
108 std::declval<std::size_t>())),
109 decltype(std::declval<T&>().result())
110 > > : std::integral_constant<bool,
111 std::is_convertible<decltype(
112 std::declval<T&>().result()),
113 typename T::result_type>::value &&
114 std::is_same<decltype(
115 std::declval<T&>().prepare(0)),
116 char*>::value &&
117 std::is_base_of<arg, T>::value &&
118 std::is_convertible<T const volatile*,
119 arg const volatile*>::value
120 >
121 {
122 };
123 } // see_below
124
125 /** Metafunction returning true if T is a StringToken
126 */
127 template<class T>
128 using is_token = see_below::is_token<T>;
129 #endif
130
131 //------------------------------------------------
132
133 /** A token for returning a plain string
134 */
135 #ifdef BOOST_URL_DOCS
136 using return_string = __implementation_defined__;
137 #else
138 namespace implementation_defined {
139 struct return_string
140 : arg
141 {
142 using result_type = std::string;
143
144 char*
145 3028 prepare(std::size_t n) override
146 {
147 3028 s_.resize(n);
148 3028 return &s_[0];
149 }
150
151 result_type
152 3028 result() noexcept
153 {
154 3028 return std::move(s_);
155 }
156
157 private:
158 result_type s_;
159 };
160 } // implementation_defined
161
162 /** A token for returning a plain string
163 */
164 using return_string = implementation_defined::return_string;
165 #endif
166
167 //------------------------------------------------
168
169 /** A token for appending to a plain string
170 */
171 #ifdef BOOST_URL_DOCS
172 template<
173 class Allocator =
174 std::allocator<char>>
175 __implementation_defined__
176 append_to(
177 std::basic_string<
178 char,
179 std::char_traits<char>,
180 Allocator>& s);
181 #else
182 namespace implementation_defined {
183 template<class Alloc>
184 struct append_to_t
185 : arg
186 {
187 using string_type = std::basic_string<
188 char, std::char_traits<char>,
189 Alloc>;
190
191 using result_type = string_type&;
192
193 explicit
194 3 append_to_t(
195 string_type& s) noexcept
196 3 : s_(s)
197 {
198 3 }
199
200 char*
201 3 prepare(std::size_t n) override
202 {
203 3 std::size_t n0 = s_.size();
204
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if(n > s_.max_size() - n0)
205 urls::detail::throw_length_error();
206 3 s_.resize(n0 + n);
207 3 return &s_[n0];
208 }
209
210 result_type
211 3 result() noexcept
212 {
213 3 return s_;
214 }
215
216 private:
217 string_type& s_;
218 };
219 } // implementation_defined
220
221 /** Create a token for appending to a plain string
222 */
223 template<
224 class Alloc =
225 std::allocator<char>>
226 implementation_defined::append_to_t<Alloc>
227 3 append_to(
228 std::basic_string<
229 char,
230 std::char_traits<char>,
231 Alloc>& s)
232 {
233 3 return implementation_defined::append_to_t<Alloc>(s);
234 }
235 #endif
236
237 //------------------------------------------------
238
239 /** A token for assigning to a plain string
240 */
241 #ifdef BOOST_URL_DOCS
242 template<
243 class Allocator =
244 std::allocator<char>>
245 __implementation_defined__
246 assign_to(
247 std::basic_string<
248 char,
249 std::char_traits<char>,
250 Allocator>& s);
251 #else
252 namespace implementation_defined {
253 template<class Alloc>
254 struct assign_to_t
255 : arg
256 {
257 using string_type = std::basic_string<
258 char, std::char_traits<char>,
259 Alloc>;
260
261 using result_type = string_type&;
262
263 explicit
264 337 assign_to_t(
265 string_type& s) noexcept
266 337 : s_(s)
267 {
268 337 }
269
270 char*
271 337 prepare(std::size_t n) override
272 {
273 337 s_.resize(n);
274 337 return &s_[0];
275 }
276
277 result_type
278 337 result() noexcept
279 {
280 337 return s_;
281 }
282
283 private:
284 string_type& s_;
285 };
286 } // implementation_defined
287
288 /** A token for assigning to a plain string
289 */
290 template<
291 class Alloc =
292 std::allocator<char>>
293 implementation_defined::assign_to_t<Alloc>
294 337 assign_to(
295 std::basic_string<
296 char,
297 std::char_traits<char>,
298 Alloc>& s)
299 {
300 337 return implementation_defined::assign_to_t<Alloc>(s);
301 }
302 #endif
303
304 //------------------------------------------------
305
306 /** A token for producing a durable core::string_view from a temporary string
307 */
308 #ifdef BOOST_URL_DOCS
309 template<
310 class Allocator =
311 std::allocator<char>>
312 __implementation_defined__
313 preserve_size(
314 std::basic_string<
315 char,
316 std::char_traits<char>,
317 Allocator>& s);
318 #else
319 namespace implementation_defined {
320 template<class Alloc>
321 struct preserve_size_t
322 : arg
323 {
324 using result_type = core::string_view;
325
326 using string_type = std::basic_string<
327 char, std::char_traits<char>,
328 Alloc>;
329
330 explicit
331 4 preserve_size_t(
332 string_type& s) noexcept
333 4 : s_(s)
334 {
335 4 }
336
337 char*
338 4 prepare(std::size_t n) override
339 {
340 4 n_ = n;
341 // preserve size() to
342 // avoid value-init
343
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if(s_.size() < n)
344 2 s_.resize(n);
345 4 return &s_[0];
346 }
347
348 result_type
349 4 result() noexcept
350 {
351 4 return core::string_view(
352 8 s_.data(), n_);
353 }
354
355 private:
356 string_type& s_;
357 std::size_t n_ = 0;
358 };
359 } // implementation_defined
360
361 /** A token for producing a durable core::string_view from a temporary string
362 */
363 template<
364 class Alloc =
365 std::allocator<char>>
366 implementation_defined::preserve_size_t<Alloc>
367 4 preserve_size(
368 std::basic_string<
369 char,
370 std::char_traits<char>,
371 Alloc>& s)
372 {
373 4 return implementation_defined::preserve_size_t<Alloc>(s);
374 }
375 #endif
376
377 } // string_token
378
379 namespace grammar {
380 namespace string_token = ::boost::urls::string_token;
381 } // grammar
382
383 } // urls
384 } // boost
385
386 #endif
387