GCC Code Coverage Report


Directory: libs/url/
File: include/boost/url/format.hpp
Date: 2025-11-10 19:06:22
Exec Total Coverage
Lines: 14 14 100.0%
Functions: 64 64 100.0%
Branches: 15 22 68.2%

Line Branch Exec Source
1 //
2 // Copyright (c) 2022 Alan de Freitas (alandefreitas@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_FORMAT_HPP
11 #define BOOST_URL_FORMAT_HPP
12
13 #include <boost/url/detail/config.hpp>
14 #include <boost/core/detail/string_view.hpp>
15 #include <boost/url/url.hpp>
16 #include <boost/url/detail/vformat.hpp>
17 #include <initializer_list>
18
19 #ifdef BOOST_URL_HAS_CONCEPTS
20 #include <concepts>
21 #endif
22
23 namespace boost {
24 namespace urls {
25
26 /** A temporary reference to a named formatting argument
27
28 This class represents a temporary reference
29 to a named formatting argument used by the
30 @ref format function.
31
32 Named arguments should always be created
33 with the @ref arg function.
34
35 Any type that can be formatted into a URL
36 with the @ref format function can also be used
37 in a named argument. All named arguments
38 are convertible to @ref format_arg and
39 can be used in the @ref format function.
40
41 @see
42 @ref arg,
43 @ref format,
44 @ref format_to,
45 @ref format_arg.
46 */
47 template <class T>
48 using named_arg = detail::named_arg<T>;
49
50 /** A temporary reference to a formatting argument
51
52 This class represents a temporary reference
53 to a formatting argument used by the
54 @ref format function.
55
56 A @ref format argument should always be
57 created by passing the argument to be
58 formatted directly to the @ref format function.
59
60 Any type that can be formatted into a URL
61 with the @ref format function is convertible
62 to this type.
63
64 This includes basic types, types convertible
65 to `core::string_view`, and @ref named_arg.
66
67 @see
68 @ref format,
69 @ref format_to,
70 @ref arg.
71 */
72 using format_arg = detail::format_arg;
73
74 /** Format arguments into a URL
75
76 Format arguments according to the format
77 URL string into a @ref url.
78
79 The rules for a format URL string are the same
80 as for a `std::format_string`, where replacement
81 fields are delimited by curly braces.
82
83 The URL components to which replacement fields
84 belong are identified before replacement is
85 applied and any invalid characters for that
86 formatted argument are percent-escaped.
87
88 Hence, the delimiters between URL components,
89 such as `:`, `//`, `?`, and `#`, should be
90 included in the URL format string. Likewise,
91 a format string with a single `"{}"` is
92 interpreted as a path and any replacement
93 characters invalid in this component will be
94 encoded to form a valid URL.
95
96 @par Example
97 @code
98 assert(format("{}", "Hello world!").buffer() == "Hello%20world%21");
99 @endcode
100
101 @par Preconditions
102 All replacement fields must be valid and the
103 resulting URL should be valid after arguments
104 are formatted into the URL.
105
106 Because any invalid characters for a URL
107 component are encoded by this function, only
108 replacements in the scheme and port components
109 might be invalid, as these components do not
110 allow percent-encoding of arbitrary
111 characters.
112
113 @return A URL holding the formatted result.
114
115 @param fmt The format URL string.
116 @param args Arguments to be formatted.
117
118 @throws system_error
119 `fmt` contains an invalid format string and
120 the result contains an invalid URL after
121 replacements are applied.
122
123 @par BNF
124 @code
125 replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
126 arg_id ::= integer | identifier
127 integer ::= digit+
128 digit ::= "0"..."9"
129 identifier ::= id_start id_continue*
130 id_start ::= "a"..."z" | "A"..."Z" | "_"
131 id_continue ::= id_start | digit
132 @endcode
133
134 @par Specification
135 @li <a href="https://fmt.dev/latest/syntax.html"
136 >Format String Syntax</a>
137
138 @see
139 @ref format_to,
140 @ref arg.
141 */
142 template <BOOST_URL_CONSTRAINT(std::convertible_to<format_arg>)... Args>
143 url
144 282 format(
145 core::string_view fmt,
146 Args&&... args)
147 {
148 return detail::vformat(
149
7/10
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 9 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 35 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 7 not taken.
302 fmt, detail::make_format_args(
150
2/2
✓ Branch 2 taken 131 times.
✓ Branch 3 taken 10 times.
544 std::forward<Args>(args)...));
151 }
152
153 /** Format arguments into a URL
154
155 Format arguments according to the format
156 URL string into a @ref url_base.
157
158 The rules for a format URL string are the same
159 as for a `std::format_string`, where replacement
160 fields are delimited by curly braces.
161
162 The URL components to which replacement fields
163 belong are identified before replacement is
164 applied and any invalid characters for that
165 formatted argument are percent-escaped.
166
167 Hence, the delimiters between URL components,
168 such as `:`, `//`, `?`, and `#`, should be
169 included in the URL format string. Likewise,
170 a format string with a single `"{}"` is
171 interpreted as a path and any replacement
172 characters invalid in this component will be
173 encoded to form a valid URL.
174
175 @par Example
176 @code
177 static_url<30> u;
178 format(u, "{}", "Hello world!");
179 assert(u.buffer() == "Hello%20world%21");
180 @endcode
181
182 @par Preconditions
183 All replacement fields must be valid and the
184 resulting URL should be valid after arguments
185 are formatted into the URL.
186
187 Because any invalid characters for a URL
188 component are encoded by this function, only
189 replacements in the scheme and port components
190 might be invalid, as these components do not
191 allow percent-encoding of arbitrary
192 characters.
193
194 @par Exception Safety
195 Strong guarantee.
196
197 @param u An object that derives from @ref url_base.
198 @param fmt The format URL string.
199 @param args Arguments to be formatted.
200
201 @throws system_error
202 `fmt` contains an invalid format string and
203 `u` contains an invalid URL after replacements
204 are applied.
205
206 @par BNF
207 @code
208 replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
209 arg_id ::= integer | identifier
210 integer ::= digit+
211 digit ::= "0"..."9"
212 identifier ::= id_start id_continue*
213 id_start ::= "a"..."z" | "A"..."Z" | "_"
214 id_continue ::= id_start | digit
215 @endcode
216
217 @par Specification
218 @li <a href="https://fmt.dev/latest/syntax.html"
219 >Format String Syntax</a>
220
221 @see
222 @ref format.
223
224 */
225 template <BOOST_URL_CONSTRAINT(std::convertible_to<format_arg>)... Args>
226 void
227 3 format_to(
228 url_base& u,
229 core::string_view fmt,
230 Args&&... args)
231 {
232
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
3 detail::vformat_to(
233
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
4 u, fmt, detail::make_format_args(
234 std::forward<Args>(args)...));
235 2 }
236
237 /** Format arguments into a URL
238
239 Format arguments according to the format
240 URL string into a @ref url.
241
242 This overload allows type-erased arguments
243 to be passed as an initializer_list, which
244 is mostly convenient for named parameters.
245
246 All arguments must be convertible to a
247 implementation defined type able to store a
248 type-erased reference to any valid format
249 argument.
250
251 The rules for a format URL string are the same
252 as for a `std::format_string`, where replacement
253 fields are delimited by curly braces.
254
255 The URL components to which replacement fields
256 belong are identified before replacement is
257 applied and any invalid characters for that
258 formatted argument are percent-escaped.
259
260 Hence, the delimiters between URL components,
261 such as `:`, `//`, `?`, and `#`, should be
262 included in the URL format string. Likewise,
263 a format string with a single `"{}"` is
264 interpreted as a path and any replacement
265 characters invalid in this component will be
266 encoded to form a valid URL.
267
268 @par Example
269 @code
270 assert(format("user/{id}", {{"id", 1}}).buffer() == "user/1");
271 @endcode
272
273 @par Preconditions
274 All replacement fields must be valid and the
275 resulting URL should be valid after arguments
276 are formatted into the URL.
277
278 Because any invalid characters for a URL
279 component are encoded by this function, only
280 replacements in the scheme and port components
281 might be invalid, as these components do not
282 allow percent-encoding of arbitrary
283 characters.
284
285 @return A URL holding the formatted result.
286
287 @param fmt The format URL string.
288 @param args Arguments to be formatted.
289
290 @throws system_error
291 `fmt` contains an invalid format string and
292 the result contains an invalid URL after
293 replacements are applied.
294
295 @par BNF
296 @code
297 replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
298 arg_id ::= integer | identifier
299 integer ::= digit+
300 digit ::= "0"..."9"
301 identifier ::= id_start id_continue*
302 id_start ::= "a"..."z" | "A"..."Z" | "_"
303 id_continue ::= id_start | digit
304 @endcode
305
306 @par Specification
307 @li <a href="https://fmt.dev/latest/syntax.html"
308 >Format String Syntax</a>
309
310 @see
311 @ref format_to.
312
313 */
314 inline
315 url
316 2 format(
317 core::string_view fmt,
318 std::initializer_list<format_arg> args)
319 {
320 return detail::vformat(
321 fmt, detail::format_args(
322
1/2
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 args.begin(), args.end()));
323 }
324
325 /** Format arguments into a URL
326
327 Format arguments according to the format
328 URL string into a @ref url_base.
329
330 This overload allows type-erased arguments
331 to be passed as an initializer_list, which
332 is mostly convenient for named parameters.
333
334 All arguments must be convertible to a
335 implementation defined type able to store a
336 type-erased reference to any valid format
337 argument.
338
339 The rules for a format URL string are the same
340 as for a `std::format_string`, where replacement
341 fields are delimited by curly braces.
342
343 The URL components to which replacement fields
344 belong are identified before replacement is
345 applied and any invalid characters for that
346 formatted argument are percent-escaped.
347
348 Hence, the delimiters between URL components,
349 such as `:`, `//`, `?`, and `#`, should be
350 included in the URL format string. Likewise,
351 a format string with a single `"{}"` is
352 interpreted as a path and any replacement
353 characters invalid in this component will be
354 encoded to form a valid URL.
355
356 @par Example
357 @code
358 static_url<30> u;
359 format_to(u, "user/{id}", {{"id", 1}})
360 assert(u.buffer() == "user/1");
361 @endcode
362
363 @par Preconditions
364 All replacement fields must be valid and the
365 resulting URL should be valid after arguments
366 are formatted into the URL.
367
368 Because any invalid characters for a URL
369 component are encoded by this function, only
370 replacements in the scheme and port components
371 might be invalid, as these components do not
372 allow percent-encoding of arbitrary
373 characters.
374
375 @par Exception Safety
376 Strong guarantee.
377
378 @param u An object that derives from @ref url_base.
379 @param fmt The format URL string.
380 @param args Arguments to be formatted.
381
382 @throws system_error
383 `fmt` contains an invalid format string and
384 `u` contains an invalid URL after replacements
385 are applied.
386
387 @par BNF
388 @code
389 replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
390 arg_id ::= integer | identifier
391 integer ::= digit+
392 digit ::= "0"..."9"
393 identifier ::= id_start id_continue*
394 id_start ::= "a"..."z" | "A"..."Z" | "_"
395 id_continue ::= id_start | digit
396 @endcode
397
398 @par Specification
399 @li <a href="https://fmt.dev/latest/syntax.html"
400 >Format String Syntax</a>
401
402 @see
403 @ref format.
404
405 */
406 inline
407 void
408 1 format_to(
409 url_base& u,
410 core::string_view fmt,
411 std::initializer_list<format_arg> args)
412 {
413
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 detail::vformat_to(
414 u, fmt, detail::format_args(
415 args.begin(), args.end()));
416 1 }
417
418 /** Designate a named argument for a replacement field
419
420 Construct a named argument for a format URL
421 string that contains named replacement fields.
422
423 The function parameters should be convertible
424 to an implementation defined type able to
425 store the name and a reference to any type
426 potentially used as a format argument.
427
428 @par Example
429 The function should be used to designate a named
430 argument for a replacement field in a format
431 URL string.
432 @code
433 assert(format("user/{id}", arg("id", 1)).buffer() == "user/1");
434 @endcode
435
436 @return A temporary object with reference
437 semantics for a named argument
438
439 @param name The format argument name
440 @param arg The format argument value
441
442 @see
443 @ref format,
444 @ref format_to.
445
446 */
447 template <class T>
448 named_arg<T>
449 19 arg(core::string_view name, T const& arg)
450 {
451 19 return {name, arg};
452 }
453
454 } // url
455 } // boost
456
457 #endif
458