// // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast // #ifndef BOOST_BEAST_HTTP_DETAIL_BASIC_PARSER_HPP #define BOOST_BEAST_HTTP_DETAIL_BASIC_PARSER_HPP #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace beast { namespace http { namespace detail { struct basic_parser_base { // limit on the size of the obs-fold buffer // // https://stackoverflow.com/questions/686217/maximum-on-http-header-values // static std::size_t constexpr max_obs_fold = 4096; template struct is_unsigned_integer: std::integral_constant::is_integer && ! std::numeric_limits::is_signed> {}; enum class state { nothing_yet = 0, start_line, fields, body0, body, body_to_eof0, body_to_eof, chunk_header0, chunk_header, chunk_body, complete }; static bool is_digit(char c) { return static_cast(c-'0') < 10; } static bool is_print(char c) { return static_cast(c-32) < 95; } template static FwdIt trim_front(FwdIt it, FwdIt const& end) { while(it != end) { if(*it != ' ' && *it != '\t') break; ++it; } return it; } template static RanIt trim_back( RanIt it, RanIt const& first) { while(it != first) { auto const c = it[-1]; if(c != ' ' && c != '\t') break; --it; } return it; } static string_view make_string(char const* first, char const* last) { return {first, static_cast< std::size_t>(last - first)}; } //-------------------------------------------------------------------------- BOOST_BEAST_DECL static bool is_pathchar(char c); BOOST_BEAST_DECL static bool unhex(unsigned char& d, char c); BOOST_BEAST_DECL static std::pair find_fast( char const* buf, char const* buf_end, char const* ranges, size_t ranges_size); BOOST_BEAST_DECL static char const* find_eol( char const* it, char const* last, error_code& ec); BOOST_BEAST_DECL static char const* find_eom(char const* p, char const* last); //-------------------------------------------------------------------------- BOOST_BEAST_DECL static char const* parse_token_to_eol( char const* p, char const* last, char const*& token_last, error_code& ec); template static typename std::enable_if::value, bool>::type parse_dec(Iter it, Iter last, T& v) { if(it == last) return false; T tmp = 0; do { if((! is_digit(*it)) || tmp > (std::numeric_limits::max)() / 10) return false; tmp *= 10; T const d = *it - '0'; if((std::numeric_limits::max)() - tmp < d) return false; tmp += d; } while(++it != last); v = tmp; return true; } template static typename std::enable_if::value, bool>::type parse_hex(Iter& it, T& v) { unsigned char d; if(! unhex(d, *it)) return false; T tmp = 0; do { if(tmp > (std::numeric_limits::max)() / 16) return false; tmp *= 16; if((std::numeric_limits::max)() - tmp < d) return false; tmp += d; } while(unhex(d, *++it)); v = tmp; return true; } BOOST_BEAST_DECL static bool parse_crlf(char const*& it); BOOST_BEAST_DECL static void parse_method( char const*& it, char const* last, string_view& result, error_code& ec); BOOST_BEAST_DECL static void parse_target( char const*& it, char const* last, string_view& result, error_code& ec); BOOST_BEAST_DECL static void parse_version( char const*& it, char const* last, int& result, error_code& ec); BOOST_BEAST_DECL static void parse_status( char const*& it, char const* last, unsigned short& result, error_code& ec); BOOST_BEAST_DECL static void parse_reason( char const*& it, char const* last, string_view& result, error_code& ec); BOOST_BEAST_DECL static void parse_field( char const*& p, char const* last, string_view& name, string_view& value, static_string& buf, error_code& ec); BOOST_BEAST_DECL static void parse_chunk_extensions( char const*& it, char const* last, error_code& ec); }; } // detail } // http } // beast } // boost #ifdef BOOST_BEAST_HEADER_ONLY #include #endif #endif