// // 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 #include #include #include #include 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 Format String Syntax @see @ref format_to. */ template url format( core::string_view fmt, Args&&... args) { return detail::vformat( fmt, detail::make_format_args( std::forward(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 Format String Syntax @see @ref format. */ template void format_to( url_base& u, core::string_view fmt, Args&&... args) { detail::vformat_to( u, fmt, detail::make_format_args( std::forward(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 Format String Syntax @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 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 Format String Syntax @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 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 #ifdef BOOST_URL_DOCS __implementation_defined__ #else detail::named_arg #endif arg(core::string_view name, T const& arg) { return {name, arg}; } } // url } // boost #endif