LCOV - code coverage report
Current view: top level - boost/url/detail/impl - format_args.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 71 71 100.0 %
Date: 2024-04-08 19:38:36 Functions: 207 207 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_IMPL_FORMAT_ARGS_HPP
      11             : #define BOOST_URL_DETAIL_IMPL_FORMAT_ARGS_HPP
      12             : 
      13             : namespace boost {
      14             : namespace urls {
      15             : namespace detail {
      16             : 
      17             : template<
      18             :     class A,
      19             :     typename std::enable_if<
      20             :         !std::is_integral<
      21             :             typename std::decay<A>::type>::value,
      22             :                 int>::type = 0>
      23             : std::size_t
      24         160 : get_uvalue( A&& )
      25             : {
      26         160 :     return 0;
      27             : }
      28             : 
      29             : template<
      30             :     class A,
      31             :     typename std::enable_if<
      32             :         std::is_integral<
      33             :             typename std::decay<A>::type>::value &&
      34             :         std::is_signed<
      35             :             typename std::decay<A>::type>::value,
      36             :         int>::type = 0>
      37             : std::size_t
      38          47 : get_uvalue( A&& a )
      39             : {
      40          47 :     if (a > 0)
      41          45 :         return static_cast<std::size_t>(a);
      42           2 :     return 0;
      43             : }
      44             : 
      45             : template<
      46             :     class A,
      47             :     typename std::enable_if<
      48             :         std::is_integral<
      49             :             typename std::decay<A>::type>::value &&
      50             :             std::is_unsigned<
      51             :                 typename std::decay<A>::type>::value,
      52             :         int>::type = 0>
      53             : std::size_t
      54          14 : get_uvalue( A&& a )
      55             : {
      56          14 :     return static_cast<std::size_t>(a);
      57             : }
      58             : 
      59             : BOOST_URL_DECL
      60             : std::size_t
      61             : get_uvalue( core::string_view a );
      62             : 
      63             : BOOST_URL_DECL
      64             : std::size_t
      65             : get_uvalue( char a );
      66             : 
      67             : template<class A>
      68         259 : format_arg::
      69             : format_arg( A&& a )
      70             :     : arg_( &a )
      71             :     , measure_( &measure_impl<A> )
      72             :     , fmt_( &format_impl<A> )
      73         259 :     , value_( get_uvalue(std::forward<A>(a) ))
      74         259 :     , ignore_( std::is_same<A, ignore_format>::value )
      75         259 : {}
      76             : 
      77             : template<class A>
      78          19 : format_arg::
      79             : format_arg( named_arg<A>&& a )
      80          19 :     : arg_( &a.value )
      81             :     , measure_( &measure_impl<A> )
      82             :     , fmt_( &format_impl<A> )
      83             :     , name_( a.name )
      84          19 :     , value_( get_uvalue(a.value))
      85          19 : {}
      86             : 
      87             : template<class A>
      88          11 : format_arg::
      89             : format_arg( core::string_view name, A&& a )
      90             :     : arg_( &a )
      91             :     , measure_( &measure_impl<A> )
      92             :     , fmt_( &format_impl<A> )
      93             :     , name_( name )
      94          11 :     , value_( get_uvalue(a) )
      95          11 : {}
      96             : 
      97             : // define the type-erased implementations that
      98             : // depends on everything: the context types,
      99             : // formatters, and type erased args
     100             : template <class A>
     101             : void
     102         240 : format_arg::
     103             : measure_impl(
     104             :     format_parse_context& pctx,
     105             :     measure_context& mctx,
     106             :     grammar::lut_chars const& cs,
     107             :     void const* a )
     108             : {
     109             :     using ref_t = typename std::remove_cv<
     110             :         typename std::remove_reference<A>::type>::type;
     111         240 :     A const& ref = *static_cast<ref_t*>(
     112             :         const_cast<void*>( a ) );
     113         235 :     formatter<ref_t> f;
     114         240 :     pctx.advance_to( f.parse(pctx) );
     115         238 :     mctx.advance_to( f.measure( ref, mctx, cs ) );
     116         238 : }
     117             : 
     118             : template <class A>
     119             : void
     120         236 : format_arg::
     121             : format_impl(
     122             :     format_parse_context& pctx,
     123             :     format_context& fctx,
     124             :     grammar::lut_chars const& cs,
     125             :     void const* a )
     126             : {
     127             :     using ref_t = typename std::remove_cv<
     128             :         typename std::remove_reference<A>::type>::type;
     129         236 :     A const& ref = *static_cast<ref_t*>(
     130             :             const_cast<void*>( a ) );
     131         231 :     formatter<ref_t> f;
     132         236 :     pctx.advance_to( f.parse(pctx) );
     133         236 :     fctx.advance_to( f.format( ref, fctx, cs ) );
     134         236 : }
     135             : 
     136             : // We point to formatter<ignore_format> where
     137             : // the format_arg variant would store monostate
     138             : template <>
     139             : struct formatter<ignore_format>
     140             : {
     141             : public:
     142             :     char const*
     143           6 :     parse(format_parse_context& ctx) const
     144             :     {
     145           6 :         return parse_empty_spec(
     146           6 :             ctx.begin(), ctx.end());
     147             :     }
     148             : 
     149             :     std::size_t
     150           3 :     measure(
     151             :         ignore_format,
     152             :         measure_context& ctx,
     153             :         grammar::lut_chars const&) const
     154             :     {
     155           3 :         return ctx.out();
     156             :     }
     157             : 
     158             :     char*
     159           3 :     format(
     160             :         ignore_format,
     161             :         format_context& ctx,
     162             :         grammar::lut_chars const&) const
     163             :     {
     164           3 :         return ctx.out();
     165             :     }
     166             : 
     167             :     // We ignore the modifiers in all replacements
     168             :     // for now
     169             :     static
     170             :     char const*
     171          10 :     parse_empty_spec(
     172             :         char const* it,
     173             :         char const* end)
     174             :     {
     175             :         // [it, end] -> "} suffix"
     176          10 :         BOOST_ASSERT(it != end);
     177             :         ignore_unused(end);
     178             :         // Should be always empty/valid as an
     179             :         // implementation detail
     180          10 :         BOOST_ASSERT(*it == '}');
     181             :         /*
     182             :         if (*it != '}')
     183             :             urls::detail::throw_invalid_argument();
     184             :         */
     185          10 :         return it;
     186             :     }
     187             : };
     188             : 
     189             : inline
     190             : std::size_t
     191         625 : measure_one(
     192             :     char c,
     193             :     grammar::lut_chars const& unreserved)
     194             : {
     195             :     // '%' must be reserved
     196         625 :     BOOST_ASSERT(! unreserved('%'));
     197         625 :     return 1 + !unreserved(c) * 2;
     198             : }
     199             : 
     200             : inline
     201             : void
     202        1394 : encode_one(
     203             :     char*& out,
     204             :     char c,
     205             :     grammar::lut_chars const& unreserved)
     206             : {
     207             :     // '%' must be reserved
     208        1394 :     BOOST_ASSERT(! unreserved('%'));
     209        1394 :     if(unreserved(c))
     210             :     {
     211        1378 :         *out++ = c;
     212        1378 :         return;
     213             :     }
     214          16 :     *out++ = '%';
     215          16 :     *out++ = urls::detail::hexdigs[0][c>>4];
     216          16 :     *out++ = urls::detail::hexdigs[0][c&0xf];
     217             : }
     218             : 
     219             : // get an unsigned value from format_args
     220             : BOOST_URL_DECL
     221             : void
     222             : get_width_from_args(
     223             :     std::size_t arg_idx,
     224             :     core::string_view arg_name,
     225             :     format_args args,
     226             :     std::size_t& w);
     227             : 
     228             : // formatter for string view
     229             : template <>
     230             : struct formatter<core::string_view>
     231             : {
     232             : private:
     233             :     char fill = ' ';
     234             :     char align = '\0';
     235             :     std::size_t width = 0;
     236             :     std::size_t width_idx = std::size_t(-1);
     237             :     core::string_view width_name;
     238             : 
     239             : public:
     240             :     BOOST_URL_DECL
     241             :     char const*
     242             :     parse(format_parse_context& ctx);
     243             : 
     244             :     BOOST_URL_DECL
     245             :     std::size_t
     246             :     measure(
     247             :         core::string_view str,
     248             :         measure_context& ctx,
     249             :         grammar::lut_chars const& cs) const;
     250             : 
     251             :     BOOST_URL_DECL
     252             :     char*
     253             :     format(
     254             :         core::string_view str,
     255             :         format_context& ctx,
     256             :         grammar::lut_chars const& cs) const;
     257             : };
     258             : 
     259             : // formatter for anything convertible to a
     260             : // string view
     261             : template <class T>
     262             : struct formatter<
     263             :     T, typename std::enable_if<
     264             :         std::is_convertible<
     265             :             T, core::string_view>::value>::type>
     266             : {
     267             :     formatter<core::string_view> impl_;
     268             : 
     269             : public:
     270             :     char const*
     271         240 :     parse(format_parse_context& ctx)
     272             :     {
     273         240 :         return impl_.parse(ctx);
     274             :     }
     275             : 
     276             :     std::size_t
     277         121 :     measure(
     278             :         core::string_view str,
     279             :         measure_context& ctx,
     280             :         grammar::lut_chars const& cs) const
     281             :     {
     282         121 :         return impl_.measure(str, ctx, cs);
     283             :     }
     284             : 
     285             :     char*
     286         119 :     format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const
     287             :     {
     288         119 :         return impl_.format(str, ctx, cs);
     289             :     }
     290             : };
     291             : 
     292             : template <>
     293             : struct formatter<char>
     294             : {
     295             :     formatter<core::string_view> impl_;
     296             : 
     297             : public:
     298             :     char const*
     299         129 :     parse(format_parse_context& ctx)
     300             :     {
     301         129 :         return impl_.parse(ctx);
     302             :     }
     303             : 
     304             :     std::size_t
     305          64 :     measure(
     306             :         char c,
     307             :         measure_context& ctx,
     308             :         grammar::lut_chars const& cs) const
     309             :     {
     310          64 :         return impl_.measure({&c, 1}, ctx, cs);
     311             :     }
     312             : 
     313             :     char*
     314          64 :     format(
     315             :         char c,
     316             :         format_context& ctx,
     317             :         grammar::lut_chars const& cs) const
     318             :     {
     319          64 :         return impl_.format({&c, 1}, ctx, cs);
     320             :     }
     321             : };
     322             : 
     323             : // formatters for a single integer
     324             : class integer_formatter_impl
     325             : {
     326             :     char fill = ' ';
     327             :     char align = '\0';
     328             :     char sign = '-';
     329             :     bool zeros = false;
     330             :     std::size_t width = 0;
     331             :     std::size_t width_idx = std::size_t(-1);
     332             :     core::string_view width_name;
     333             : 
     334             : public:
     335             :     BOOST_URL_DECL
     336             :     char const*
     337             :     parse(format_parse_context& ctx);
     338             : 
     339             :     BOOST_URL_DECL
     340             :     std::size_t
     341             :     measure(
     342             :         unsigned long long int v,
     343             :         measure_context& ctx,
     344             :         grammar::lut_chars const& cs) const;
     345             : 
     346             :     BOOST_URL_DECL
     347             :     std::size_t
     348             :     measure(
     349             :         long long int v,
     350             :         measure_context& ctx,
     351             :         grammar::lut_chars const& cs) const;
     352             : 
     353             :     BOOST_URL_DECL
     354             :     char*
     355             :     format(
     356             :         unsigned long long int v,
     357             :         format_context& ctx,
     358             :         grammar::lut_chars const& cs) const;
     359             : 
     360             :     BOOST_URL_DECL
     361             :     char*
     362             :     format(
     363             :         long long int v,
     364             :         format_context& ctx,
     365             :         grammar::lut_chars const& cs) const;
     366             : };
     367             : 
     368             : template <class T>
     369             : struct formatter<
     370             :     T, typename std::enable_if<
     371             :         mp11::mp_contains<mp11::mp_list<
     372             :             short int,
     373             :             int,
     374             :             long int,
     375             :             long long int,
     376             :             unsigned short int,
     377             :             unsigned int,
     378             :             unsigned long int,
     379             :             unsigned long long int>, T>::value>::type>
     380             : {
     381             : private:
     382             :     integer_formatter_impl impl_;
     383             :     using base_value_type = typename std::conditional<
     384             :         std::is_unsigned<T>::value,
     385             :         unsigned long long int,
     386             :         long long int
     387             :         >::type;
     388             : 
     389             : public:
     390             :     char const*
     391          97 :     parse(format_parse_context& ctx)
     392             :     {
     393          97 :         return impl_.parse(ctx);
     394             :     }
     395             : 
     396             :     std::size_t
     397          48 :     measure(
     398             :         T v,
     399             :         measure_context& ctx,
     400             :         grammar::lut_chars const& cs) const
     401             :     {
     402             :         return impl_.measure(
     403          48 :             static_cast<base_value_type>(v), ctx, cs);
     404             :     }
     405             : 
     406             :     char*
     407          48 :     format(T v, format_context& ctx, grammar::lut_chars const& cs) const
     408             :     {
     409             :         return impl_.format(
     410          48 :             static_cast<base_value_type>(v), ctx, cs);
     411             :     }
     412             : };
     413             : 
     414             : } // detail
     415             : } // url
     416             : } // boost
     417             : 
     418             : #endif

Generated by: LCOV version 1.15