LCOV - code coverage report
Current view: top level - boost/url - format.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 14 14
Test Date: 2026-01-27 15:41:35 Functions: 100.0 % 70 70

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

Generated by: LCOV version 2.3