LCOV - code coverage report
Current view: top level - boost/url/grammar/string_token.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 97.7 % 43 42
Test Date: 2025-11-10 19:06:20 Functions: 94.1 % 17 16

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_STRING_TOKEN_HPP
      11              : #define BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
      12              : 
      13              : #include <boost/url/detail/config.hpp>
      14              : #include <boost/core/detail/string_view.hpp>
      15              : #include <boost/url/detail/except.hpp>
      16              : #include <memory>
      17              : #include <string>
      18              : 
      19              : namespace boost {
      20              : namespace urls {
      21              : namespace string_token {
      22              : 
      23              : /** Base class for string tokens, and algorithm parameters
      24              : 
      25              :     This abstract interface provides a means
      26              :     for an algorithm to generically obtain a
      27              :     modifiable, contiguous character buffer
      28              :     of prescribed size.
      29              : 
      30              :     A @ref StringToken should be derived
      31              :     from this class. As the author of an
      32              :     algorithm using a @ref StringToken,
      33              :     simply declare an rvalue reference
      34              :     as a parameter type.
      35              : 
      36              :     Instances of this type are intended only
      37              :     to be used once and then destroyed.
      38              : 
      39              :     @par Example
      40              :     The declared function accepts any
      41              :     temporary instance of `arg` to be
      42              :     used for writing:
      43              :     @code
      44              :     void algorithm( string_token::arg&& dest );
      45              :     @endcode
      46              : 
      47              :     To implement the interface for your type
      48              :     or use-case, derive from the class and
      49              :     implement the prepare function.
      50              : */
      51              : struct arg
      52              : {
      53              :     /** Return a modifiable character buffer
      54              : 
      55              :         This function attempts to obtain a
      56              :         character buffer with space for at
      57              :         least `n` characters. Upon success,
      58              :         a pointer to the beginning of the
      59              :         buffer is returned. Ownership is not
      60              :         transferred; the caller should not
      61              :         attempt to free the storage. The
      62              :         buffer shall remain valid until
      63              :         `this` is destroyed.
      64              : 
      65              :         @note
      66              :         This function may only be called once.
      67              :         After invoking the function, the only
      68              :         valid operation is destruction.
      69              : 
      70              :         @param n The number of characters needed
      71              :         @return A pointer to the buffer
      72              :     */
      73              :     virtual char* prepare(std::size_t n) = 0;
      74              : 
      75              :     /// Virtual destructor
      76         3430 :     virtual ~arg() = default;
      77              : 
      78              :     /// Default constructor
      79         3430 :     arg() = default;
      80              : 
      81              :     /// Default move constructor
      82              :     arg(arg&&) = default;
      83              : 
      84              :     /// Deleted copy constructor
      85              :     arg(arg const&) = delete;
      86              : 
      87              :     /// Deleted move assignment
      88              :     arg& operator=(arg&&) = delete;
      89              : 
      90              :     /// Deleted copy assignment
      91              :     arg& operator=(arg const&) = delete;
      92              : };
      93              : 
      94              : //------------------------------------------------
      95              : 
      96              : namespace implementation_defined {
      97              : template<class T, class = void>
      98              : struct is_token : std::false_type {};
      99              : 
     100              : template<class T>
     101              : struct is_token<T, void_t<
     102              :     decltype(std::declval<T&>().prepare(
     103              :         std::declval<std::size_t>())),
     104              :     decltype(std::declval<T&>().result())
     105              :     > > : std::integral_constant<bool,
     106              :         std::is_convertible<decltype(
     107              :             std::declval<T&>().result()),
     108              :             typename T::result_type>::value &&
     109              :         std::is_same<decltype(
     110              :             std::declval<T&>().prepare(0)),
     111              :             char*>::value &&
     112              :         std::is_base_of<arg, T>::value &&
     113              :         std::is_convertible<T const volatile*,
     114              :             arg const volatile*>::value
     115              :     >
     116              : {
     117              : };
     118              : } // implementation_defined
     119              : 
     120              : /** Trait to determine if a type is a string token
     121              : 
     122              :     This trait returns `true` if `T` is a valid
     123              :     @ref StringToken type, and `false` otherwise.
     124              : 
     125              :     @par Example
     126              :     @code
     127              :     static_assert( string_token::is_token<T>::value );
     128              :     @endcode
     129              :  */
     130              : template<class T>
     131              : using is_token = implementation_defined::is_token<T>;
     132              : 
     133              : #ifdef BOOST_URL_HAS_CONCEPTS
     134              : /** Concept for a string token
     135              : 
     136              :     This concept is satisfied if `T` is a
     137              :     valid string token type.
     138              : 
     139              :     A string token is an rvalue passed to a function template
     140              :     which customizes the return type of the function and also
     141              :     controls how a modifiable character buffer is obtained and presented.
     142              : 
     143              :     The string token's lifetime extends only for the duration of the
     144              :     function call in which it appears as a parameter.
     145              : 
     146              :     A string token cannot be copied, moved, or assigned, and must be
     147              :     destroyed when the function returns or throws.
     148              : 
     149              :     @par Semantics
     150              : 
     151              :     `T::result_type` determines the return type of functions
     152              :     that accept a string token.
     153              : 
     154              :     The `prepare()` function overrides the virtual function
     155              :     in the base class @ref arg. It must return a pointer to
     156              :     a character buffer of at least size `n`, otherwise
     157              :     throw an exception. This function is called only
     158              :     once or not at all.
     159              : 
     160              :     The `result()` function is invoked by the algorithm
     161              :     to receive the result from the string token.
     162              :     It is only invoked if `prepare()` returned
     163              :     successfully and the string token was not destroyed.
     164              :     It is only called after `prepare()` returns
     165              :     successfully, and the string token is destroyed
     166              :     when the algorithm completes or if an exception
     167              :     is thrown.
     168              : 
     169              :     String tokens cannot be reused.
     170              : 
     171              :     @par Exemplars
     172              :     String token prototype:
     173              : 
     174              :     @code
     175              :     struct StringToken : string_token::arg
     176              :     {
     177              :         using result_type = std::string;
     178              : 
     179              :         char* prepare( std::size_t n ) override;
     180              : 
     181              :         result_type result();
     182              :     };
     183              :     @endcode
     184              : 
     185              :     Algorithm prototype:
     186              : 
     187              :     @code
     188              :     namespace detail {
     189              : 
     190              :     // Algorithm implementation may be placed
     191              :     // out of line, and written as an ordinary
     192              :     // function (no template required).
     193              :     void algorithm_impl( string_token::arg& token )
     194              :     {
     195              :         std::size_t n = 0;
     196              : 
     197              :         // calculate space needed in n
     198              :         // ...
     199              : 
     200              :         // acquire a destination buffer
     201              :         char* dest = token.prepare( n );
     202              : 
     203              :         // write the characters to the buffer
     204              :     }
     205              :     } // detail
     206              : 
     207              :     // public interface is a function template,
     208              :     // defaulting to return std::string.
     209              :     template< class StringToken = string_token::return_string >
     210              :     auto
     211              :     algorithm( StringToken&& token = {} ) ->
     212              :         typename StringToken::result_type
     213              :     {
     214              :         // invoke the algorithm with the token
     215              :         algorithm_impl( token );
     216              : 
     217              :         // return the result from the token
     218              :         return token.result();
     219              :     }
     220              :     @endcode
     221              : 
     222              :     @par Models
     223              :     The following classes and functions implement and
     224              :     generate string tokens.
     225              : 
     226              :     @li @ref return_string
     227              :     @li @ref assign_to
     228              :     @li @ref preserve_size
     229              : 
     230              :  */
     231              : template <class T>
     232              : concept StringToken =
     233              :     std::derived_from<T, string_token::arg> &&
     234              :     requires (T t, std::size_t n)
     235              : {
     236              :     typename T::result_type;
     237              :     { t.prepare(n) } -> std::same_as<char*>;
     238              :     { t.result() } -> std::convertible_to<typename T::result_type>;
     239              : };
     240              : #endif
     241              : 
     242              : //------------------------------------------------
     243              : 
     244              : namespace implementation_defined {
     245              : struct return_string
     246              :     : arg
     247              : {
     248              :     using result_type = std::string;
     249              : 
     250              :     char*
     251         3086 :     prepare(std::size_t n) override
     252              :     {
     253         3086 :         s_.resize(n);
     254         3086 :         return &s_[0];
     255              :     }
     256              : 
     257              :     result_type
     258         3086 :     result() noexcept
     259              :     {
     260         3086 :         return std::move(s_);
     261              :     }
     262              : 
     263              : private:
     264              :     result_type s_;
     265              : };
     266              : } // implementation_defined
     267              : 
     268              : /** A string token for returning a plain string
     269              : 
     270              :     This @ref StringToken is used to customize
     271              :     a function to return a plain string.
     272              : 
     273              :     This is default token type used by
     274              :     the methods of @ref url_view_base
     275              :     that return decoded strings.
     276              :  */
     277              : using return_string = implementation_defined::return_string;
     278              : 
     279              : //------------------------------------------------
     280              : 
     281              : namespace implementation_defined {
     282              : template<class Alloc>
     283              : struct append_to_t
     284              :     : arg
     285              : {
     286              :     using string_type = std::basic_string<
     287              :         char, std::char_traits<char>,
     288              :             Alloc>;
     289              : 
     290              :     using result_type = string_type&;
     291              : 
     292              :     explicit
     293            3 :     append_to_t(
     294              :         string_type& s) noexcept
     295            3 :         : s_(s)
     296              :     {
     297            3 :     }
     298              : 
     299              :     char*
     300            3 :     prepare(std::size_t n) override
     301              :     {
     302            3 :         std::size_t n0 = s_.size();
     303            3 :         if(n > s_.max_size() - n0)
     304            0 :             urls::detail::throw_length_error();
     305            3 :         s_.resize(n0 + n);
     306            3 :         return &s_[n0];
     307              :     }
     308              : 
     309              :     result_type
     310            3 :     result() noexcept
     311              :     {
     312            3 :         return s_;
     313              :     }
     314              : 
     315              : private:
     316              :     string_type& s_;
     317              : };
     318              : } // implementation_defined
     319              : 
     320              : /** Create a string token for appending to a plain string
     321              : 
     322              :     This function creates a @ref StringToken
     323              :     which appends to an existing plain string.
     324              : 
     325              :     Functions using this token will append
     326              :     the result to the existing string and
     327              :     return a reference to it.
     328              : 
     329              :     @param s The string to append
     330              :     @return A string token
     331              :  */
     332              : template<
     333              :     class Alloc =
     334              :         std::allocator<char>>
     335              : implementation_defined::append_to_t<Alloc>
     336            3 : append_to(
     337              :     std::basic_string<
     338              :         char,
     339              :         std::char_traits<char>,
     340              :         Alloc>& s)
     341              : {
     342            3 :     return implementation_defined::append_to_t<Alloc>(s);
     343              : }
     344              : 
     345              : //------------------------------------------------
     346              : 
     347              : namespace implementation_defined {
     348              : template<class Alloc>
     349              : struct assign_to_t
     350              :     : arg
     351              : {
     352              :     using string_type = std::basic_string<
     353              :         char, std::char_traits<char>,
     354              :             Alloc>;
     355              : 
     356              :     using result_type = string_type&;
     357              : 
     358              :     explicit
     359          337 :     assign_to_t(
     360              :         string_type& s) noexcept
     361          337 :         : s_(s)
     362              :     {
     363          337 :     }
     364              : 
     365              :     char*
     366          337 :     prepare(std::size_t n) override
     367              :     {
     368          337 :         s_.resize(n);
     369          337 :         return &s_[0];
     370              :     }
     371              : 
     372              :     result_type
     373          337 :     result() noexcept
     374              :     {
     375          337 :         return s_;
     376              :     }
     377              : 
     378              : private:
     379              :     string_type& s_;
     380              : };
     381              : } // implementation_defined
     382              : 
     383              : /** Create a string token for assigning to a plain string
     384              : 
     385              :     This function creates a @ref StringToken
     386              :     which assigns to an existing plain string.
     387              : 
     388              :     Functions using this token will assign
     389              :     the result to the existing string and
     390              :     return a reference to it.
     391              : 
     392              :     @param s The string to assign
     393              :     @return A string token
     394              :  */
     395              : template<
     396              :     class Alloc =
     397              :         std::allocator<char>>
     398              : implementation_defined::assign_to_t<Alloc>
     399          337 : assign_to(
     400              :     std::basic_string<
     401              :         char,
     402              :         std::char_traits<char>,
     403              :         Alloc>& s)
     404              : {
     405          337 :     return implementation_defined::assign_to_t<Alloc>(s);
     406              : }
     407              : 
     408              : //------------------------------------------------
     409              : 
     410              : namespace implementation_defined {
     411              : template<class Alloc>
     412              : struct preserve_size_t
     413              :     : arg
     414              : {
     415              :     using result_type = core::string_view;
     416              : 
     417              :     using string_type = std::basic_string<
     418              :         char, std::char_traits<char>,
     419              :             Alloc>;
     420              : 
     421              :     explicit
     422            4 :     preserve_size_t(
     423              :         string_type& s) noexcept
     424            4 :         : s_(s)
     425              :     {
     426            4 :     }
     427              : 
     428              :     char*
     429            4 :     prepare(std::size_t n) override
     430              :     {
     431            4 :         n_ = n;
     432              :         // preserve size() to
     433              :         // avoid value-init
     434            4 :         if(s_.size() < n)
     435            2 :             s_.resize(n);
     436            4 :         return &s_[0];
     437              :     }
     438              : 
     439              :     result_type
     440            4 :     result() noexcept
     441              :     {
     442            4 :         return core::string_view(
     443            8 :             s_.data(), n_);
     444              :     }
     445              : 
     446              : private:
     447              :     string_type& s_;
     448              :     std::size_t n_ = 0;
     449              : };
     450              : } // implementation_defined
     451              : 
     452              : /** Create a string token for a durable core::string_view
     453              : 
     454              :     This function creates a @ref StringToken
     455              :     which assigns to an existing plain string.
     456              : 
     457              :     Functions using this token will assign
     458              :     the result to the existing string and
     459              :     return a `core::string_view` to it.
     460              : 
     461              :     @param s The string to preserve
     462              :     @return A string token
     463              :  */
     464              : template<
     465              :     class Alloc =
     466              :         std::allocator<char>>
     467              : implementation_defined::preserve_size_t<Alloc>
     468            4 : preserve_size(
     469              :     std::basic_string<
     470              :         char,
     471              :         std::char_traits<char>,
     472              :         Alloc>& s)
     473              : {
     474            4 :     return implementation_defined::preserve_size_t<Alloc>(s);
     475              : }
     476              : } // string_token
     477              : 
     478              : namespace grammar {
     479              : namespace string_token = ::boost::urls::string_token;
     480              : } // grammar
     481              : 
     482              : } // urls
     483              : } // boost
     484              : 
     485              : #endif
        

Generated by: LCOV version 2.1