Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-14 08:48:41

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_cv<
0110         typename std::remove_reference<A>::type>::type;
0111     A const& ref = *static_cast<ref_t*>(
0112         const_cast<void*>( a ) );
0113     formatter<ref_t> f;
0114     pctx.advance_to( f.parse(pctx) );
0115     mctx.advance_to( f.measure( ref, mctx, cs ) );
0116 }
0117 
0118 template <class A>
0119 void
0120 format_arg::
0121 format_impl(
0122     format_parse_context& pctx,
0123     format_context& fctx,
0124     grammar::lut_chars const& cs,
0125     void const* a )
0126 {
0127     using ref_t = typename std::remove_cv<
0128         typename std::remove_reference<A>::type>::type;
0129     A const& ref = *static_cast<ref_t*>(
0130             const_cast<void*>( a ) );
0131     formatter<ref_t> f;
0132     pctx.advance_to( f.parse(pctx) );
0133     fctx.advance_to( f.format( ref, fctx, cs ) );
0134 }
0135 
0136 // We point to formatter<ignore_format> where
0137 // the format_arg variant would store monostate
0138 template <>
0139 struct formatter<ignore_format>
0140 {
0141 public:
0142     char const*
0143     parse(format_parse_context& ctx) const
0144     {
0145         return parse_empty_spec(
0146             ctx.begin(), ctx.end());
0147     }
0148 
0149     std::size_t
0150     measure(
0151         ignore_format,
0152         measure_context& ctx,
0153         grammar::lut_chars const&) const
0154     {
0155         return ctx.out();
0156     }
0157 
0158     char*
0159     format(
0160         ignore_format,
0161         format_context& ctx,
0162         grammar::lut_chars const&) const
0163     {
0164         return ctx.out();
0165     }
0166 
0167     // We ignore the modifiers in all replacements
0168     // for now
0169     static
0170     char const*
0171     parse_empty_spec(
0172         char const* it,
0173         char const* end)
0174     {
0175         // [it, end] -> "} suffix"
0176         BOOST_ASSERT(it != end);
0177         ignore_unused(end);
0178         // Should be always empty/valid as an
0179         // implementation detail
0180         BOOST_ASSERT(*it == '}');
0181         /*
0182         if (*it != '}')
0183             urls::detail::throw_invalid_argument();
0184         */
0185         return it;
0186     }
0187 };
0188 
0189 inline
0190 std::size_t
0191 measure_one(
0192     char c,
0193     grammar::lut_chars const& unreserved)
0194 {
0195     // '%' must be reserved
0196     BOOST_ASSERT(! unreserved('%'));
0197     return 1 + !unreserved(c) * 2;
0198 }
0199 
0200 inline
0201 void
0202 encode_one(
0203     char*& out,
0204     char c,
0205     grammar::lut_chars const& unreserved)
0206 {
0207     // '%' must be reserved
0208     BOOST_ASSERT(! unreserved('%'));
0209     if(unreserved(c))
0210     {
0211         *out++ = c;
0212         return;
0213     }
0214     *out++ = '%';
0215     *out++ = urls::detail::hexdigs[0][c>>4];
0216     *out++ = urls::detail::hexdigs[0][c&0xf];
0217 }
0218 
0219 // get an unsigned value from format_args
0220 BOOST_URL_DECL
0221 void
0222 get_width_from_args(
0223     std::size_t arg_idx,
0224     core::string_view arg_name,
0225     format_args args,
0226     std::size_t& w);
0227 
0228 // formatter for string view
0229 template <>
0230 struct formatter<core::string_view>
0231 {
0232 private:
0233     char fill = ' ';
0234     char align = '\0';
0235     std::size_t width = 0;
0236     std::size_t width_idx = std::size_t(-1);
0237     core::string_view width_name;
0238 
0239 public:
0240     BOOST_URL_DECL
0241     char const*
0242     parse(format_parse_context& ctx);
0243 
0244     BOOST_URL_DECL
0245     std::size_t
0246     measure(
0247         core::string_view str,
0248         measure_context& ctx,
0249         grammar::lut_chars const& cs) const;
0250 
0251     BOOST_URL_DECL
0252     char*
0253     format(
0254         core::string_view str,
0255         format_context& ctx,
0256         grammar::lut_chars const& cs) const;
0257 };
0258 
0259 // formatter for anything convertible to a
0260 // string view
0261 template <class T>
0262 struct formatter<
0263     T, typename std::enable_if<
0264         std::is_convertible<
0265             T, core::string_view>::value>::type>
0266 {
0267     formatter<core::string_view> impl_;
0268 
0269 public:
0270     char const*
0271     parse(format_parse_context& ctx)
0272     {
0273         return impl_.parse(ctx);
0274     }
0275 
0276     std::size_t
0277     measure(
0278         core::string_view str,
0279         measure_context& ctx,
0280         grammar::lut_chars const& cs) const
0281     {
0282         return impl_.measure(str, ctx, cs);
0283     }
0284 
0285     char*
0286     format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const
0287     {
0288         return impl_.format(str, ctx, cs);
0289     }
0290 };
0291 
0292 template <>
0293 struct formatter<char>
0294 {
0295     formatter<core::string_view> impl_;
0296 
0297 public:
0298     char const*
0299     parse(format_parse_context& ctx)
0300     {
0301         return impl_.parse(ctx);
0302     }
0303 
0304     std::size_t
0305     measure(
0306         char c,
0307         measure_context& ctx,
0308         grammar::lut_chars const& cs) const
0309     {
0310         return impl_.measure({&c, 1}, ctx, cs);
0311     }
0312 
0313     char*
0314     format(
0315         char c,
0316         format_context& ctx,
0317         grammar::lut_chars const& cs) const
0318     {
0319         return impl_.format({&c, 1}, ctx, cs);
0320     }
0321 };
0322 
0323 // formatters for a single integer
0324 class integer_formatter_impl
0325 {
0326     char fill = ' ';
0327     char align = '\0';
0328     char sign = '-';
0329     bool zeros = false;
0330     std::size_t width = 0;
0331     std::size_t width_idx = std::size_t(-1);
0332     core::string_view width_name;
0333 
0334 public:
0335     BOOST_URL_DECL
0336     char const*
0337     parse(format_parse_context& ctx);
0338 
0339     BOOST_URL_DECL
0340     std::size_t
0341     measure(
0342         unsigned long long int v,
0343         measure_context& ctx,
0344         grammar::lut_chars const& cs) const;
0345 
0346     BOOST_URL_DECL
0347     std::size_t
0348     measure(
0349         long long int v,
0350         measure_context& ctx,
0351         grammar::lut_chars const& cs) const;
0352 
0353     BOOST_URL_DECL
0354     char*
0355     format(
0356         unsigned long long int v,
0357         format_context& ctx,
0358         grammar::lut_chars const& cs) const;
0359 
0360     BOOST_URL_DECL
0361     char*
0362     format(
0363         long long int v,
0364         format_context& ctx,
0365         grammar::lut_chars const& cs) const;
0366 };
0367 
0368 template <class T>
0369 struct formatter<
0370     T, typename std::enable_if<
0371         mp11::mp_contains<mp11::mp_list<
0372             short int,
0373             int,
0374             long int,
0375             long long int,
0376             unsigned short int,
0377             unsigned int,
0378             unsigned long int,
0379             unsigned long long int>, T>::value>::type>
0380 {
0381 private:
0382     integer_formatter_impl impl_;
0383     using base_value_type = typename std::conditional<
0384         std::is_unsigned<T>::value,
0385         unsigned long long int,
0386         long long int
0387         >::type;
0388 
0389 public:
0390     char const*
0391     parse(format_parse_context& ctx)
0392     {
0393         return impl_.parse(ctx);
0394     }
0395 
0396     std::size_t
0397     measure(
0398         T v,
0399         measure_context& ctx,
0400         grammar::lut_chars const& cs) const
0401     {
0402         return impl_.measure(
0403             static_cast<base_value_type>(v), ctx, cs);
0404     }
0405 
0406     char*
0407     format(T v, format_context& ctx, grammar::lut_chars const& cs) const
0408     {
0409         return impl_.format(
0410             static_cast<base_value_type>(v), ctx, cs);
0411     }
0412 };
0413 
0414 } // detail
0415 } // url
0416 } // boost
0417 
0418 #endif