123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- //
- // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // Official repository: https://github.com/boostorg/url
- //
- #ifndef BOOST_URL_DETAIL_FORMAT_ARGS_HPP
- #define BOOST_URL_DETAIL_FORMAT_ARGS_HPP
- #include <boost/url/detail/encode.hpp>
- #include <boost/url/grammar/lut_chars.hpp>
- #include <boost/core/ignore_unused.hpp>
- #include <array>
- // This file implements functions and classes to
- // type-erase format arguments.
- namespace boost {
- namespace urls {
- namespace detail {
- // state of the format string. It basically keeps
- // track of where we are in the format string.
- class format_parse_context
- {
- char const* begin_;
- char const* end_;
- std::size_t arg_id_ = 0;
- public:
- constexpr
- format_parse_context(
- char const* first,
- char const* last,
- std::size_t arg_id = 0)
- : begin_( first )
- , end_( last )
- , arg_id_( arg_id )
- {}
- constexpr
- format_parse_context(
- core::string_view fmt,
- std::size_t arg_id = 0)
- : format_parse_context(
- fmt.data(),
- fmt.data() + fmt.size(),
- arg_id )
- {}
- constexpr
- char const*
- begin() const noexcept
- {
- return begin_;
- }
- constexpr
- char const*
- end() const noexcept
- {
- return end_;
- }
- BOOST_CXX14_CONSTEXPR
- void
- advance_to( char const* it )
- {
- begin_ = it;
- }
- std::size_t
- next_arg_id()
- {
- return arg_id_++;
- }
- };
- // State of the destination string
- class format_context;
- class measure_context;
- struct ignore_format {};
- template <class T>
- struct named_arg
- {
- core::string_view name;
- T const& value;
- named_arg(core::string_view n, T const& v)
- : name(n)
- , value(v)
- {}
- };
- // A type erased format argument
- class format_arg
- {
- void const* arg_;
- void (*measure_)(
- format_parse_context&,
- measure_context&,
- grammar::lut_chars const&,
- void const* );
- void (*fmt_)(
- format_parse_context&,
- format_context&,
- grammar::lut_chars const&,
- void const* );
- core::string_view name_;
- std::size_t value_ = 0;
- bool ignore_ = false;
- template <class A>
- static
- void
- measure_impl(
- format_parse_context& pctx,
- measure_context& mctx,
- grammar::lut_chars const& cs,
- void const* a );
- template <class A>
- static
- void
- format_impl(
- format_parse_context& pctx,
- format_context& fctx,
- grammar::lut_chars const& cs,
- void const* a );
- public:
- template<class A>
- format_arg( A&& a );
- template<class A>
- format_arg( named_arg<A>&& a );
- template<class A>
- format_arg( core::string_view name, A&& a );
- format_arg()
- : format_arg(ignore_format{})
- {}
- explicit
- operator bool() const noexcept
- {
- return !ignore_;
- }
- void
- measure(
- format_parse_context& pctx,
- measure_context& mctx,
- grammar::lut_chars const& cs)
- {
- measure_( pctx, mctx, cs, arg_ );
- }
- void
- format(
- format_parse_context& pctx,
- format_context& fctx,
- grammar::lut_chars const& cs )
- {
- fmt_( pctx, fctx, cs, arg_ );
- }
- core::string_view
- name() const
- {
- return name_;
- }
- std::size_t
- value() const
- {
- return value_;
- }
- };
- // create temp stack storage for type erased args
- template< class... Args >
- std::array<format_arg, sizeof...(Args)>
- make_format_args( Args&&... args )
- {
- return {{ std::forward<Args>(args)... }};
- }
- // reference to an array of format_args
- class format_args
- {
- format_arg const* p_{nullptr};
- std::size_t n_{0};
- public:
- format_args(
- detail::format_arg const* first,
- detail::format_arg const* last ) noexcept
- : p_(first)
- , n_(static_cast<std::size_t>(last - first))
- {}
- template < std::size_t N >
- format_args( std::array<format_arg, N> const& store ) noexcept
- : p_(store.data())
- , n_(store.size())
- {}
- format_arg
- get( std::size_t i ) const noexcept
- {
- if (i < n_)
- return p_[i];
- return {};
- }
- format_arg
- get( core::string_view name ) const noexcept
- {
- for (std::size_t i = 0; i < n_; ++i)
- {
- if (p_[i].name() == name)
- return p_[i];
- }
- return {};
- }
- };
- // define the format_context after format_args
- class format_context
- {
- format_args args_;
- char* out_;
- public:
- format_context(
- char* out,
- format_args args )
- : args_( args )
- , out_( out )
- {}
- format_args
- args() const noexcept
- {
- return args_;
- }
- format_arg
- arg( std::size_t id ) const noexcept
- {
- return args_.get( id );
- }
- format_arg
- arg( core::string_view name ) const noexcept
- {
- return args_.get( name );
- }
- char*
- out()
- {
- return out_;
- }
- void
- advance_to( char* it )
- {
- out_ = it;
- }
- };
- // define the measure_context after format_args
- class measure_context
- {
- format_args args_;
- std::size_t out_;
- public:
- measure_context(
- format_args args )
- : measure_context(0, args)
- {}
- measure_context(
- std::size_t out,
- format_args args )
- : args_( args )
- , out_( out )
- {}
- format_args
- args() const noexcept
- {
- return args_;
- }
- format_arg
- arg( std::size_t id ) const noexcept
- {
- return args_.get( id );
- }
- format_arg
- arg( core::string_view name ) const noexcept
- {
- return args_.get( name );
- }
- std::size_t
- out()
- {
- return out_;
- }
- void
- advance_to( std::size_t n )
- {
- out_ = n;
- }
- };
- // fwd declare the formatter
- template <class T, class = void>
- struct formatter;
- } // detail
- } // url
- } // boost
- #include <boost/url/detail/impl/format_args.hpp>
- #endif
|