LCOV - code coverage report
Current view: top level - url/detail/impl - format_args.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 83 83
Test Date: 2026-02-25 21:00:01 Functions: 100.0 % 208 208

           TLA  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 HIT         197 : get_uvalue( A&& )
      25                 : {
      26             197 :     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              55 : get_uvalue( A&& a )
      39                 : {
      40              55 :     if (a > 0)
      41              53 :         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             287 : format_arg::
      69                 : format_arg( A&& a )
      70             287 :     : arg_( &a )
      71             287 :     , measure_( &measure_impl<A> )
      72             287 :     , fmt_( &format_impl<A> )
      73             287 :     , value_( get_uvalue(std::forward<A>(a) ))
      74             287 :     , ignore_( std::is_same<A, ignore_format>::value )
      75             287 : {}
      76                 : 
      77                 : template<class A>
      78              21 : format_arg::
      79                 : format_arg( named_arg<A>&& a )
      80              21 :     : arg_( &a.value )
      81              21 :     , measure_( &measure_impl<A> )
      82              21 :     , fmt_( &format_impl<A> )
      83              21 :     , name_( a.name )
      84              21 :     , value_( get_uvalue(a.value))
      85              21 : {}
      86                 : 
      87                 : template<class A>
      88              26 : format_arg::
      89                 : format_arg( core::string_view name, A&& a )
      90              26 :     : arg_( &a )
      91              26 :     , measure_( &measure_impl<A> )
      92              26 :     , fmt_( &format_impl<A> )
      93              26 :     , name_( name )
      94              26 :     , value_( get_uvalue(a) )
      95              26 : {}
      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             286 : 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             286 :     A const& ref = *static_cast<ref_t*>(
     112                 :         const_cast<void*>( a ) );
     113             281 :     formatter<ref_t> f;
     114             286 :     pctx.advance_to( f.parse(pctx) );
     115             284 :     mctx.advance_to( f.measure( ref, mctx, cs ) );
     116             284 : }
     117                 : 
     118                 : template <class A>
     119                 : void
     120             282 : 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             282 :     A const& ref = *static_cast<ref_t*>(
     130                 :             const_cast<void*>( a ) );
     131             277 :     formatter<ref_t> f;
     132             282 :     pctx.advance_to( f.parse(pctx) );
     133             282 :     fctx.advance_to( f.format( ref, fctx, cs ) );
     134             282 : }
     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             728 : measure_one(
     192                 :     char c,
     193                 :     grammar::lut_chars const& unreserved)
     194                 : {
     195                 :     // '%' must be reserved
     196             728 :     BOOST_ASSERT(! unreserved('%'));
     197             728 :     return 1 + !unreserved(c) * 2;
     198                 : }
     199                 : 
     200                 : inline
     201                 : void
     202            1822 : encode_one(
     203                 :     char*& out,
     204                 :     char c,
     205                 :     grammar::lut_chars const& unreserved)
     206                 : {
     207                 :     // '%' must be reserved
     208            1822 :     BOOST_ASSERT(! unreserved('%'));
     209            1822 :     if(unreserved(c))
     210                 :     {
     211            1804 :         *out++ = c;
     212            1804 :         return;
     213                 :     }
     214              18 :     *out++ = '%';
     215              18 :     *out++ = urls::detail::hexdigs[0][c>>4];
     216              18 :     *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             316 :     parse(format_parse_context& ctx)
     272                 :     {
     273             316 :         return impl_.parse(ctx);
     274                 :     }
     275                 : 
     276                 :     std::size_t
     277             159 :     measure(
     278                 :         core::string_view str,
     279                 :         measure_context& ctx,
     280                 :         grammar::lut_chars const& cs) const
     281                 :     {
     282             159 :         return impl_.measure(str, ctx, cs);
     283                 :     }
     284                 : 
     285                 :     char*
     286             157 :     format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const
     287                 :     {
     288             157 :         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             113 :     parse(format_parse_context& ctx)
     392                 :     {
     393             113 :         return impl_.parse(ctx);
     394                 :     }
     395                 : 
     396                 :     std::size_t
     397              56 :     measure(
     398                 :         T v,
     399                 :         measure_context& ctx,
     400                 :         grammar::lut_chars const& cs) const
     401                 :     {
     402              56 :         return impl_.measure(
     403              56 :             static_cast<base_value_type>(v), ctx, cs);
     404                 :     }
     405                 : 
     406                 :     char*
     407              56 :     format(T v, format_context& ctx, grammar::lut_chars const& cs) const
     408                 :     {
     409              56 :         return impl_.format(
     410              56 :             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.3