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
 
102 +
    The formatting machinery relies on language and library
 
103 +
    features that are broken on GCC 4.8 and GCC 5.x, so this
 
104 +
    function is not supported on those compilers.
 
105 +

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

110  

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

117  

113  
    @return A URL holding the formatted result.
118  
    @return A URL holding the formatted result.
114  

119  

115  
    @param fmt The format URL string.
120  
    @param fmt The format URL string.
116  
    @param args Arguments to be formatted.
121  
    @param args Arguments to be formatted.
117  

122  

118  
    @throws system_error
123  
    @throws system_error
119  
    `fmt` contains an invalid format string and
124  
    `fmt` contains an invalid format string and
120  
    the result contains an invalid URL after
125  
    the result contains an invalid URL after
121  
    replacements are applied.
126  
    replacements are applied.
122  

127  

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

138  

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

142  

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

157  

153  
/** Format arguments into a URL
158  
/** Format arguments into a URL
154  

159  

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

162  

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

166  

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

171  

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

179  

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

186  

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

191  

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

198  

194  
    @par Exception Safety
199  
    @par Exception Safety
195  
    Strong guarantee.
200  
    Strong guarantee.
196  

201  

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

205  

201  
    @throws system_error
206  
    @throws system_error
202  
    `fmt` contains an invalid format string and
207  
    `fmt` contains an invalid format string and
203  
    `u` contains an invalid URL after replacements
208  
    `u` contains an invalid URL after replacements
204  
    are applied.
209  
    are applied.
205  

210  

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

221  

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

225  

221  
    @see
226  
    @see
222  
        @ref format.
227  
        @ref format.
223  

228  

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

241  

237  
/** Format arguments into a URL
242  
/** Format arguments into a URL
238  

243  

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

246  

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

250  

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

255  

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

259  

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

264  

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

272  

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

277  

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

282  

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

289  

285  
    @return A URL holding the formatted result.
290  
    @return A URL holding the formatted result.
286  

291  

287  
    @param fmt The format URL string.
292  
    @param fmt The format URL string.
288  
    @param args Arguments to be formatted.
293  
    @param args Arguments to be formatted.
289  

294  

290  
    @throws system_error
295  
    @throws system_error
291  
    `fmt` contains an invalid format string and
296  
    `fmt` contains an invalid format string and
292  
    the result contains an invalid URL after
297  
    the result contains an invalid URL after
293  
    replacements are applied.
298  
    replacements are applied.
294  

299  

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

310  

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

314  

310  
    @see
315  
    @see
311  
        @ref format_to.
316  
        @ref format_to.
312  

317  

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

329  

325  
/** Format arguments into a URL
330  
/** Format arguments into a URL
326  

331  

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

334  

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

338  

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

343  

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

347  

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

352  

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

360  

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

367  

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

372  

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

379  

375  
    @par Exception Safety
380  
    @par Exception Safety
376  
    Strong guarantee.
381  
    Strong guarantee.
377  

382  

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

386  

382  
    @throws system_error
387  
    @throws system_error
383  
    `fmt` contains an invalid format string and
388  
    `fmt` contains an invalid format string and
384  
    `u` contains an invalid URL after replacements
389  
    `u` contains an invalid URL after replacements
385  
    are applied.
390  
    are applied.
386  

391  

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

402  

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

406  

402  
    @see
407  
    @see
403  
        @ref format.
408  
        @ref format.
404  

409  

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

422  

418  
/** Designate a named argument for a replacement field
423  
/** Designate a named argument for a replacement field
419  

424  

420  
    Construct a named argument for a format URL
425  
    Construct a named argument for a format URL
421  
    string that contains named replacement fields.
426  
    string that contains named replacement fields.
422  

427  

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

432  

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

440  

436  
    @return A temporary object with reference
441  
    @return A temporary object with reference
437  
    semantics for a named argument
442  
    semantics for a named argument
438  

443  

439  
    @param name The format argument name
444  
    @param name The format argument name
440  
    @param arg The format argument value
445  
    @param arg The format argument value
441  

446  

442  
    @see
447  
    @see
443  
        @ref format,
448  
        @ref format,
444  
        @ref format_to.
449  
        @ref format_to.
445  

450  

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

458  

454  
} // url
459  
} // url
455  
} // boost
460  
} // boost
456  

461  

457  
#endif
462  
#endif