Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:26

0001 //
0002 // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/url
0008 //
0009 
0010 #ifndef BOOST_URL_DETAIL_IMPL_FORMAT_ARGS_HPP
0011 #define BOOST_URL_DETAIL_IMPL_FORMAT_ARGS_HPP
0012 
0013 namespace boost {
0014 namespace urls {
0015 namespace detail {
0016 
0017 template<
0018     class A,
0019     typename std::enable_if<
0020         !std::is_integral<
0021             typename std::decay<A>::type>::value,
0022                 int>::type = 0>
0023 std::size_t
0024 get_uvalue( A&& )
0025 {
0026     return 0;
0027 }
0028 
0029 template<
0030     class A,
0031     typename std::enable_if<
0032         std::is_integral<
0033             typename std::decay<A>::type>::value &&
0034         std::is_signed<
0035             typename std::decay<A>::type>::value,
0036         int>::type = 0>
0037 std::size_t
0038 get_uvalue( A&& a )
0039 {
0040     if (a > 0)
0041         return static_cast<std::size_t>(a);
0042     return 0;
0043 }
0044 
0045 template<
0046     class A,
0047     typename std::enable_if<
0048         std::is_integral<
0049             typename std::decay<A>::type>::value &&
0050             std::is_unsigned<
0051                 typename std::decay<A>::type>::value,
0052         int>::type = 0>
0053 std::size_t
0054 get_uvalue( A&& a )
0055 {
0056     return static_cast<std::size_t>(a);
0057 }
0058 
0059 BOOST_URL_DECL
0060 std::size_t
0061 get_uvalue( core::string_view a );
0062 
0063 BOOST_URL_DECL
0064 std::size_t
0065 get_uvalue( char a );
0066 
0067 template<class A>
0068 format_arg::
0069 format_arg( A&& a )
0070     : arg_( &a )
0071     , measure_( &measure_impl<A> )
0072     , fmt_( &format_impl<A> )
0073     , value_( get_uvalue(std::forward<A>(a) ))
0074     , ignore_( std::is_same<A, ignore_format>::value )
0075 {}
0076 
0077 template<class A>
0078 format_arg::
0079 format_arg( named_arg<A>&& a )
0080     : arg_( &a.value )
0081     , measure_( &measure_impl<A> )
0082     , fmt_( &format_impl<A> )
0083     , name_( a.name )
0084     , value_( get_uvalue(a.value))
0085 {}
0086 
0087 template<class A>
0088 format_arg::
0089 format_arg( core::string_view name, A&& a )
0090     : arg_( &a )
0091     , measure_( &measure_impl<A> )
0092     , fmt_( &format_impl<A> )
0093     , name_( name )
0094     , value_( get_uvalue(a) )
0095 {}
0096 
0097 // define the type-erased implementations that
0098 // depends on everything: the context types,
0099 // formatters, and type erased args
0100 template <class A>
0101 void
0102 format_arg::
0103 measure_impl(
0104     format_parse_context& pctx,
0105     measure_context& mctx,
0106     grammar::lut_chars const& cs,
0107     void const* a )
0108 {
0109     using ref_t = typename std::remove_reference<A>::type;
0110     A const& ref = *static_cast<ref_t*>(
0111         const_cast<void*>( a ) );
0112     formatter<ref_t> f;
0113     pctx.advance_to( f.parse(pctx) );
0114     mctx.advance_to( f.measure( ref, mctx, cs ) );
0115 }
0116 
0117 template <class A>
0118 void
0119 format_arg::
0120 format_impl(
0121     format_parse_context& pctx,
0122     format_context& fctx,
0123     grammar::lut_chars const& cs,
0124     void const* a )
0125 {
0126     using ref_t = typename std::remove_reference<A>::type;
0127     A const& ref = *static_cast<ref_t*>(
0128             const_cast<void*>( a ) );
0129     formatter<ref_t> f;
0130     pctx.advance_to( f.parse(pctx) );
0131     fctx.advance_to( f.format( ref, fctx, cs ) );
0132 }
0133 
0134 // We point to formatter<ignore_format> where
0135 // the format_arg variant would store monostate
0136 template <>
0137 struct formatter<ignore_format>
0138 {
0139 public:
0140     char const*
0141     parse(format_parse_context& ctx) const
0142     {
0143         return parse_empty_spec(
0144             ctx.begin(), ctx.end());
0145     }
0146 
0147     std::size_t
0148     measure(
0149         ignore_format,
0150         measure_context& ctx,
0151         grammar::lut_chars const&) const
0152     {
0153         return ctx.out();
0154     }
0155 
0156     char*
0157     format(
0158         ignore_format,
0159         format_context& ctx,
0160         grammar::lut_chars const&) const
0161     {
0162         return ctx.out();
0163     }
0164 
0165     // We ignore the modifiers in all replacements
0166     // for now
0167     static
0168     char const*
0169     parse_empty_spec(
0170         char const* it,
0171         char const* end)
0172     {
0173         // [it, end] -> "} suffix"
0174         BOOST_ASSERT(it != end);
0175         ignore_unused(end);
0176         // Should be always empty/valid as an
0177         // implementation detail
0178         BOOST_ASSERT(*it == '}');
0179         /*
0180         if (*it != '}')
0181             urls::detail::throw_invalid_argument();
0182         */
0183         return it;
0184     }
0185 };
0186 
0187 inline
0188 std::size_t
0189 measure_one(
0190     char c,
0191     grammar::lut_chars const& unreserved)
0192 {
0193     // '%' must be reserved
0194     BOOST_ASSERT(! unreserved('%'));
0195     return 1 + !unreserved(c) * 2;
0196 }
0197 
0198 inline
0199 void
0200 encode_one(
0201     char*& out,
0202     char c,
0203     grammar::lut_chars const& unreserved)
0204 {
0205     // '%' must be reserved
0206     BOOST_ASSERT(! unreserved('%'));
0207     if(unreserved(c))
0208     {
0209         *out++ = c;
0210         return;
0211     }
0212     *out++ = '%';
0213     *out++ = urls::detail::hexdigs[0][c>>4];
0214     *out++ = urls::detail::hexdigs[0][c&0xf];
0215 }
0216 
0217 // get an unsigned value from format_args
0218 BOOST_URL_DECL
0219 void
0220 get_width_from_args(
0221     std::size_t arg_idx,
0222     core::string_view arg_name,
0223     format_args args,
0224     std::size_t& w);
0225 
0226 // formatter for string view
0227 template <>
0228 struct formatter<core::string_view>
0229 {
0230 private:
0231     char fill = ' ';
0232     char align = '\0';
0233     std::size_t width = 0;
0234     std::size_t width_idx = std::size_t(-1);
0235     core::string_view width_name;
0236 
0237 public:
0238     BOOST_URL_DECL
0239     char const*
0240     parse(format_parse_context& ctx);
0241 
0242     BOOST_URL_DECL
0243     std::size_t
0244     measure(
0245         core::string_view str,
0246         measure_context& ctx,
0247         grammar::lut_chars const& cs) const;
0248 
0249     BOOST_URL_DECL
0250     char*
0251     format(
0252         core::string_view str,
0253         format_context& ctx,
0254         grammar::lut_chars const& cs) const;
0255 };
0256 
0257 // formatter for anything convertible to a
0258 // string view
0259 template <class T>
0260 struct formatter<
0261     T, typename std::enable_if<
0262         std::is_convertible<
0263             T, core::string_view>::value>::type>
0264 {
0265     formatter<core::string_view> impl_;
0266 
0267 public:
0268     char const*
0269     parse(format_parse_context& ctx)
0270     {
0271         return impl_.parse(ctx);
0272     }
0273 
0274     std::size_t
0275     measure(
0276         core::string_view str,
0277         measure_context& ctx,
0278         grammar::lut_chars const& cs) const
0279     {
0280         return impl_.measure(str, ctx, cs);
0281     }
0282 
0283     char*
0284     format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const
0285     {
0286         return impl_.format(str, ctx, cs);
0287     }
0288 };
0289 
0290 template <>
0291 struct formatter<char>
0292 {
0293     formatter<core::string_view> impl_;
0294 
0295 public:
0296     char const*
0297     parse(format_parse_context& ctx)
0298     {
0299         return impl_.parse(ctx);
0300     }
0301 
0302     std::size_t
0303     measure(
0304         char c,
0305         measure_context& ctx,
0306         grammar::lut_chars const& cs) const
0307     {
0308         return impl_.measure({&c, 1}, ctx, cs);
0309     }
0310 
0311     char*
0312     format(
0313         char c,
0314         format_context& ctx,
0315         grammar::lut_chars const& cs) const
0316     {
0317         return impl_.format({&c, 1}, ctx, cs);
0318     }
0319 };
0320 
0321 // formatters for a single integer
0322 class integer_formatter_impl
0323 {
0324     char fill = ' ';
0325     char align = '\0';
0326     char sign = '-';
0327     bool zeros = false;
0328     std::size_t width = 0;
0329     std::size_t width_idx = std::size_t(-1);
0330     core::string_view width_name;
0331 
0332 public:
0333     BOOST_URL_DECL
0334     char const*
0335     parse(format_parse_context& ctx);
0336 
0337     BOOST_URL_DECL
0338     std::size_t
0339     measure(
0340         unsigned long long int v,
0341         measure_context& ctx,
0342         grammar::lut_chars const& cs) const;
0343 
0344     BOOST_URL_DECL
0345     std::size_t
0346     measure(
0347         long long int v,
0348         measure_context& ctx,
0349         grammar::lut_chars const& cs) const;
0350 
0351     BOOST_URL_DECL
0352     char*
0353     format(
0354         unsigned long long int v,
0355         format_context& ctx,
0356         grammar::lut_chars const& cs) const;
0357 
0358     BOOST_URL_DECL
0359     char*
0360     format(
0361         long long int v,
0362         format_context& ctx,
0363         grammar::lut_chars const& cs) const;
0364 };
0365 
0366 template <class T>
0367 struct formatter<
0368     T, typename std::enable_if<
0369         mp11::mp_contains<mp11::mp_list<
0370             short int,
0371             int,
0372             long int,
0373             long long int,
0374             unsigned short int,
0375             unsigned int,
0376             unsigned long int,
0377             unsigned long long int>, T>::value>::type>
0378 {
0379 private:
0380     integer_formatter_impl impl_;
0381     using base_value_type = typename std::conditional<
0382         std::is_unsigned<T>::value,
0383         unsigned long long int,
0384         long long int
0385         >::type;
0386 
0387 public:
0388     char const*
0389     parse(format_parse_context& ctx)
0390     {
0391         return impl_.parse(ctx);
0392     }
0393 
0394     std::size_t
0395     measure(
0396         T v,
0397         measure_context& ctx,
0398         grammar::lut_chars const& cs) const
0399     {
0400         return impl_.measure(
0401             static_cast<base_value_type>(v), ctx, cs);
0402     }
0403 
0404     char*
0405     format(T v, format_context& ctx, grammar::lut_chars const& cs) const
0406     {
0407         return impl_.format(
0408             static_cast<base_value_type>(v), ctx, cs);
0409     }
0410 };
0411 
0412 } // detail
0413 } // url
0414 } // boost
0415 
0416 #endif