1  
//
1  
//
2  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
2  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/url
7  
// Official repository: https://github.com/boostorg/url
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_URL_FORMAT_HPP
10  
#ifndef BOOST_URL_FORMAT_HPP
11  
#define BOOST_URL_FORMAT_HPP
11  
#define BOOST_URL_FORMAT_HPP
12  

12  

13  
#include <boost/url/detail/config.hpp>
13  
#include <boost/url/detail/config.hpp>
14  
#include <boost/core/detail/string_view.hpp>
14  
#include <boost/core/detail/string_view.hpp>
15  
#include <boost/url/url.hpp>
15  
#include <boost/url/url.hpp>
16  
#include <boost/url/detail/vformat.hpp>
16  
#include <boost/url/detail/vformat.hpp>
17  
#include <initializer_list>
17  
#include <initializer_list>
18  

18  

19  
#ifdef BOOST_URL_HAS_CONCEPTS
19  
#ifdef BOOST_URL_HAS_CONCEPTS
20  
#include <concepts>
20  
#include <concepts>
21  
#endif
21  
#endif
22  

22  

23  
namespace boost {
23  
namespace boost {
24  
namespace urls {
24  
namespace urls {
25  

25  

26  
/** A temporary reference to a named formatting argument
26  
/** A temporary reference to a named formatting argument
27  

27  

28  
    This class represents a temporary reference
28  
    This class represents a temporary reference
29  
    to a named formatting argument used by the
29  
    to a named formatting argument used by the
30  
    @ref format function.
30  
    @ref format function.
31  

31  

32  
    Named arguments should always be created
32  
    Named arguments should always be created
33  
    with the @ref arg function.
33  
    with the @ref arg function.
34  

34  

35  
    Any type that can be formatted into a URL
35  
    Any type that can be formatted into a URL
36  
    with the @ref format function can also be used
36  
    with the @ref format function can also be used
37  
    in a named argument. All named arguments
37  
    in a named argument. All named arguments
38  
    are convertible to @ref format_arg and
38  
    are convertible to @ref format_arg and
39  
    can be used in the @ref format function.
39  
    can be used in the @ref format function.
40  

40  

41  
    @see
41  
    @see
42  
        @ref arg,
42  
        @ref arg,
43  
        @ref format,
43  
        @ref format,
44  
        @ref format_to,
44  
        @ref format_to,
45  
        @ref format_arg.
45  
        @ref format_arg.
46  
  */
46  
  */
47  
template <class T>
47  
template <class T>
48  
using named_arg = detail::named_arg<T>;
48  
using named_arg = detail::named_arg<T>;
49  

49  

50  
/** A temporary reference to a formatting argument
50  
/** A temporary reference to a formatting argument
51  

51  

52  
    This class represents a temporary reference
52  
    This class represents a temporary reference
53  
    to a formatting argument used by the
53  
    to a formatting argument used by the
54  
    @ref format function.
54  
    @ref format function.
55  

55  

56  
    A @ref format argument should always be
56  
    A @ref format argument should always be
57  
    created by passing the argument to be
57  
    created by passing the argument to be
58  
    formatted directly to the @ref format function.
58  
    formatted directly to the @ref format function.
59  

59  

60  
    Any type that can be formatted into a URL
60  
    Any type that can be formatted into a URL
61  
    with the @ref format function is convertible
61  
    with the @ref format function is convertible
62  
    to this type.
62  
    to this type.
63  

63  

64  
    This includes basic types, types convertible
64  
    This includes basic types, types convertible
65  
    to `core::string_view`, and @ref named_arg.
65  
    to `core::string_view`, and @ref named_arg.
66  

66  

67  
    @see
67  
    @see
68  
        @ref format,
68  
        @ref format,
69  
        @ref format_to,
69  
        @ref format_to,
70  
        @ref arg.
70  
        @ref arg.
71  
  */
71  
  */
72  
using format_arg = detail::format_arg;
72  
using format_arg = detail::format_arg;
73  

73  

74  
/** Format arguments into a URL
74  
/** Format arguments into a URL
75  

75  

76  
    Format arguments according to the format
76  
    Format arguments according to the format
77  
    URL string into a @ref url.
77  
    URL string into a @ref url.
78  

78  

79  
    The rules for a format URL string are the same
79  
    The rules for a format URL string are the same
80  
    as for a `std::format_string`, where replacement
80  
    as for a `std::format_string`, where replacement
81  
    fields are delimited by curly braces.
81  
    fields are delimited by curly braces.
82  

82  

83  
    The URL components to which replacement fields
83  
    The URL components to which replacement fields
84  
    belong are identified before replacement is
84  
    belong are identified before replacement is
85  
    applied and any invalid characters for that
85  
    applied and any invalid characters for that
86  
    formatted argument are percent-escaped.
86  
    formatted argument are percent-escaped.
87  

87  

88  
    Hence, the delimiters between URL components,
88  
    Hence, the delimiters between URL components,
89  
    such as `:`, `//`, `?`, and `#`, should be
89  
    such as `:`, `//`, `?`, and `#`, should be
90  
    included in the URL format string. Likewise,
90  
    included in the URL format string. Likewise,
91  
    a format string with a single `"{}"` is
91  
    a format string with a single `"{}"` is
92  
    interpreted as a path and any replacement
92  
    interpreted as a path and any replacement
93  
    characters invalid in this component will be
93  
    characters invalid in this component will be
94  
    encoded to form a valid URL.
94  
    encoded to form a valid URL.
95  

95  

96  
    @par Example
96  
    @par Example
97  
    @code
97  
    @code
98  
    assert(format("{}", "Hello world!").buffer() == "Hello%20world%21");
98  
    assert(format("{}", "Hello world!").buffer() == "Hello%20world%21");
99  
    @endcode
99  
    @endcode
100  

100  

101  
    @note
101  
    @note
102  
    The formatting machinery relies on language and library
102  
    The formatting machinery relies on language and library
103  
    features that are broken on GCC 4.8 and GCC 5.x, so this
103  
    features that are broken on GCC 4.8 and GCC 5.x, so this
104  
    function is not supported on those compilers.
104  
    function is not supported on those compilers.
105  

105  

106  
    @par Preconditions
106  
    @par Preconditions
107  
    All replacement fields must be valid and the
107  
    All replacement fields must be valid and the
108  
    resulting URL should be valid after arguments
108  
    resulting URL should be valid after arguments
109  
    are formatted into the URL.
109  
    are formatted into the URL.
110  

110  

111  
    Because any invalid characters for a URL
111  
    Because any invalid characters for a URL
112  
    component are encoded by this function, only
112  
    component are encoded by this function, only
113  
    replacements in the scheme and port components
113  
    replacements in the scheme and port components
114  
    might be invalid, as these components do not
114  
    might be invalid, as these components do not
115  
    allow percent-encoding of arbitrary
115  
    allow percent-encoding of arbitrary
116  
    characters.
116  
    characters.
117  

117  

118  
    @return A URL holding the formatted result.
118  
    @return A URL holding the formatted result.
119  

119  

120  
    @param fmt The format URL string.
120  
    @param fmt The format URL string.
121  
    @param args Arguments to be formatted.
121  
    @param args Arguments to be formatted.
122  

122  

123  
    @throws system_error
123  
    @throws system_error
124  
    `fmt` contains an invalid format string and
124  
    `fmt` contains an invalid format string and
125  
    the result contains an invalid URL after
125  
    the result contains an invalid URL after
126  
    replacements are applied.
126  
    replacements are applied.
127  

127  

128  
    @par BNF
128  
    @par BNF
129  
    @code
129  
    @code
130  
    replacement_field ::=  "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
130  
    replacement_field ::=  "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
131  
    arg_id            ::=  integer | identifier
131  
    arg_id            ::=  integer | identifier
132  
    integer           ::=  digit+
132  
    integer           ::=  digit+
133  
    digit             ::=  "0"..."9"
133  
    digit             ::=  "0"..."9"
134  
    identifier        ::=  id_start id_continue*
134  
    identifier        ::=  id_start id_continue*
135  
    id_start          ::=  "a"..."z" | "A"..."Z" | "_"
135  
    id_start          ::=  "a"..."z" | "A"..."Z" | "_"
136  
    id_continue       ::=  id_start | digit
136  
    id_continue       ::=  id_start | digit
137  
    @endcode
137  
    @endcode
138  

138  

139  
    @par Specification
139  
    @par Specification
140  
    @li <a href="https://fmt.dev/latest/syntax.html"
140  
    @li <a href="https://fmt.dev/latest/syntax.html"
141  
        >Format String Syntax</a>
141  
        >Format String Syntax</a>
142  

142  

143  
    @see
143  
    @see
144  
        @ref format_to,
144  
        @ref format_to,
145  
        @ref arg.
145  
        @ref arg.
146  
*/
146  
*/
147  
template <BOOST_URL_CONSTRAINT(std::convertible_to<format_arg>)... Args>
147  
template <BOOST_URL_CONSTRAINT(std::convertible_to<format_arg>)... Args>
148  
url
148  
url
149  
format(
149  
format(
150  
    core::string_view fmt,
150  
    core::string_view fmt,
151  
    Args&&... args)
151  
    Args&&... args)
152  
{
152  
{
153  
    return detail::vformat(
153  
    return detail::vformat(
154  
        fmt, detail::make_format_args(
154  
        fmt, detail::make_format_args(
155  
            std::forward<Args>(args)...));
155  
            std::forward<Args>(args)...));
156  
}
156  
}
157  

157  

158  
/** Format arguments into a URL
158  
/** Format arguments into a URL
159  

159  

160  
    Format arguments according to the format
160  
    Format arguments according to the format
161  
    URL string into a @ref url_base.
161  
    URL string into a @ref url_base.
162  

162  

163  
    The rules for a format URL string are the same
163  
    The rules for a format URL string are the same
164  
    as for a `std::format_string`, where replacement
164  
    as for a `std::format_string`, where replacement
165  
    fields are delimited by curly braces.
165  
    fields are delimited by curly braces.
166  

166  

167  
    The URL components to which replacement fields
167  
    The URL components to which replacement fields
168  
    belong are identified before replacement is
168  
    belong are identified before replacement is
169  
    applied and any invalid characters for that
169  
    applied and any invalid characters for that
170  
    formatted argument are percent-escaped.
170  
    formatted argument are percent-escaped.
171  

171  

172  
    Hence, the delimiters between URL components,
172  
    Hence, the delimiters between URL components,
173  
    such as `:`, `//`, `?`, and `#`, should be
173  
    such as `:`, `//`, `?`, and `#`, should be
174  
    included in the URL format string. Likewise,
174  
    included in the URL format string. Likewise,
175  
    a format string with a single `"{}"` is
175  
    a format string with a single `"{}"` is
176  
    interpreted as a path and any replacement
176  
    interpreted as a path and any replacement
177  
    characters invalid in this component will be
177  
    characters invalid in this component will be
178  
    encoded to form a valid URL.
178  
    encoded to form a valid URL.
179  

179  

180  
    @par Example
180  
    @par Example
181  
    @code
181  
    @code
182  
    static_url<30> u;
182  
    static_url<30> u;
183  
    format(u, "{}", "Hello world!");
183  
    format(u, "{}", "Hello world!");
184  
    assert(u.buffer() == "Hello%20world%21");
184  
    assert(u.buffer() == "Hello%20world%21");
185  
    @endcode
185  
    @endcode
186  

186  

187  
    @par Preconditions
187  
    @par Preconditions
188  
    All replacement fields must be valid and the
188  
    All replacement fields must be valid and the
189  
    resulting URL should be valid after arguments
189  
    resulting URL should be valid after arguments
190  
    are formatted into the URL.
190  
    are formatted into the URL.
191  

191  

192  
    Because any invalid characters for a URL
192  
    Because any invalid characters for a URL
193  
    component are encoded by this function, only
193  
    component are encoded by this function, only
194  
    replacements in the scheme and port components
194  
    replacements in the scheme and port components
195  
    might be invalid, as these components do not
195  
    might be invalid, as these components do not
196  
    allow percent-encoding of arbitrary
196  
    allow percent-encoding of arbitrary
197  
    characters.
197  
    characters.
198  

198  

199  
    @par Exception Safety
199  
    @par Exception Safety
200  
    Strong guarantee.
200  
    Strong guarantee.
201  

201  

202  
    @param u An object that derives from @ref url_base.
202  
    @param u An object that derives from @ref url_base.
203  
    @param fmt The format URL string.
203  
    @param fmt The format URL string.
204  
    @param args Arguments to be formatted.
204  
    @param args Arguments to be formatted.
205  

205  

206  
    @throws system_error
206  
    @throws system_error
207  
    `fmt` contains an invalid format string and
207  
    `fmt` contains an invalid format string and
208  
    `u` contains an invalid URL after replacements
208  
    `u` contains an invalid URL after replacements
209  
    are applied.
209  
    are applied.
210  

210  

211  
    @par BNF
211  
    @par BNF
212  
    @code
212  
    @code
213  
    replacement_field ::=  "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
213  
    replacement_field ::=  "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
214  
    arg_id            ::=  integer | identifier
214  
    arg_id            ::=  integer | identifier
215  
    integer           ::=  digit+
215  
    integer           ::=  digit+
216  
    digit             ::=  "0"..."9"
216  
    digit             ::=  "0"..."9"
217  
    identifier        ::=  id_start id_continue*
217  
    identifier        ::=  id_start id_continue*
218  
    id_start          ::=  "a"..."z" | "A"..."Z" | "_"
218  
    id_start          ::=  "a"..."z" | "A"..."Z" | "_"
219  
    id_continue       ::=  id_start | digit
219  
    id_continue       ::=  id_start | digit
220  
    @endcode
220  
    @endcode
221  

221  

222  
    @par Specification
222  
    @par Specification
223  
    @li <a href="https://fmt.dev/latest/syntax.html"
223  
    @li <a href="https://fmt.dev/latest/syntax.html"
224  
        >Format String Syntax</a>
224  
        >Format String Syntax</a>
225  

225  

226  
    @see
226  
    @see
227  
        @ref format.
227  
        @ref format.
228  

228  

229  
*/
229  
*/
230  
template <BOOST_URL_CONSTRAINT(std::convertible_to<format_arg>)... Args>
230  
template <BOOST_URL_CONSTRAINT(std::convertible_to<format_arg>)... Args>
231  
void
231  
void
232  
format_to(
232  
format_to(
233  
    url_base& u,
233  
    url_base& u,
234  
    core::string_view fmt,
234  
    core::string_view fmt,
235  
    Args&&... args)
235  
    Args&&... args)
236  
{
236  
{
237  
    detail::vformat_to(
237  
    detail::vformat_to(
238  
        u, fmt, detail::make_format_args(
238  
        u, fmt, detail::make_format_args(
239  
            std::forward<Args>(args)...));
239  
            std::forward<Args>(args)...));
240  
}
240  
}
241  

241  

242  
/** Format arguments into a URL
242  
/** Format arguments into a URL
243  

243  

244  
    Format arguments according to the format
244  
    Format arguments according to the format
245  
    URL string into a @ref url.
245  
    URL string into a @ref url.
246  

246  

247  
    This overload allows type-erased arguments
247  
    This overload allows type-erased arguments
248  
    to be passed as an initializer_list, which
248  
    to be passed as an initializer_list, which
249  
    is mostly convenient for named parameters.
249  
    is mostly convenient for named parameters.
250  

250  

251  
    All arguments must be convertible to a
251  
    All arguments must be convertible to a
252  
    implementation defined type able to store a
252  
    implementation defined type able to store a
253  
    type-erased reference to any valid format
253  
    type-erased reference to any valid format
254  
    argument.
254  
    argument.
255  

255  

256  
    The rules for a format URL string are the same
256  
    The rules for a format URL string are the same
257  
    as for a `std::format_string`, where replacement
257  
    as for a `std::format_string`, where replacement
258  
    fields are delimited by curly braces.
258  
    fields are delimited by curly braces.
259  

259  

260  
    The URL components to which replacement fields
260  
    The URL components to which replacement fields
261  
    belong are identified before replacement is
261  
    belong are identified before replacement is
262  
    applied and any invalid characters for that
262  
    applied and any invalid characters for that
263  
    formatted argument are percent-escaped.
263  
    formatted argument are percent-escaped.
264  

264  

265  
    Hence, the delimiters between URL components,
265  
    Hence, the delimiters between URL components,
266  
    such as `:`, `//`, `?`, and `#`, should be
266  
    such as `:`, `//`, `?`, and `#`, should be
267  
    included in the URL format string. Likewise,
267  
    included in the URL format string. Likewise,
268  
    a format string with a single `"{}"` is
268  
    a format string with a single `"{}"` is
269  
    interpreted as a path and any replacement
269  
    interpreted as a path and any replacement
270  
    characters invalid in this component will be
270  
    characters invalid in this component will be
271  
    encoded to form a valid URL.
271  
    encoded to form a valid URL.
272  

272  

273  
    @par Example
273  
    @par Example
274  
    @code
274  
    @code
275  
    assert(format("user/{id}", {{"id", 1}}).buffer() == "user/1");
275  
    assert(format("user/{id}", {{"id", 1}}).buffer() == "user/1");
276  
    @endcode
276  
    @endcode
277  

277  

278  
    @par Preconditions
278  
    @par Preconditions
279  
    All replacement fields must be valid and the
279  
    All replacement fields must be valid and the
280  
    resulting URL should be valid after arguments
280  
    resulting URL should be valid after arguments
281  
    are formatted into the URL.
281  
    are formatted into the URL.
282  

282  

283  
    Because any invalid characters for a URL
283  
    Because any invalid characters for a URL
284  
    component are encoded by this function, only
284  
    component are encoded by this function, only
285  
    replacements in the scheme and port components
285  
    replacements in the scheme and port components
286  
    might be invalid, as these components do not
286  
    might be invalid, as these components do not
287  
    allow percent-encoding of arbitrary
287  
    allow percent-encoding of arbitrary
288  
    characters.
288  
    characters.
289  

289  

290  
    @return A URL holding the formatted result.
290  
    @return A URL holding the formatted result.
291  

291  

292  
    @param fmt The format URL string.
292  
    @param fmt The format URL string.
293  
    @param args Arguments to be formatted.
293  
    @param args Arguments to be formatted.
294  

294  

295  
    @throws system_error
295  
    @throws system_error
296  
    `fmt` contains an invalid format string and
296  
    `fmt` contains an invalid format string and
297  
    the result contains an invalid URL after
297  
    the result contains an invalid URL after
298  
    replacements are applied.
298  
    replacements are applied.
299  

299  

300  
    @par BNF
300  
    @par BNF
301  
    @code
301  
    @code
302  
    replacement_field ::=  "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
302  
    replacement_field ::=  "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
303  
    arg_id            ::=  integer | identifier
303  
    arg_id            ::=  integer | identifier
304  
    integer           ::=  digit+
304  
    integer           ::=  digit+
305  
    digit             ::=  "0"..."9"
305  
    digit             ::=  "0"..."9"
306  
    identifier        ::=  id_start id_continue*
306  
    identifier        ::=  id_start id_continue*
307  
    id_start          ::=  "a"..."z" | "A"..."Z" | "_"
307  
    id_start          ::=  "a"..."z" | "A"..."Z" | "_"
308  
    id_continue       ::=  id_start | digit
308  
    id_continue       ::=  id_start | digit
309  
    @endcode
309  
    @endcode
310  

310  

311  
    @par Specification
311  
    @par Specification
312  
    @li <a href="https://fmt.dev/latest/syntax.html"
312  
    @li <a href="https://fmt.dev/latest/syntax.html"
313  
        >Format String Syntax</a>
313  
        >Format String Syntax</a>
314  

314  

315  
    @see
315  
    @see
316  
        @ref format_to.
316  
        @ref format_to.
317  

317  

318  
*/
318  
*/
319  
inline
319  
inline
320  
url
320  
url
321  
format(
321  
format(
322  
    core::string_view fmt,
322  
    core::string_view fmt,
323  
    std::initializer_list<format_arg> args)
323  
    std::initializer_list<format_arg> args)
324  
{
324  
{
325  
    return detail::vformat(
325  
    return detail::vformat(
326  
        fmt, detail::format_args(
326  
        fmt, detail::format_args(
327  
            args.begin(), args.end()));
327  
            args.begin(), args.end()));
328  
}
328  
}
329  

329  

330  
/** Format arguments into a URL
330  
/** Format arguments into a URL
331  

331  

332  
    Format arguments according to the format
332  
    Format arguments according to the format
333  
    URL string into a @ref url_base.
333  
    URL string into a @ref url_base.
334  

334  

335  
    This overload allows type-erased arguments
335  
    This overload allows type-erased arguments
336  
    to be passed as an initializer_list, which
336  
    to be passed as an initializer_list, which
337  
    is mostly convenient for named parameters.
337  
    is mostly convenient for named parameters.
338  

338  

339  
    All arguments must be convertible to a
339  
    All arguments must be convertible to a
340  
    implementation defined type able to store a
340  
    implementation defined type able to store a
341  
    type-erased reference to any valid format
341  
    type-erased reference to any valid format
342  
    argument.
342  
    argument.
343  

343  

344  
    The rules for a format URL string are the same
344  
    The rules for a format URL string are the same
345  
    as for a `std::format_string`, where replacement
345  
    as for a `std::format_string`, where replacement
346  
    fields are delimited by curly braces.
346  
    fields are delimited by curly braces.
347  

347  

348  
    The URL components to which replacement fields
348  
    The URL components to which replacement fields
349  
    belong are identified before replacement is
349  
    belong are identified before replacement is
350  
    applied and any invalid characters for that
350  
    applied and any invalid characters for that
351  
    formatted argument are percent-escaped.
351  
    formatted argument are percent-escaped.
352  

352  

353  
    Hence, the delimiters between URL components,
353  
    Hence, the delimiters between URL components,
354  
    such as `:`, `//`, `?`, and `#`, should be
354  
    such as `:`, `//`, `?`, and `#`, should be
355  
    included in the URL format string. Likewise,
355  
    included in the URL format string. Likewise,
356  
    a format string with a single `"{}"` is
356  
    a format string with a single `"{}"` is
357  
    interpreted as a path and any replacement
357  
    interpreted as a path and any replacement
358  
    characters invalid in this component will be
358  
    characters invalid in this component will be
359  
    encoded to form a valid URL.
359  
    encoded to form a valid URL.
360  

360  

361  
    @par Example
361  
    @par Example
362  
    @code
362  
    @code
363  
    static_url<30> u;
363  
    static_url<30> u;
364  
    format_to(u, "user/{id}", {{"id", 1}})
364  
    format_to(u, "user/{id}", {{"id", 1}})
365  
    assert(u.buffer() == "user/1");
365  
    assert(u.buffer() == "user/1");
366  
    @endcode
366  
    @endcode
367  

367  

368  
    @par Preconditions
368  
    @par Preconditions
369  
    All replacement fields must be valid and the
369  
    All replacement fields must be valid and the
370  
    resulting URL should be valid after arguments
370  
    resulting URL should be valid after arguments
371  
    are formatted into the URL.
371  
    are formatted into the URL.
372  

372  

373  
    Because any invalid characters for a URL
373  
    Because any invalid characters for a URL
374  
    component are encoded by this function, only
374  
    component are encoded by this function, only
375  
    replacements in the scheme and port components
375  
    replacements in the scheme and port components
376  
    might be invalid, as these components do not
376  
    might be invalid, as these components do not
377  
    allow percent-encoding of arbitrary
377  
    allow percent-encoding of arbitrary
378  
    characters.
378  
    characters.
379  

379  

380  
    @par Exception Safety
380  
    @par Exception Safety
381  
    Strong guarantee.
381  
    Strong guarantee.
382  

382  

383  
    @param u An object that derives from @ref url_base.
383  
    @param u An object that derives from @ref url_base.
384  
    @param fmt The format URL string.
384  
    @param fmt The format URL string.
385  
    @param args Arguments to be formatted.
385  
    @param args Arguments to be formatted.
386  

386  

387  
    @throws system_error
387  
    @throws system_error
388  
    `fmt` contains an invalid format string and
388  
    `fmt` contains an invalid format string and
389  
    `u` contains an invalid URL after replacements
389  
    `u` contains an invalid URL after replacements
390  
    are applied.
390  
    are applied.
391  

391  

392  
    @par BNF
392  
    @par BNF
393  
    @code
393  
    @code
394  
    replacement_field ::=  "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
394  
    replacement_field ::=  "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
395  
    arg_id            ::=  integer | identifier
395  
    arg_id            ::=  integer | identifier
396  
    integer           ::=  digit+
396  
    integer           ::=  digit+
397  
    digit             ::=  "0"..."9"
397  
    digit             ::=  "0"..."9"
398  
    identifier        ::=  id_start id_continue*
398  
    identifier        ::=  id_start id_continue*
399  
    id_start          ::=  "a"..."z" | "A"..."Z" | "_"
399  
    id_start          ::=  "a"..."z" | "A"..."Z" | "_"
400  
    id_continue       ::=  id_start | digit
400  
    id_continue       ::=  id_start | digit
401  
    @endcode
401  
    @endcode
402  

402  

403  
    @par Specification
403  
    @par Specification
404  
    @li <a href="https://fmt.dev/latest/syntax.html"
404  
    @li <a href="https://fmt.dev/latest/syntax.html"
405  
        >Format String Syntax</a>
405  
        >Format String Syntax</a>
406  

406  

407  
    @see
407  
    @see
408  
        @ref format.
408  
        @ref format.
409  

409  

410  
*/
410  
*/
411  
inline
411  
inline
412  
void
412  
void
413  
format_to(
413  
format_to(
414  
    url_base& u,
414  
    url_base& u,
415  
    core::string_view fmt,
415  
    core::string_view fmt,
416  
    std::initializer_list<format_arg> args)
416  
    std::initializer_list<format_arg> args)
417  
{
417  
{
418  
    detail::vformat_to(
418  
    detail::vformat_to(
419  
        u, fmt, detail::format_args(
419  
        u, fmt, detail::format_args(
420  
            args.begin(), args.end()));
420  
            args.begin(), args.end()));
421  
}
421  
}
422  

422  

423  
/** Designate a named argument for a replacement field
423  
/** Designate a named argument for a replacement field
424  

424  

425  
    Construct a named argument for a format URL
425  
    Construct a named argument for a format URL
426  
    string that contains named replacement fields.
426  
    string that contains named replacement fields.
427  

427  

428  
    The function parameters should be convertible
428  
    The function parameters should be convertible
429  
    to an implementation defined type able to
429  
    to an implementation defined type able to
430  
    store the name and a reference to any type
430  
    store the name and a reference to any type
431  
    potentially used as a format argument.
431  
    potentially used as a format argument.
432  

432  

433  
    @par Example
433  
    @par Example
434  
    The function should be used to designate a named
434  
    The function should be used to designate a named
435  
    argument for a replacement field in a format
435  
    argument for a replacement field in a format
436  
    URL string.
436  
    URL string.
437  
    @code
437  
    @code
438  
    assert(format("user/{id}", arg("id", 1)).buffer() == "user/1");
438  
    assert(format("user/{id}", arg("id", 1)).buffer() == "user/1");
439  
    @endcode
439  
    @endcode
440  

440  

441  
    @return A temporary object with reference
441  
    @return A temporary object with reference
442  
    semantics for a named argument
442  
    semantics for a named argument
443  

443  

444  
    @param name The format argument name
444  
    @param name The format argument name
445  
    @param arg The format argument value
445  
    @param arg The format argument value
446  

446  

447  
    @see
447  
    @see
448  
        @ref format,
448  
        @ref format,
449  
        @ref format_to.
449  
        @ref format_to.
450  

450  

451  
*/
451  
*/
452  
template <class T>
452  
template <class T>
453  
named_arg<T>
453  
named_arg<T>
454  
arg(core::string_view name, T const& arg)
454  
arg(core::string_view name, T const& arg)
455  
{
455  
{
456  
    return {name, arg};
456  
    return {name, arg};
457  
}
457  
}
458  

458  

459  
} // url
459  
} // url
460  
} // boost
460  
} // boost
461  

461  

462  
#endif
462  
#endif