123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- //
- // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // Official repository: https://github.com/boostorg/url
- //
- #ifndef BOOST_URL_FORMAT_HPP
- #define BOOST_URL_FORMAT_HPP
- #include <boost/url/detail/config.hpp>
- #include <boost/core/detail/string_view.hpp>
- #include <boost/url/url.hpp>
- #include <boost/url/detail/vformat.hpp>
- #include <initializer_list>
- namespace boost {
- namespace urls {
- /** Format arguments into a URL
- Format arguments according to the format
- URL string into a @ref url.
- The rules for a format URL string are the same
- as for a `std::format_string`, where replacement
- fields are delimited by curly braces.
- The URL components to which replacement fields
- belong are identified before replacement is
- applied and any invalid characters for that
- formatted argument are percent-escaped.
- Hence, the delimiters between URL components,
- such as `:`, `//`, `?`, and `#`, should be
- included in the URL format string. Likewise,
- a format string with a single `"{}"` is
- interpreted as a path and any replacement
- characters invalid in this component will be
- encoded to form a valid URL.
- @par Example
- @code
- assert(format("{}", "Hello world!").buffer() == "Hello%20world%21");
- @endcode
- @par Preconditions
- All replacement fields must be valid and the
- resulting URL should be valid after arguments
- are formatted into the URL.
- Because any invalid characters for a URL
- component are encoded by this function, only
- replacements in the scheme and port components
- might be invalid, as these components do not
- allow percent-encoding of arbitrary
- characters.
- @return A URL holding the formatted result.
- @param fmt The format URL string.
- @param args Arguments to be formatted.
- @throws system_error
- `fmt` contains an invalid format string and
- the result contains an invalid URL after
- replacements are applied.
- @par BNF
- @code
- replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
- arg_id ::= integer | identifier
- integer ::= digit+
- digit ::= "0"..."9"
- identifier ::= id_start id_continue*
- id_start ::= "a"..."z" | "A"..."Z" | "_"
- id_continue ::= id_start | digit
- @endcode
- @par Specification
- @li <a href="https://fmt.dev/latest/syntax.html"
- >Format String Syntax</a>
- @see
- @ref format_to.
- */
- template <class... Args>
- url
- format(
- core::string_view fmt,
- Args&&... args)
- {
- return detail::vformat(
- fmt, detail::make_format_args(
- std::forward<Args>(args)...));
- }
- /** Format arguments into a URL
- Format arguments according to the format
- URL string into a @ref url_base.
- The rules for a format URL string are the same
- as for a `std::format_string`, where replacement
- fields are delimited by curly braces.
- The URL components to which replacement fields
- belong are identified before replacement is
- applied and any invalid characters for that
- formatted argument are percent-escaped.
- Hence, the delimiters between URL components,
- such as `:`, `//`, `?`, and `#`, should be
- included in the URL format string. Likewise,
- a format string with a single `"{}"` is
- interpreted as a path and any replacement
- characters invalid in this component will be
- encoded to form a valid URL.
- @par Example
- @code
- static_url<30> u;
- format(u, "{}", "Hello world!");
- assert(u.buffer() == "Hello%20world%21");
- @endcode
- @par Preconditions
- All replacement fields must be valid and the
- resulting URL should be valid after arguments
- are formatted into the URL.
- Because any invalid characters for a URL
- component are encoded by this function, only
- replacements in the scheme and port components
- might be invalid, as these components do not
- allow percent-encoding of arbitrary
- characters.
- @par Exception Safety
- Strong guarantee.
- @param u An object that derives from @ref url_base.
- @param fmt The format URL string.
- @param args Arguments to be formatted.
- @throws system_error
- `fmt` contains an invalid format string and
- `u` contains an invalid URL after replacements
- are applied.
- @par BNF
- @code
- replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
- arg_id ::= integer | identifier
- integer ::= digit+
- digit ::= "0"..."9"
- identifier ::= id_start id_continue*
- id_start ::= "a"..."z" | "A"..."Z" | "_"
- id_continue ::= id_start | digit
- @endcode
- @par Specification
- @li <a href="https://fmt.dev/latest/syntax.html"
- >Format String Syntax</a>
- @see
- @ref format.
- */
- template <class... Args>
- void
- format_to(
- url_base& u,
- core::string_view fmt,
- Args&&... args)
- {
- detail::vformat_to(
- u, fmt, detail::make_format_args(
- std::forward<Args>(args)...));
- }
- /** Format arguments into a URL
- Format arguments according to the format
- URL string into a @ref url.
- This overload allows type-erased arguments
- to be passed as an initializer_list, which
- is mostly convenient for named parameters.
- All arguments must be convertible to a
- implementation defined type able to store a
- type-erased reference to any valid format
- argument.
- The rules for a format URL string are the same
- as for a `std::format_string`, where replacement
- fields are delimited by curly braces.
- The URL components to which replacement fields
- belong are identified before replacement is
- applied and any invalid characters for that
- formatted argument are percent-escaped.
- Hence, the delimiters between URL components,
- such as `:`, `//`, `?`, and `#`, should be
- included in the URL format string. Likewise,
- a format string with a single `"{}"` is
- interpreted as a path and any replacement
- characters invalid in this component will be
- encoded to form a valid URL.
- @par Example
- @code
- assert(format("user/{id}", {{"id", 1}}).buffer() == "user/1");
- @endcode
- @par Preconditions
- All replacement fields must be valid and the
- resulting URL should be valid after arguments
- are formatted into the URL.
- Because any invalid characters for a URL
- component are encoded by this function, only
- replacements in the scheme and port components
- might be invalid, as these components do not
- allow percent-encoding of arbitrary
- characters.
- @return A URL holding the formatted result.
- @param fmt The format URL string.
- @param args Arguments to be formatted.
- @throws system_error
- `fmt` contains an invalid format string and
- the result contains an invalid URL after
- replacements are applied.
- @par BNF
- @code
- replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
- arg_id ::= integer | identifier
- integer ::= digit+
- digit ::= "0"..."9"
- identifier ::= id_start id_continue*
- id_start ::= "a"..."z" | "A"..."Z" | "_"
- id_continue ::= id_start | digit
- @endcode
- @par Specification
- @li <a href="https://fmt.dev/latest/syntax.html"
- >Format String Syntax</a>
- @see
- @ref format_to.
- */
- inline
- url
- format(
- core::string_view fmt,
- #ifdef BOOST_URL_DOCS
- std::initializer_list<__see_below__> args
- #else
- std::initializer_list<detail::format_arg> args
- #endif
- )
- {
- return detail::vformat(
- fmt, detail::format_args(
- args.begin(), args.end()));
- }
- /** Format arguments into a URL
- Format arguments according to the format
- URL string into a @ref url_base.
- This overload allows type-erased arguments
- to be passed as an initializer_list, which
- is mostly convenient for named parameters.
- All arguments must be convertible to a
- implementation defined type able to store a
- type-erased reference to any valid format
- argument.
- The rules for a format URL string are the same
- as for a `std::format_string`, where replacement
- fields are delimited by curly braces.
- The URL components to which replacement fields
- belong are identified before replacement is
- applied and any invalid characters for that
- formatted argument are percent-escaped.
- Hence, the delimiters between URL components,
- such as `:`, `//`, `?`, and `#`, should be
- included in the URL format string. Likewise,
- a format string with a single `"{}"` is
- interpreted as a path and any replacement
- characters invalid in this component will be
- encoded to form a valid URL.
- @par Example
- @code
- static_url<30> u;
- format_to(u, "user/{id}", {{"id", 1}})
- assert(u.buffer() == "user/1");
- @endcode
- @par Preconditions
- All replacement fields must be valid and the
- resulting URL should be valid after arguments
- are formatted into the URL.
- Because any invalid characters for a URL
- component are encoded by this function, only
- replacements in the scheme and port components
- might be invalid, as these components do not
- allow percent-encoding of arbitrary
- characters.
- @par Exception Safety
- Strong guarantee.
- @param u An object that derives from @ref url_base.
- @param fmt The format URL string.
- @param args Arguments to be formatted.
- @throws system_error
- `fmt` contains an invalid format string and
- `u` contains an invalid URL after replacements
- are applied.
- @par BNF
- @code
- replacement_field ::= "{" [arg_id] [":" (format_spec | chrono_format_spec)] "}"
- arg_id ::= integer | identifier
- integer ::= digit+
- digit ::= "0"..."9"
- identifier ::= id_start id_continue*
- id_start ::= "a"..."z" | "A"..."Z" | "_"
- id_continue ::= id_start | digit
- @endcode
- @par Specification
- @li <a href="https://fmt.dev/latest/syntax.html"
- >Format String Syntax</a>
- @see
- @ref format.
- */
- inline
- void
- format_to(
- url_base& u,
- core::string_view fmt,
- #ifdef BOOST_URL_DOCS
- std::initializer_list<__see_below__> args
- #else
- std::initializer_list<detail::format_arg> args
- #endif
- )
- {
- detail::vformat_to(
- u, fmt, detail::format_args(
- args.begin(), args.end()));
- }
- /** Designate a named argument for a replacement field
- Construct a named argument for a format URL
- string that contains named replacement fields.
- The function parameters should be convertible
- to an implementation defined type able to
- store the name and a reference to any type
- potentially used as a format argument.
- @par Example
- @code
- assert(format("user/{id}", arg("id", 1)).buffer() == "user/1");
- @endcode
- @return An temporary object with reference
- semantics for a named argument
- @param name The argument name
- @param arg The argument value
- @see
- @ref format,
- @ref format_to.
- */
- template <class T>
- #ifdef BOOST_URL_DOCS
- __implementation_defined__
- #else
- detail::named_arg<T>
- #endif
- arg(core::string_view name, T const& arg)
- {
- return {name, arg};
- }
- } // url
- } // boost
- #endif
|