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 % 84 84
Test Date: 2026-03-02 22:26:03 Functions: 100.0 % 212 212

           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         200 : get_uvalue( A&& )
      25                 : {
      26             200 :     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              56 : get_uvalue( A&& a )
      39                 : {
      40              56 :     if (a > 0)
      41              53 :         return static_cast<std::size_t>(a);
      42               3 :     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             291 : format_arg::
      69                 : format_arg( A&& a )
      70             291 :     : arg_( &a )
      71             291 :     , measure_( &measure_impl<A> )
      72             291 :     , fmt_( &format_impl<A> )
      73             291 :     , value_( get_uvalue(std::forward<A>(a) ))
      74             291 :     , ignore_( std::is_same<A, ignore_format>::value )
      75             291 : {}
      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             290 : 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             290 :     A const& ref = *static_cast<ref_t*>(
     112                 :         const_cast<void*>( a ) );
     113             285 :     formatter<ref_t> f;
     114             290 :     pctx.advance_to( f.parse(pctx) );
     115             288 :     mctx.advance_to( f.measure( ref, mctx, cs ) );
     116             288 : }
     117                 : 
     118                 : template <class A>
     119                 : void
     120             286 : 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             286 :     A const& ref = *static_cast<ref_t*>(
     130                 :             const_cast<void*>( a ) );
     131             281 :     formatter<ref_t> f;
     132             286 :     pctx.advance_to( f.parse(pctx) );
     133             286 :     fctx.advance_to( f.format( ref, fctx, cs ) );
     134             286 : }
     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             753 : measure_one(
     192                 :     char c,
     193                 :     grammar::lut_chars const& unreserved)
     194                 : {
     195                 :     // '%' must be reserved
     196             753 :     BOOST_ASSERT(! unreserved('%'));
     197             753 :     return 1 + !unreserved(c) * 2;
     198                 : }
     199                 : 
     200                 : inline
     201                 : void
     202            1856 : encode_one(
     203                 :     char*& out,
     204                 :     char c,
     205                 :     grammar::lut_chars const& unreserved)
     206                 : {
     207                 :     // '%' must be reserved
     208            1856 :     BOOST_ASSERT(! unreserved('%'));
     209            1856 :     if(unreserved(c))
     210                 :     {
     211            1837 :         *out++ = c;
     212            1837 :         return;
     213                 :     }
     214              19 :     *out++ = '%';
     215              19 :     auto uc = static_cast<unsigned char>(c);
     216              19 :     *out++ = urls::detail::hexdigs[0][uc>>4];
     217              19 :     *out++ = urls::detail::hexdigs[0][uc&0xf];
     218                 : }
     219                 : 
     220                 : // get an unsigned value from format_args
     221                 : BOOST_URL_DECL
     222                 : void
     223                 : get_width_from_args(
     224                 :     std::size_t arg_idx,
     225                 :     core::string_view arg_name,
     226                 :     format_args args,
     227                 :     std::size_t& w);
     228                 : 
     229                 : // formatter for string view
     230                 : template <>
     231                 : struct formatter<core::string_view>
     232                 : {
     233                 : private:
     234                 :     char fill = ' ';
     235                 :     char align = '\0';
     236                 :     std::size_t width = 0;
     237                 :     std::size_t width_idx = std::size_t(-1);
     238                 :     core::string_view width_name;
     239                 : 
     240                 : public:
     241                 :     BOOST_URL_DECL
     242                 :     char const*
     243                 :     parse(format_parse_context& ctx);
     244                 : 
     245                 :     BOOST_URL_DECL
     246                 :     std::size_t
     247                 :     measure(
     248                 :         core::string_view str,
     249                 :         measure_context& ctx,
     250                 :         grammar::lut_chars const& cs) const;
     251                 : 
     252                 :     BOOST_URL_DECL
     253                 :     char*
     254                 :     format(
     255                 :         core::string_view str,
     256                 :         format_context& ctx,
     257                 :         grammar::lut_chars const& cs) const;
     258                 : };
     259                 : 
     260                 : // formatter for anything convertible to a
     261                 : // string view
     262                 : template <class T>
     263                 : struct formatter<
     264                 :     T, typename std::enable_if<
     265                 :         std::is_convertible<
     266                 :             T, core::string_view>::value>::type>
     267                 : {
     268                 :     formatter<core::string_view> impl_;
     269                 : 
     270                 : public:
     271                 :     char const*
     272             322 :     parse(format_parse_context& ctx)
     273                 :     {
     274             322 :         return impl_.parse(ctx);
     275                 :     }
     276                 : 
     277                 :     std::size_t
     278             162 :     measure(
     279                 :         core::string_view str,
     280                 :         measure_context& ctx,
     281                 :         grammar::lut_chars const& cs) const
     282                 :     {
     283             162 :         return impl_.measure(str, ctx, cs);
     284                 :     }
     285                 : 
     286                 :     char*
     287             160 :     format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const
     288                 :     {
     289             160 :         return impl_.format(str, ctx, cs);
     290                 :     }
     291                 : };
     292                 : 
     293                 : template <>
     294                 : struct formatter<char>
     295                 : {
     296                 :     formatter<core::string_view> impl_;
     297                 : 
     298                 : public:
     299                 :     char const*
     300             129 :     parse(format_parse_context& ctx)
     301                 :     {
     302             129 :         return impl_.parse(ctx);
     303                 :     }
     304                 : 
     305                 :     std::size_t
     306              64 :     measure(
     307                 :         char c,
     308                 :         measure_context& ctx,
     309                 :         grammar::lut_chars const& cs) const
     310                 :     {
     311              64 :         return impl_.measure({&c, 1}, ctx, cs);
     312                 :     }
     313                 : 
     314                 :     char*
     315              64 :     format(
     316                 :         char c,
     317                 :         format_context& ctx,
     318                 :         grammar::lut_chars const& cs) const
     319                 :     {
     320              64 :         return impl_.format({&c, 1}, ctx, cs);
     321                 :     }
     322                 : };
     323                 : 
     324                 : // formatters for a single integer
     325                 : class integer_formatter_impl
     326                 : {
     327                 :     char fill = ' ';
     328                 :     char align = '\0';
     329                 :     char sign = '-';
     330                 :     bool zeros = false;
     331                 :     std::size_t width = 0;
     332                 :     std::size_t width_idx = std::size_t(-1);
     333                 :     core::string_view width_name;
     334                 : 
     335                 : public:
     336                 :     BOOST_URL_DECL
     337                 :     char const*
     338                 :     parse(format_parse_context& ctx);
     339                 : 
     340                 :     BOOST_URL_DECL
     341                 :     std::size_t
     342                 :     measure(
     343                 :         unsigned long long int v,
     344                 :         measure_context& ctx,
     345                 :         grammar::lut_chars const& cs) const;
     346                 : 
     347                 :     BOOST_URL_DECL
     348                 :     std::size_t
     349                 :     measure(
     350                 :         long long int v,
     351                 :         measure_context& ctx,
     352                 :         grammar::lut_chars const& cs) const;
     353                 : 
     354                 :     BOOST_URL_DECL
     355                 :     char*
     356                 :     format(
     357                 :         unsigned long long int v,
     358                 :         format_context& ctx,
     359                 :         grammar::lut_chars const& cs) const;
     360                 : 
     361                 :     BOOST_URL_DECL
     362                 :     char*
     363                 :     format(
     364                 :         long long int v,
     365                 :         format_context& ctx,
     366                 :         grammar::lut_chars const& cs) const;
     367                 : };
     368                 : 
     369                 : template <class T>
     370                 : struct formatter<
     371                 :     T, typename std::enable_if<
     372                 :         mp11::mp_contains<mp11::mp_list<
     373                 :             short int,
     374                 :             int,
     375                 :             long int,
     376                 :             long long int,
     377                 :             unsigned short int,
     378                 :             unsigned int,
     379                 :             unsigned long int,
     380                 :             unsigned long long int>, T>::value>::type>
     381                 : {
     382                 : private:
     383                 :     integer_formatter_impl impl_;
     384                 :     using base_value_type = typename std::conditional<
     385                 :         std::is_unsigned<T>::value,
     386                 :         unsigned long long int,
     387                 :         long long int
     388                 :         >::type;
     389                 : 
     390                 : public:
     391                 :     char const*
     392             115 :     parse(format_parse_context& ctx)
     393                 :     {
     394             115 :         return impl_.parse(ctx);
     395                 :     }
     396                 : 
     397                 :     std::size_t
     398              57 :     measure(
     399                 :         T v,
     400                 :         measure_context& ctx,
     401                 :         grammar::lut_chars const& cs) const
     402                 :     {
     403              57 :         return impl_.measure(
     404              57 :             static_cast<base_value_type>(v), ctx, cs);
     405                 :     }
     406                 : 
     407                 :     char*
     408              57 :     format(T v, format_context& ctx, grammar::lut_chars const& cs) const
     409                 :     {
     410              57 :         return impl_.format(
     411              57 :             static_cast<base_value_type>(v), ctx, cs);
     412                 :     }
     413                 : };
     414                 : 
     415                 : } // detail
     416                 : } // url
     417                 : } // boost
     418                 : 
     419                 : #endif
        

Generated by: LCOV version 2.3