LCOV - code coverage report
Current view: top level - boost/url/detail/impl/format_args.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 83 83
Test Date: 2024-08-19 20:08:54 Functions: 100.0 % 207 207

            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          259 :     : arg_( &a )
      71          259 :     , measure_( &measure_impl<A> )
      72          259 :     , 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           19 :     , measure_( &measure_impl<A> )
      82           19 :     , fmt_( &format_impl<A> )
      83           19 :     , 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           11 :     : arg_( &a )
      91           11 :     , measure_( &measure_impl<A> )
      92           11 :     , fmt_( &format_impl<A> )
      93           11 :     , 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           48 :         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           48 :         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 2.1