GCC Code Coverage Report


Directory: libs/url/
File: boost/url/grammar/string_token.hpp
Date: 2024-03-15 21:27:27
Exec Total Coverage
Lines: 41 42 97.6%
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 // prevent misuse
71 6736 virtual ~arg() = default;
72 3368 arg() = default;
73 arg(arg&&) = default;
74 arg(arg const&) = delete;
75 arg& operator=(arg&&) = delete;
76 arg& operator=(arg const&) = delete;
77 };
78
79 //------------------------------------------------
80
81 /** Metafunction returning true if T is a StringToken
82 */
83 #ifdef BOOST_URL_DOCS
84 template<class T>
85 using is_token = __see_below__;
86 #else
87 template<class T, class = void>
88 struct is_token : std::false_type {};
89
90 template<class T>
91 struct is_token<T, void_t<
92 decltype(std::declval<T&>().prepare(
93 std::declval<std::size_t>())),
94 decltype(std::declval<T&>().result())
95 > > : std::integral_constant<bool,
96 std::is_convertible<decltype(
97 std::declval<T&>().result()),
98 typename T::result_type>::value &&
99 std::is_same<decltype(
100 std::declval<T&>().prepare(0)),
101 char*>::value &&
102 std::is_base_of<arg, T>::value &&
103 std::is_convertible<T const volatile*,
104 arg const volatile*>::value
105 >
106 {
107 };
108 #endif
109
110 //------------------------------------------------
111
112 /** A token for returning a plain string
113 */
114 #ifdef BOOST_URL_DOCS
115 using return_string = __implementation_defined__;
116 #else
117 struct return_string
118 : arg
119 {
120 using result_type = std::string;
121
122 char*
123 3027 prepare(std::size_t n) override
124 {
125 3027 s_.resize(n);
126 3027 return &s_[0];
127 }
128
129 result_type
130 3027 result() noexcept
131 {
132 3027 return std::move(s_);
133 }
134
135 private:
136 result_type s_;
137 };
138 #endif
139
140 //------------------------------------------------
141
142 /** A token for appending to a plain string
143 */
144 #ifdef BOOST_URL_DOCS
145 template<
146 class Allocator =
147 std::allocator<char>>
148 __implementation_defined__
149 append_to(
150 std::basic_string<
151 char,
152 std::char_traits<char>,
153 Allocator>& s);
154 #else
155 template<class Alloc>
156 struct append_to_t
157 : arg
158 {
159 using string_type = std::basic_string<
160 char, std::char_traits<char>,
161 Alloc>;
162
163 using result_type = string_type&;
164
165 explicit
166 2 append_to_t(
167 string_type& s) noexcept
168 2 : s_(s)
169 {
170 2 }
171
172 char*
173 2 prepare(std::size_t n) override
174 {
175 2 std::size_t n0 = s_.size();
176
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if(n > s_.max_size() - n0)
177 urls::detail::throw_length_error();
178 2 s_.resize(n0 + n);
179 2 return &s_[n0];
180 }
181
182 result_type
183 2 result() noexcept
184 {
185 2 return s_;
186 }
187
188 private:
189 string_type& s_;
190 };
191
192 template<
193 class Alloc =
194 std::allocator<char>>
195 append_to_t<Alloc>
196 2 append_to(
197 std::basic_string<
198 char,
199 std::char_traits<char>,
200 Alloc>& s)
201 {
202 2 return append_to_t<Alloc>(s);
203 }
204 #endif
205
206 //------------------------------------------------
207
208 /** A token for assigning to a plain string
209 */
210 #ifdef BOOST_URL_DOCS
211 template<
212 class Allocator =
213 std::allocator<char>>
214 __implementation_defined__
215 assign_to(
216 std::basic_string<
217 char,
218 std::char_traits<char>,
219 Allocator>& s);
220 #else
221 template<class Alloc>
222 struct assign_to_t
223 : arg
224 {
225 using string_type = std::basic_string<
226 char, std::char_traits<char>,
227 Alloc>;
228
229 using result_type = string_type&;
230
231 explicit
232 336 assign_to_t(
233 string_type& s) noexcept
234 336 : s_(s)
235 {
236 336 }
237
238 char*
239 336 prepare(std::size_t n) override
240 {
241 336 s_.resize(n);
242 336 return &s_[0];
243 }
244
245 result_type
246 336 result() noexcept
247 {
248 336 return s_;
249 }
250
251 private:
252 string_type& s_;
253 };
254
255 template<
256 class Alloc =
257 std::allocator<char>>
258 assign_to_t<Alloc>
259 336 assign_to(
260 std::basic_string<
261 char,
262 std::char_traits<char>,
263 Alloc>& s)
264 {
265 336 return assign_to_t<Alloc>(s);
266 }
267 #endif
268
269 //------------------------------------------------
270
271 /** A token for producing a durable core::string_view from a temporary string
272 */
273 #ifdef BOOST_URL_DOCS
274 template<
275 class Allocator =
276 std::allocator<char>>
277 __implementation_defined__
278 preserve_size(
279 std::basic_string<
280 char,
281 std::char_traits<char>,
282 Allocator>& s);
283 #else
284 template<class Alloc>
285 struct preserve_size_t
286 : arg
287 {
288 using result_type = core::string_view;
289
290 using string_type = std::basic_string<
291 char, std::char_traits<char>,
292 Alloc>;
293
294 explicit
295 3 preserve_size_t(
296 string_type& s) noexcept
297 3 : s_(s)
298 {
299 3 }
300
301 char*
302 3 prepare(std::size_t n) override
303 {
304 3 n_ = n;
305 // preserve size() to
306 // avoid value-init
307
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
3 if(s_.size() < n)
308 2 s_.resize(n);
309 3 return &s_[0];
310 }
311
312 result_type
313 3 result() noexcept
314 {
315 return core::string_view(
316 3 s_.data(), n_);
317 }
318
319 private:
320 string_type& s_;
321 std::size_t n_ = 0;
322 };
323
324 template<
325 class Alloc =
326 std::allocator<char>>
327 preserve_size_t<Alloc>
328 3 preserve_size(
329 std::basic_string<
330 char,
331 std::char_traits<char>,
332 Alloc>& s)
333 {
334 3 return preserve_size_t<Alloc>(s);
335 }
336 #endif
337
338 } // string_token
339
340 namespace grammar {
341 namespace string_token = ::boost::urls::string_token;
342 } // grammar
343
344 } // urls
345 } // boost
346
347 #endif
348