// // Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_ANY_PARAMS_ITER_HPP #define BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP #include #include #include #include #include #include namespace boost { namespace urls { namespace detail { //------------------------------------------------ // // any_params_iter // //------------------------------------------------ /* An iterator to a type-erased, possibly encoded sequence of query params_ref. */ struct BOOST_SYMBOL_VISIBLE any_params_iter { protected: any_params_iter( bool empty_, string_view s0_ = {}, string_view s1_ = {}) noexcept : s0(s0_) , s1(s1_) , empty(empty_) { } public: // these are adjusted // when self-intersecting string_view s0; string_view s1; // True if the sequence is empty bool empty = false; BOOST_URL_DECL virtual ~any_params_iter() noexcept = 0; // Rewind the iterator to the beginning virtual void rewind() noexcept = 0; // Measure and increment current element // element. // Returns false on end of range. // n is increased by encoded size. // Can throw on bad percent-escape virtual bool measure(std::size_t& n) = 0; // Copy and increment the current // element. encoding is performed // if needed. virtual void copy( char*& dest, char const* end) noexcept = 0; }; //------------------------------------------------ // // query_iter // //------------------------------------------------ // A string of plain query params struct BOOST_SYMBOL_VISIBLE query_iter : any_params_iter { // ne = never empty BOOST_URL_DECL explicit query_iter( string_view s, bool ne = false) noexcept; private: string_view s_; std::size_t n_; char const* p_; bool at_end_; void rewind() noexcept override; bool measure(std::size_t&) noexcept override; void copy(char*&, char const*) noexcept override; void increment() noexcept; }; //------------------------------------------------ // // param_iter // //------------------------------------------------ // A 1-param range allowing // self-intersection struct BOOST_SYMBOL_VISIBLE param_iter : any_params_iter { BOOST_URL_DECL explicit param_iter( param_view const&) noexcept; private: bool has_value_; bool at_end_ = false; void rewind() noexcept override; bool measure(std::size_t&) noexcept override; void copy(char*&, char const*) noexcept override; }; //------------------------------------------------ // // params_iter_base // //------------------------------------------------ struct params_iter_base { protected: // return encoded size BOOST_URL_DECL static void measure_impl( std::size_t& n, param_view const& p) noexcept; // encode to dest BOOST_URL_DECL static void copy_impl( char*& dest, char const* end, param_view const& v) noexcept; }; //------------------------------------------------ // A range of plain query params_ref template struct params_iter : any_params_iter , private params_iter_base { BOOST_STATIC_ASSERT( std::is_convertible< typename std::iterator_traits< FwdIt>::reference, param_view>::value); params_iter( FwdIt first, FwdIt last) noexcept : any_params_iter( first == last) , it0_(first) , it_(first) , end_(last) { } private: FwdIt it0_; FwdIt it_; FwdIt end_; void rewind() noexcept override { it_ = it0_; } bool measure( std::size_t& n) noexcept override { if(it_ == end_) return false; measure_impl(n, param_view(*it_++)); return true; } void copy( char*& dest, char const* end) noexcept override { copy_impl(dest, end, param_view(*it_++)); } }; //------------------------------------------------ // // param_encoded_iter // //------------------------------------------------ // A 1-param encoded range // allowing self-intersection struct BOOST_SYMBOL_VISIBLE param_encoded_iter : any_params_iter { BOOST_URL_DECL explicit param_encoded_iter( param_pct_view const&) noexcept; private: bool has_value_; bool at_end_ = false; void rewind() noexcept override; bool measure(std::size_t&) noexcept override; void copy(char*&, char const*) noexcept override; }; //------------------------------------------------ // // params_encoded_iter // //------------------------------------------------ // Validating and copying from // a string of encoded params struct params_encoded_iter_base { protected: BOOST_URL_DECL static void measure_impl( std::size_t& n, param_view const& v) noexcept; BOOST_URL_DECL static void copy_impl( char*& dest, char const* end, param_view const& v) noexcept; }; //------------------------------------------------ // A range of encoded query params_ref template struct params_encoded_iter : any_params_iter , private params_encoded_iter_base { BOOST_STATIC_ASSERT( std::is_convertible< typename std::iterator_traits< FwdIt>::reference, param_view>::value); params_encoded_iter( FwdIt first, FwdIt last) noexcept : any_params_iter( first == last) , it0_(first) , it_(first) , end_(last) { } private: FwdIt it0_; FwdIt it_; FwdIt end_; void rewind() noexcept override { it_ = it0_; } bool measure( std::size_t& n) override { if(it_ == end_) return false; // throw on invalid input measure_impl(n, param_pct_view( param_view(*it_++))); return true; } void copy( char*& dest, char const* end ) noexcept override { copy_impl(dest, end, param_view(*it_++)); } }; //------------------------------------------------ // // param_value_iter // //------------------------------------------------ // An iterator which outputs // one value on an existing key struct param_value_iter : any_params_iter { param_value_iter( std::size_t nk, string_view const& value, bool has_value) noexcept : any_params_iter( false, value) , nk_(nk) , has_value_(has_value) { } private: std::size_t nk_ = 0; bool has_value_ = false; bool at_end_ = false; void rewind() noexcept override; bool measure(std::size_t&) noexcept override; void copy(char*&, char const*) noexcept override; }; //------------------------------------------------ // // param_encoded_value_iter // //------------------------------------------------ // An iterator which outputs one // encoded value on an existing key struct param_encoded_value_iter : any_params_iter { param_encoded_value_iter( std::size_t nk, pct_string_view const& value, bool has_value) noexcept : any_params_iter( false, value) , nk_(nk) , has_value_(has_value) { } private: std::size_t nk_ = 0; bool has_value_ = false; bool at_end_ = false; void rewind() noexcept override; bool measure(std::size_t&) noexcept override; void copy(char*&, char const*) noexcept override; }; //------------------------------------------------ template params_iter make_params_iter( FwdIt first, FwdIt last) { return params_iter< FwdIt>(first, last); } template params_encoded_iter make_params_encoded_iter( FwdIt first, FwdIt last) { return params_encoded_iter< FwdIt>(first, last); } } // detail } // urls } // boost #endif