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_FORMAT_ARGS_HPP
0011 #define BOOST_URL_DETAIL_FORMAT_ARGS_HPP
0012 
0013 #include <boost/url/detail/encode.hpp>
0014 #include <boost/url/grammar/lut_chars.hpp>
0015 
0016 #include <boost/core/ignore_unused.hpp>
0017 #include <array>
0018 
0019 // This file implements functions and classes to
0020 // type-erase format arguments.
0021 
0022 namespace boost {
0023 namespace urls {
0024 namespace detail {
0025 
0026 // state of the format string. It basically keeps
0027 // track of where we are in the format string.
0028 class format_parse_context
0029 {
0030     char const* begin_;
0031     char const* end_;
0032     std::size_t arg_id_ = 0;
0033 
0034 public:
0035     constexpr
0036     format_parse_context(
0037         char const* first,
0038         char const* last,
0039         std::size_t arg_id = 0)
0040         : begin_( first )
0041         , end_( last )
0042         , arg_id_( arg_id )
0043     {}
0044 
0045     constexpr
0046     format_parse_context(
0047         core::string_view fmt,
0048         std::size_t arg_id = 0)
0049         : format_parse_context(
0050             fmt.data(),
0051             fmt.data() + fmt.size(),
0052             arg_id )
0053     {}
0054 
0055     constexpr
0056     char const*
0057     begin() const noexcept
0058     {
0059         return begin_;
0060     }
0061 
0062     constexpr
0063     char const*
0064     end() const noexcept
0065     {
0066         return end_;
0067     }
0068 
0069     BOOST_CXX14_CONSTEXPR
0070     void
0071     advance_to( char const* it )
0072     {
0073         begin_ = it;
0074     }
0075 
0076     std::size_t
0077     next_arg_id()
0078     {
0079         return arg_id_++;
0080     }
0081 };
0082 
0083 // State of the destination string
0084 class format_context;
0085 class measure_context;
0086 struct ignore_format {};
0087 
0088 template <class T>
0089 struct named_arg
0090 {
0091     core::string_view name;
0092     T const& value;
0093 
0094     named_arg(core::string_view n, T const& v)
0095         : name(n)
0096         , value(v)
0097     {}
0098 };
0099 
0100 // A type erased format argument
0101 class format_arg
0102 {
0103     void const* arg_;
0104     void (*measure_)(
0105         format_parse_context&,
0106         measure_context&,
0107         grammar::lut_chars const&,
0108         void const* );
0109     void (*fmt_)(
0110         format_parse_context&,
0111         format_context&,
0112         grammar::lut_chars const&,
0113         void const* );
0114     core::string_view name_;
0115     std::size_t value_ = 0;
0116     bool ignore_ = false;
0117 
0118     template <class A>
0119     static
0120     void
0121     measure_impl(
0122         format_parse_context& pctx,
0123         measure_context& mctx,
0124         grammar::lut_chars const& cs,
0125         void const* a );
0126 
0127     template <class A>
0128     static
0129     void
0130     format_impl(
0131         format_parse_context& pctx,
0132         format_context& fctx,
0133         grammar::lut_chars const& cs,
0134         void const* a );
0135 
0136 public:
0137     template<class A>
0138     format_arg( A&& a );
0139 
0140     template<class A>
0141     format_arg( named_arg<A>&& a );
0142 
0143     template<class A>
0144     format_arg( core::string_view name, A&& a );
0145 
0146     format_arg()
0147         : format_arg(ignore_format{})
0148     {}
0149 
0150     explicit
0151     operator bool() const noexcept
0152     {
0153         return !ignore_;
0154     }
0155 
0156     void
0157     measure(
0158         format_parse_context& pctx,
0159         measure_context& mctx,
0160         grammar::lut_chars const& cs)
0161     {
0162         measure_( pctx, mctx, cs, arg_ );
0163     }
0164 
0165     void
0166     format(
0167         format_parse_context& pctx,
0168         format_context& fctx,
0169         grammar::lut_chars const& cs )
0170     {
0171         fmt_( pctx, fctx, cs, arg_ );
0172     }
0173 
0174     core::string_view
0175     name() const
0176     {
0177         return name_;
0178     }
0179 
0180     std::size_t
0181     value() const
0182     {
0183         return value_;
0184     }
0185 };
0186 
0187 // create temp stack storage for type erased args
0188 template< class... Args >
0189 std::array<format_arg, sizeof...(Args)>
0190 make_format_args( Args&&... args )
0191 {
0192     return {{ std::forward<Args>(args)... }};
0193 }
0194 
0195 // reference to an array of format_args
0196 class format_args
0197 {
0198     format_arg const* p_{nullptr};
0199     std::size_t n_{0};
0200 
0201 public:
0202     format_args(
0203         detail::format_arg const* first,
0204         detail::format_arg const* last ) noexcept
0205         : p_(first)
0206         , n_(static_cast<std::size_t>(last - first))
0207     {}
0208 
0209     template < std::size_t N >
0210     format_args( std::array<format_arg, N> const& store ) noexcept
0211         : p_(store.data())
0212         , n_(store.size())
0213     {}
0214 
0215     format_arg
0216     get( std::size_t i ) const noexcept
0217     {
0218         if (i < n_)
0219             return p_[i];
0220         return {};
0221     }
0222 
0223     format_arg
0224     get( core::string_view name ) const noexcept
0225     {
0226         for (std::size_t i = 0; i < n_; ++i)
0227         {
0228             if (p_[i].name() == name)
0229                 return p_[i];
0230         }
0231         return {};
0232     }
0233 };
0234 
0235 // define the format_context after format_args
0236 class format_context
0237 {
0238     format_args args_;
0239     char* out_;
0240 
0241 public:
0242     format_context(
0243         char* out,
0244         format_args args )
0245         : args_( args )
0246         , out_( out )
0247     {}
0248 
0249     format_args
0250     args() const noexcept
0251     {
0252         return args_;
0253     }
0254 
0255     format_arg
0256     arg( std::size_t id ) const noexcept
0257     {
0258         return args_.get( id );
0259     }
0260 
0261     format_arg
0262     arg( core::string_view name ) const noexcept
0263     {
0264         return args_.get( name );
0265     }
0266 
0267     char*
0268     out()
0269     {
0270         return out_;
0271     }
0272 
0273     void
0274     advance_to( char* it )
0275     {
0276         out_ = it;
0277     }
0278 };
0279 
0280 // define the measure_context after format_args
0281 class measure_context
0282 {
0283     format_args args_;
0284     std::size_t out_;
0285 
0286 public:
0287     measure_context(
0288         format_args args )
0289         : measure_context(0, args)
0290     {}
0291 
0292     measure_context(
0293         std::size_t out,
0294         format_args args )
0295         : args_( args )
0296         , out_( out )
0297     {}
0298 
0299     format_args
0300     args() const noexcept
0301     {
0302         return args_;
0303     }
0304 
0305     format_arg
0306     arg( std::size_t id ) const noexcept
0307     {
0308         return args_.get( id );
0309     }
0310 
0311     format_arg
0312     arg( core::string_view name ) const noexcept
0313     {
0314         return args_.get( name );
0315     }
0316 
0317     std::size_t
0318     out()
0319     {
0320         return out_;
0321     }
0322 
0323     void
0324     advance_to( std::size_t n )
0325     {
0326         out_ = n;
0327     }
0328 };
0329 
0330 // fwd declare the formatter
0331 template <class T, class = void>
0332 struct formatter;
0333 
0334 } // detail
0335 } // url
0336 } // boost
0337 
0338 #include <boost/url/detail/impl/format_args.hpp>
0339 
0340 #endif