LCOV - code coverage report
Current view: top level - boost/url/detail - format_args.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 85 85 100.0 %
Date: 2023-12-15 15:31:48 Functions: 102 102 100.0 %

          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_DETAIL_FORMAT_ARGS_HPP
      11             : #define BOOST_URL_DETAIL_FORMAT_ARGS_HPP
      12             : 
      13             : #include <boost/url/detail/encode.hpp>
      14             : #include <boost/url/grammar/lut_chars.hpp>
      15             : 
      16             : #include <boost/core/ignore_unused.hpp>
      17             : #include <array>
      18             : 
      19             : // This file implements functions and classes to
      20             : // type-erase format arguments.
      21             : 
      22             : namespace boost {
      23             : namespace urls {
      24             : namespace detail {
      25             : 
      26             : // state of the format string. It basically keeps
      27             : // track of where we are in the format string.
      28             : class format_parse_context
      29             : {
      30             :     char const* begin_;
      31             :     char const* end_;
      32             :     std::size_t arg_id_ = 0;
      33             : 
      34             : public:
      35             :     constexpr
      36         632 :     format_parse_context(
      37             :         char const* first,
      38             :         char const* last,
      39             :         std::size_t arg_id = 0)
      40         632 :         : begin_( first )
      41             :         , end_( last )
      42         632 :         , arg_id_( arg_id )
      43         632 :     {}
      44             : 
      45             :     constexpr
      46         495 :     format_parse_context(
      47             :         core::string_view fmt,
      48             :         std::size_t arg_id = 0)
      49         495 :         : format_parse_context(
      50             :             fmt.data(),
      51         495 :             fmt.data() + fmt.size(),
      52         495 :             arg_id )
      53         495 :     {}
      54             : 
      55             :     constexpr
      56             :     char const*
      57        1445 :     begin() const noexcept
      58             :     {
      59        1445 :         return begin_;
      60             :     }
      61             : 
      62             :     constexpr
      63             :     char const*
      64         971 :     end() const noexcept
      65             :     {
      66         971 :         return end_;
      67             :     }
      68             : 
      69             :     BOOST_CXX14_CONSTEXPR
      70             :     void
      71         950 :     advance_to( char const* it )
      72             :     {
      73         950 :         begin_ = it;
      74         950 :     }
      75             : 
      76             :     std::size_t
      77         871 :     next_arg_id()
      78             :     {
      79         871 :         return arg_id_++;
      80             :     }
      81             : };
      82             : 
      83             : // State of the destination string
      84             : class format_context;
      85             : class measure_context;
      86             : struct ignore_format {};
      87             : 
      88             : template <class T>
      89             : struct named_arg
      90             : {
      91             :     core::string_view name;
      92             :     T const& value;
      93             : 
      94          19 :     named_arg(core::string_view n, T const& v)
      95             :         : name(n)
      96          19 :         , value(v)
      97          19 :     {}
      98             : };
      99             : 
     100             : // A type erased format argument
     101             : class format_arg
     102             : {
     103             :     void const* arg_;
     104             :     void (*measure_)(
     105             :         format_parse_context&,
     106             :         measure_context&,
     107             :         grammar::lut_chars const&,
     108             :         void const* );
     109             :     void (*fmt_)(
     110             :         format_parse_context&,
     111             :         format_context&,
     112             :         grammar::lut_chars const&,
     113             :         void const* );
     114             :     core::string_view name_;
     115             :     std::size_t value_ = 0;
     116             :     bool ignore_ = false;
     117             : 
     118             :     template <class A>
     119             :     static
     120             :     void
     121             :     measure_impl(
     122             :         format_parse_context& pctx,
     123             :         measure_context& mctx,
     124             :         grammar::lut_chars const& cs,
     125             :         void const* a );
     126             : 
     127             :     template <class A>
     128             :     static
     129             :     void
     130             :     format_impl(
     131             :         format_parse_context& pctx,
     132             :         format_context& fctx,
     133             :         grammar::lut_chars const& cs,
     134             :         void const* a );
     135             : 
     136             : public:
     137             :     template<class A>
     138             :     format_arg( A&& a );
     139             : 
     140             :     template<class A>
     141             :     format_arg( named_arg<A>&& a );
     142             : 
     143             :     template<class A>
     144             :     format_arg( core::string_view name, A&& a );
     145             : 
     146          34 :     format_arg()
     147          34 :         : format_arg(ignore_format{})
     148          34 :     {}
     149             : 
     150             :     explicit
     151             :     operator bool() const noexcept
     152             :     {
     153             :         return !ignore_;
     154             :     }
     155             : 
     156             :     void
     157         240 :     measure(
     158             :         format_parse_context& pctx,
     159             :         measure_context& mctx,
     160             :         grammar::lut_chars const& cs)
     161             :     {
     162         240 :         measure_( pctx, mctx, cs, arg_ );
     163         238 :     }
     164             : 
     165             :     void
     166         236 :     format(
     167             :         format_parse_context& pctx,
     168             :         format_context& fctx,
     169             :         grammar::lut_chars const& cs )
     170             :     {
     171         236 :         fmt_( pctx, fctx, cs, arg_ );
     172         236 :     }
     173             : 
     174             :     core::string_view
     175         130 :     name() const
     176             :     {
     177         130 :         return name_;
     178             :     }
     179             : 
     180             :     std::size_t
     181          28 :     value() const
     182             :     {
     183          28 :         return value_;
     184             :     }
     185             : };
     186             : 
     187             : // create temp stack storage for type erased args
     188             : template< class... Args >
     189             : std::array<format_arg, sizeof...(Args)>
     190         144 : make_format_args( Args&&... args )
     191             : {
     192         144 :     return {{ std::forward<Args>(args)... }};
     193             : }
     194             : 
     195             : // reference to an array of format_args
     196             : class format_args
     197             : {
     198             :     format_arg const* p_{nullptr};
     199             :     std::size_t n_{0};
     200             : 
     201             : public:
     202           3 :     format_args(
     203             :         detail::format_arg const* first,
     204             :         detail::format_arg const* last ) noexcept
     205           3 :         : p_(first)
     206           3 :         , n_(static_cast<std::size_t>(last - first))
     207           3 :     {}
     208             : 
     209             :     template < std::size_t N >
     210         144 :     format_args( std::array<format_arg, N> const& store ) noexcept
     211             :         : p_(store.data())
     212         144 :         , n_(store.size())
     213         144 :     {}
     214             : 
     215             :     format_arg
     216         442 :     get( std::size_t i ) const noexcept
     217             :     {
     218         442 :         if (i < n_)
     219         438 :             return p_[i];
     220           4 :         return {};
     221             :     }
     222             : 
     223             :     format_arg
     224          62 :     get( core::string_view name ) const noexcept
     225             :     {
     226         132 :         for (std::size_t i = 0; i < n_; ++i)
     227             :         {
     228         130 :             if (p_[i].name() == name)
     229          60 :                 return p_[i];
     230             :         }
     231           2 :         return {};
     232             :     }
     233             : };
     234             : 
     235             : // define the format_context after format_args
     236             : class format_context
     237             : {
     238             :     format_args args_;
     239             :     char* out_;
     240             : 
     241             : public:
     242         137 :     format_context(
     243             :         char* out,
     244             :         format_args args )
     245         137 :         : args_( args )
     246         137 :         , out_( out )
     247         137 :     {}
     248             : 
     249             :     format_args
     250          14 :     args() const noexcept
     251             :     {
     252          14 :         return args_;
     253             :     }
     254             : 
     255             :     format_arg
     256         210 :     arg( std::size_t id ) const noexcept
     257             :     {
     258         210 :         return args_.get( id );
     259             :     }
     260             : 
     261             :     format_arg
     262          26 :     arg( core::string_view name ) const noexcept
     263             :     {
     264          26 :         return args_.get( name );
     265             :     }
     266             : 
     267             :     char*
     268         939 :     out()
     269             :     {
     270         939 :         return out_;
     271             :     }
     272             : 
     273             :     void
     274         939 :     advance_to( char* it )
     275             :     {
     276         939 :         out_ = it;
     277         939 :     }
     278             : };
     279             : 
     280             : // define the measure_context after format_args
     281             : class measure_context
     282             : {
     283             :     format_args args_;
     284             :     std::size_t out_;
     285             : 
     286             : public:
     287         140 :     measure_context(
     288             :         format_args args )
     289         140 :         : measure_context(0, args)
     290         140 :     {}
     291             : 
     292         140 :     measure_context(
     293             :         std::size_t out,
     294             :         format_args args )
     295         140 :         : args_( args )
     296         140 :         , out_( out )
     297         140 :     {}
     298             : 
     299             :     format_args
     300          14 :     args() const noexcept
     301             :     {
     302          14 :         return args_;
     303             :     }
     304             : 
     305             :     format_arg
     306         214 :     arg( std::size_t id ) const noexcept
     307             :     {
     308         214 :         return args_.get( id );
     309             :     }
     310             : 
     311             :     format_arg
     312          26 :     arg( core::string_view name ) const noexcept
     313             :     {
     314          26 :         return args_.get( name );
     315             :     }
     316             : 
     317             :     std::size_t
     318         953 :     out()
     319             :     {
     320         953 :         return out_;
     321             :     }
     322             : 
     323             :     void
     324         953 :     advance_to( std::size_t n )
     325             :     {
     326         953 :         out_ = n;
     327         953 :     }
     328             : };
     329             : 
     330             : // fwd declare the formatter
     331             : template <class T, class = void>
     332             : struct formatter;
     333             : 
     334             : } // detail
     335             : } // url
     336             : } // boost
     337             : 
     338             : #include <boost/url/detail/impl/format_args.hpp>
     339             : 
     340             : #endif

Generated by: LCOV version 1.15