mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-15 11:48:09 +00:00
Added thirdparty: boost library
This commit is contained in:
+197
@@ -0,0 +1,197 @@
|
||||
//
|
||||
// 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_PARSED_LIST_HPP
|
||||
#define BOOST_BEAST_HTTP_DETAIL_BASIC_PARSED_LIST_HPP
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
/** A list parser which presents the sequence as a container.
|
||||
*/
|
||||
template<class Policy>
|
||||
class basic_parsed_list
|
||||
{
|
||||
string_view s_;
|
||||
|
||||
public:
|
||||
/// The type of policy this list uses for parsing.
|
||||
using policy_type = Policy;
|
||||
|
||||
/// The type of each element in the list.
|
||||
using value_type = typename Policy::value_type;
|
||||
|
||||
/// A constant iterator to a list element.
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
using const_iterator = __implementation_defined__;
|
||||
#else
|
||||
class const_iterator;
|
||||
#endif
|
||||
|
||||
class const_iterator
|
||||
: private boost::empty_value<Policy>
|
||||
{
|
||||
basic_parsed_list const* list_ = nullptr;
|
||||
char const* it_ = nullptr;
|
||||
typename Policy::value_type v_;
|
||||
bool error_ = false;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename Policy::value_type;
|
||||
using reference = value_type const&;
|
||||
using pointer = value_type const*;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::forward_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
|
||||
bool
|
||||
operator==(
|
||||
const_iterator const& other) const
|
||||
{
|
||||
return
|
||||
other.list_ == list_ &&
|
||||
other.it_ == it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
const_iterator const& other) const
|
||||
{
|
||||
return ! (*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return v_;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool
|
||||
error() const
|
||||
{
|
||||
return error_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class basic_parsed_list;
|
||||
|
||||
const_iterator(
|
||||
basic_parsed_list const& list, bool at_end)
|
||||
: list_(&list)
|
||||
, it_(at_end ? nullptr :
|
||||
list.s_.data())
|
||||
{
|
||||
if(! at_end)
|
||||
increment();
|
||||
}
|
||||
|
||||
void
|
||||
increment()
|
||||
{
|
||||
if(! this->get()(
|
||||
v_, it_, list_->s_))
|
||||
{
|
||||
it_ = nullptr;
|
||||
error_ = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Construct a list from a string
|
||||
explicit
|
||||
basic_parsed_list(string_view s)
|
||||
: s_(s)
|
||||
{
|
||||
}
|
||||
|
||||
/// Return a const iterator to the beginning of the list
|
||||
const_iterator begin() const;
|
||||
|
||||
/// Return a const iterator to the end of the list
|
||||
const_iterator end() const;
|
||||
|
||||
/// Return a const iterator to the beginning of the list
|
||||
const_iterator cbegin() const;
|
||||
|
||||
/// Return a const iterator to the end of the list
|
||||
const_iterator cend() const;
|
||||
};
|
||||
|
||||
template<class Policy>
|
||||
inline
|
||||
auto
|
||||
basic_parsed_list<Policy>::
|
||||
begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, false};
|
||||
}
|
||||
|
||||
template<class Policy>
|
||||
inline
|
||||
auto
|
||||
basic_parsed_list<Policy>::
|
||||
end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, true};
|
||||
}
|
||||
|
||||
template<class Policy>
|
||||
inline
|
||||
auto
|
||||
basic_parsed_list<Policy>::
|
||||
cbegin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, false};
|
||||
}
|
||||
|
||||
template<class Policy>
|
||||
inline
|
||||
auto
|
||||
basic_parsed_list<Policy>::
|
||||
cend() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, true};
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
//
|
||||
// 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 <boost/beast/core/string.hpp>
|
||||
#include <boost/beast/core/detail/char_buffer.hpp>
|
||||
#include <boost/beast/http/error.hpp>
|
||||
#include <boost/beast/http/detail/rfc7230.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/version.hpp>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
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;
|
||||
|
||||
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<unsigned char>(c-'0') < 10;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
is_print(char c)
|
||||
{
|
||||
return static_cast<unsigned char>(c-32) < 95;
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
char const*
|
||||
trim_front(char const* it, char const* end);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
char const*
|
||||
trim_back(
|
||||
char const* it, char const* first);
|
||||
|
||||
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<char const*, bool>
|
||||
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);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
bool
|
||||
parse_dec(string_view s, std::uint64_t& v);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
bool
|
||||
parse_hex(char const*& it, std::uint64_t& v);
|
||||
|
||||
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,
|
||||
beast::detail::char_buffer<max_obs_fold>& 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 <boost/beast/http/detail/basic_parser.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+849
@@ -0,0 +1,849 @@
|
||||
//
|
||||
// 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_IPP
|
||||
#define BOOST_BEAST_HTTP_DETAIL_BASIC_PARSER_IPP
|
||||
|
||||
#include <boost/beast/http/detail/basic_parser.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
char const*
|
||||
basic_parser_base::
|
||||
trim_front(char const* it, char const* end)
|
||||
{
|
||||
while(it != end)
|
||||
{
|
||||
if(*it != ' ' && *it != '\t')
|
||||
break;
|
||||
++it;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
char const*
|
||||
basic_parser_base::
|
||||
trim_back(
|
||||
char const* it, char const* first)
|
||||
{
|
||||
while(it != first)
|
||||
{
|
||||
auto const c = it[-1];
|
||||
if(c != ' ' && c != '\t')
|
||||
break;
|
||||
--it;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
bool
|
||||
basic_parser_base::
|
||||
is_pathchar(char c)
|
||||
{
|
||||
// VFALCO This looks the same as the one below...
|
||||
|
||||
// TEXT = <any OCTET except CTLs, and excluding LWS>
|
||||
static bool constexpr tab[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
|
||||
};
|
||||
return tab[static_cast<unsigned char>(c)];
|
||||
}
|
||||
|
||||
bool
|
||||
basic_parser_base::
|
||||
unhex(unsigned char& d, char c)
|
||||
{
|
||||
static signed char constexpr tab[256] = {
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 0
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 16
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 32
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, // 48
|
||||
-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 64
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 80
|
||||
-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 96
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 112
|
||||
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 128
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 144
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 160
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 176
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 192
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 208
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 224
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 240
|
||||
};
|
||||
d = static_cast<unsigned char>(
|
||||
tab[static_cast<unsigned char>(c)]);
|
||||
return d != static_cast<unsigned char>(-1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
std::pair<char const*, bool>
|
||||
basic_parser_base::
|
||||
find_fast(
|
||||
char const* buf,
|
||||
char const* buf_end,
|
||||
char const* ranges,
|
||||
size_t ranges_size)
|
||||
{
|
||||
bool found = false;
|
||||
boost::ignore_unused(buf_end, ranges, ranges_size);
|
||||
return {buf, found};
|
||||
}
|
||||
|
||||
// VFALCO Can SIMD help this?
|
||||
char const*
|
||||
basic_parser_base::
|
||||
find_eol(
|
||||
char const* it, char const* last,
|
||||
error_code& ec)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(it == last)
|
||||
{
|
||||
ec = {};
|
||||
return nullptr;
|
||||
}
|
||||
if(*it == '\r')
|
||||
{
|
||||
if(++it == last)
|
||||
{
|
||||
ec = {};
|
||||
return nullptr;
|
||||
}
|
||||
if(*it != '\n')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_line_ending);
|
||||
return nullptr;
|
||||
}
|
||||
ec = {};
|
||||
return ++it;
|
||||
}
|
||||
// VFALCO Should we handle the legacy case
|
||||
// for lines terminated with a single '\n'?
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
basic_parser_base::
|
||||
parse_dec(
|
||||
string_view s,
|
||||
std::uint64_t& v)
|
||||
{
|
||||
char const* it = s.data();
|
||||
char const* last = it + s.size();
|
||||
if(it == last)
|
||||
return false;
|
||||
std::uint64_t tmp = 0;
|
||||
do
|
||||
{
|
||||
if((! is_digit(*it)) ||
|
||||
tmp > (std::numeric_limits<std::uint64_t>::max)() / 10)
|
||||
return false;
|
||||
tmp *= 10;
|
||||
std::uint64_t const d = *it - '0';
|
||||
if((std::numeric_limits<std::uint64_t>::max)() - tmp < d)
|
||||
return false;
|
||||
tmp += d;
|
||||
}
|
||||
while(++it != last);
|
||||
v = tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
basic_parser_base::
|
||||
parse_hex(char const*& it, std::uint64_t& v)
|
||||
{
|
||||
unsigned char d;
|
||||
if(! unhex(d, *it))
|
||||
return false;
|
||||
std::uint64_t tmp = 0;
|
||||
do
|
||||
{
|
||||
if(tmp > (std::numeric_limits<std::uint64_t>::max)() / 16)
|
||||
return false;
|
||||
tmp *= 16;
|
||||
if((std::numeric_limits<std::uint64_t>::max)() - tmp < d)
|
||||
return false;
|
||||
tmp += d;
|
||||
}
|
||||
while(unhex(d, *++it));
|
||||
v = tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
char const*
|
||||
basic_parser_base::
|
||||
find_eom(char const* p, char const* last)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(p + 4 > last)
|
||||
return nullptr;
|
||||
if(p[3] != '\n')
|
||||
{
|
||||
if(p[3] == '\r')
|
||||
++p;
|
||||
else
|
||||
p += 4;
|
||||
}
|
||||
else if(p[2] != '\r')
|
||||
{
|
||||
p += 4;
|
||||
}
|
||||
else if(p[1] != '\n')
|
||||
{
|
||||
p += 2;
|
||||
}
|
||||
else if(p[0] != '\r')
|
||||
{
|
||||
p += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return p + 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
char const*
|
||||
basic_parser_base::
|
||||
parse_token_to_eol(
|
||||
char const* p,
|
||||
char const* last,
|
||||
char const*& token_last,
|
||||
error_code& ec)
|
||||
{
|
||||
for(;; ++p)
|
||||
{
|
||||
if(p >= last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return p;
|
||||
}
|
||||
if(BOOST_UNLIKELY(! is_print(*p)))
|
||||
if((BOOST_LIKELY(static_cast<
|
||||
unsigned char>(*p) < '\040') &&
|
||||
BOOST_LIKELY(*p != 9)) ||
|
||||
BOOST_UNLIKELY(*p == 127))
|
||||
goto found_control;
|
||||
}
|
||||
found_control:
|
||||
if(BOOST_LIKELY(*p == '\r'))
|
||||
{
|
||||
if(++p >= last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return last;
|
||||
}
|
||||
if(*p++ != '\n')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_line_ending);
|
||||
return last;
|
||||
}
|
||||
token_last = p - 2;
|
||||
}
|
||||
#if 0
|
||||
// VFALCO This allows `\n` by itself
|
||||
// to terminate a line
|
||||
else if(*p == '\n')
|
||||
{
|
||||
token_last = p;
|
||||
++p;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
// invalid character
|
||||
return nullptr;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
bool
|
||||
basic_parser_base::
|
||||
parse_crlf(char const*& it)
|
||||
{
|
||||
if( it[0] != '\r' || it[1] != '\n')
|
||||
return false;
|
||||
it += 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
basic_parser_base::
|
||||
parse_method(
|
||||
char const*& it, char const* last,
|
||||
string_view& result, error_code& ec)
|
||||
{
|
||||
// parse token SP
|
||||
auto const first = it;
|
||||
for(;; ++it)
|
||||
{
|
||||
if(it + 1 > last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(! detail::is_token_char(*it))
|
||||
break;
|
||||
}
|
||||
if(it + 1 > last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(*it != ' ')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_method);
|
||||
return;
|
||||
}
|
||||
if(it == first)
|
||||
{
|
||||
// cannot be empty
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_method);
|
||||
return;
|
||||
}
|
||||
result = make_string(first, it++);
|
||||
}
|
||||
|
||||
void
|
||||
basic_parser_base::
|
||||
parse_target(
|
||||
char const*& it, char const* last,
|
||||
string_view& result, error_code& ec)
|
||||
{
|
||||
// parse target SP
|
||||
auto const first = it;
|
||||
for(;; ++it)
|
||||
{
|
||||
if(it + 1 > last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(! is_pathchar(*it))
|
||||
break;
|
||||
}
|
||||
if(it + 1 > last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(*it != ' ')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_target);
|
||||
return;
|
||||
}
|
||||
if(it == first)
|
||||
{
|
||||
// cannot be empty
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_target);
|
||||
return;
|
||||
}
|
||||
result = make_string(first, it++);
|
||||
}
|
||||
|
||||
void
|
||||
basic_parser_base::
|
||||
parse_version(
|
||||
char const*& it, char const* last,
|
||||
int& result, error_code& ec)
|
||||
{
|
||||
if(it + 8 > last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(*it++ != 'H')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_version);
|
||||
return;
|
||||
}
|
||||
if(*it++ != 'T')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_version);
|
||||
return;
|
||||
}
|
||||
if(*it++ != 'T')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_version);
|
||||
return;
|
||||
}
|
||||
if(*it++ != 'P')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_version);
|
||||
return;
|
||||
}
|
||||
if(*it++ != '/')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_version);
|
||||
return;
|
||||
}
|
||||
if(! is_digit(*it))
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_version);
|
||||
return;
|
||||
}
|
||||
result = 10 * (*it++ - '0');
|
||||
if(*it++ != '.')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_version);
|
||||
return;
|
||||
}
|
||||
if(! is_digit(*it))
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_version);
|
||||
return;
|
||||
}
|
||||
result += *it++ - '0';
|
||||
}
|
||||
|
||||
void
|
||||
basic_parser_base::
|
||||
parse_status(
|
||||
char const*& it, char const* last,
|
||||
unsigned short& result, error_code& ec)
|
||||
{
|
||||
// parse 3(digit) SP
|
||||
if(it + 4 > last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(! is_digit(*it))
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_status);
|
||||
return;
|
||||
}
|
||||
result = 100 * (*it++ - '0');
|
||||
if(! is_digit(*it))
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_status);
|
||||
return;
|
||||
}
|
||||
result += 10 * (*it++ - '0');
|
||||
if(! is_digit(*it))
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_status);
|
||||
return;
|
||||
}
|
||||
result += *it++ - '0';
|
||||
if(*it++ != ' ')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
basic_parser_base::
|
||||
parse_reason(
|
||||
char const*& it, char const* last,
|
||||
string_view& result, error_code& ec)
|
||||
{
|
||||
auto const first = it;
|
||||
char const* token_last = nullptr;
|
||||
auto p = parse_token_to_eol(
|
||||
it, last, token_last, ec);
|
||||
if(ec)
|
||||
return;
|
||||
if(! p)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_reason);
|
||||
return;
|
||||
}
|
||||
result = make_string(first, token_last);
|
||||
it = p;
|
||||
}
|
||||
|
||||
void
|
||||
basic_parser_base::
|
||||
parse_field(
|
||||
char const*& p,
|
||||
char const* last,
|
||||
string_view& name,
|
||||
string_view& value,
|
||||
beast::detail::char_buffer<max_obs_fold>& buf,
|
||||
error_code& ec)
|
||||
{
|
||||
/* header-field = field-name ":" OWS field-value OWS
|
||||
|
||||
field-name = token
|
||||
field-value = *( field-content / obs-fold )
|
||||
field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||
field-vchar = VCHAR / obs-text
|
||||
|
||||
obs-fold = CRLF 1*( SP / HTAB )
|
||||
; obsolete line folding
|
||||
; see Section 3.2.4
|
||||
|
||||
token = 1*<any CHAR except CTLs or separators>
|
||||
CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
sep = "(" | ")" | "<" | ">" | "@"
|
||||
| "," | ";" | ":" | "\" | <">
|
||||
| "/" | "[" | "]" | "?" | "="
|
||||
| "{" | "}" | SP | HT
|
||||
*/
|
||||
static char const* is_token =
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0"
|
||||
"\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1"
|
||||
"\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
|
||||
// name
|
||||
BOOST_ALIGNMENT(16) static const char ranges1[] =
|
||||
"\x00 " /* control chars and up to SP */
|
||||
"\"\"" /* 0x22 */
|
||||
"()" /* 0x28,0x29 */
|
||||
",," /* 0x2c */
|
||||
"//" /* 0x2f */
|
||||
":@" /* 0x3a-0x40 */
|
||||
"[]" /* 0x5b-0x5d */
|
||||
"{\377"; /* 0x7b-0xff */
|
||||
auto first = p;
|
||||
bool found;
|
||||
std::tie(p, found) = find_fast(
|
||||
p, last, ranges1, sizeof(ranges1)-1);
|
||||
if(! found && p >= last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
if(*p == ':')
|
||||
break;
|
||||
if(! is_token[static_cast<
|
||||
unsigned char>(*p)])
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_field);
|
||||
return;
|
||||
}
|
||||
++p;
|
||||
if(p >= last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(p == first)
|
||||
{
|
||||
// empty name
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_field);
|
||||
return;
|
||||
}
|
||||
name = make_string(first, p);
|
||||
++p; // eat ':'
|
||||
char const* token_last = nullptr;
|
||||
for(;;)
|
||||
{
|
||||
// eat leading ' ' and '\t'
|
||||
for(;;++p)
|
||||
{
|
||||
if(p + 1 > last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(! (*p == ' ' || *p == '\t'))
|
||||
break;
|
||||
}
|
||||
// parse to CRLF
|
||||
first = p;
|
||||
p = parse_token_to_eol(p, last, token_last, ec);
|
||||
if(ec)
|
||||
return;
|
||||
if(! p)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_value);
|
||||
return;
|
||||
}
|
||||
// Look 1 char past the CRLF to handle obs-fold.
|
||||
if(p + 1 > last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
token_last =
|
||||
trim_back(token_last, first);
|
||||
if(*p != ' ' && *p != '\t')
|
||||
{
|
||||
value = make_string(first, token_last);
|
||||
return;
|
||||
}
|
||||
++p;
|
||||
if(token_last != first)
|
||||
break;
|
||||
}
|
||||
buf.clear();
|
||||
if (!buf.try_append(first, token_last))
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::header_limit);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(! buf.empty());
|
||||
for(;;)
|
||||
{
|
||||
// eat leading ' ' and '\t'
|
||||
for(;;++p)
|
||||
{
|
||||
if(p + 1 > last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(! (*p == ' ' || *p == '\t'))
|
||||
break;
|
||||
}
|
||||
// parse to CRLF
|
||||
first = p;
|
||||
p = parse_token_to_eol(p, last, token_last, ec);
|
||||
if(ec)
|
||||
return;
|
||||
if(! p)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_value);
|
||||
return;
|
||||
}
|
||||
// Look 1 char past the CRLF to handle obs-fold.
|
||||
if(p + 1 > last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
token_last = trim_back(token_last, first);
|
||||
if(first != token_last)
|
||||
{
|
||||
if (!buf.try_push_back(' ') ||
|
||||
!buf.try_append(first, token_last))
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::header_limit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(*p != ' ' && *p != '\t')
|
||||
{
|
||||
value = {buf.data(), buf.size()};
|
||||
return;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
basic_parser_base::
|
||||
parse_chunk_extensions(
|
||||
char const*& it,
|
||||
char const* last,
|
||||
error_code& ec)
|
||||
{
|
||||
/*
|
||||
chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] )
|
||||
BWS = *( SP / HTAB ) ; "Bad White Space"
|
||||
chunk-ext-name = token
|
||||
chunk-ext-val = token / quoted-string
|
||||
token = 1*tchar
|
||||
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
|
||||
qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
|
||||
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
|
||||
obs-text = %x80-FF
|
||||
|
||||
https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4667
|
||||
*/
|
||||
loop:
|
||||
if(it == last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(*it != ' ' && *it != '\t' && *it != ';')
|
||||
return;
|
||||
// BWS
|
||||
if(*it == ' ' || *it == '\t')
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
++it;
|
||||
if(it == last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(*it != ' ' && *it != '\t')
|
||||
break;
|
||||
}
|
||||
}
|
||||
// ';'
|
||||
if(*it != ';')
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_chunk_extension);
|
||||
return;
|
||||
}
|
||||
semi:
|
||||
++it; // skip ';'
|
||||
// BWS
|
||||
for(;;)
|
||||
{
|
||||
if(it == last)
|
||||
{
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::need_more);
|
||||
return;
|
||||
}
|
||||
if(*it != ' ' && *it != '\t')
|
||||
break;
|
||||
++it;
|
||||
}
|
||||
// chunk-ext-name
|
||||
if(! detail::is_token_char(*it))
|
||||
{
|
||||
ec = error::bad_chunk_extension;
|
||||
return;
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
++it;
|
||||
if(it == last)
|
||||
{
|
||||
ec = error::need_more;
|
||||
return;
|
||||
}
|
||||
if(! detail::is_token_char(*it))
|
||||
break;
|
||||
}
|
||||
// BWS [ ";" / "=" ]
|
||||
{
|
||||
bool bws;
|
||||
if(*it == ' ' || *it == '\t')
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
++it;
|
||||
if(it == last)
|
||||
{
|
||||
ec = error::need_more;
|
||||
return;
|
||||
}
|
||||
if(*it != ' ' && *it != '\t')
|
||||
break;
|
||||
}
|
||||
bws = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bws = false;
|
||||
}
|
||||
if(*it == ';')
|
||||
goto semi;
|
||||
if(*it != '=')
|
||||
{
|
||||
if(bws)
|
||||
ec = error::bad_chunk_extension;
|
||||
return;
|
||||
}
|
||||
++it; // skip '='
|
||||
}
|
||||
// BWS
|
||||
for(;;)
|
||||
{
|
||||
if(it == last)
|
||||
{
|
||||
ec = error::need_more;
|
||||
return;
|
||||
}
|
||||
if(*it != ' ' && *it != '\t')
|
||||
break;
|
||||
++it;
|
||||
}
|
||||
// chunk-ext-val
|
||||
if(*it != '"')
|
||||
{
|
||||
// token
|
||||
if(! detail::is_token_char(*it))
|
||||
{
|
||||
ec = error::bad_chunk_extension;
|
||||
return;
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
++it;
|
||||
if(it == last)
|
||||
{
|
||||
ec = error::need_more;
|
||||
return;
|
||||
}
|
||||
if(! detail::is_token_char(*it))
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// quoted-string
|
||||
for(;;)
|
||||
{
|
||||
++it;
|
||||
if(it == last)
|
||||
{
|
||||
ec = error::need_more;
|
||||
return;
|
||||
}
|
||||
if(*it == '"')
|
||||
break;
|
||||
if(*it == '\\')
|
||||
{
|
||||
++it;
|
||||
if(it == last)
|
||||
{
|
||||
ec = error::need_more;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
//
|
||||
// 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_CHUNK_ENCODE_HPP
|
||||
#define BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
|
||||
|
||||
#include <boost/beast/http/type_traits.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
struct chunk_extensions
|
||||
{
|
||||
virtual ~chunk_extensions() = default;
|
||||
virtual net::const_buffer str() = 0;
|
||||
};
|
||||
|
||||
template<class ChunkExtensions>
|
||||
struct chunk_extensions_impl : chunk_extensions
|
||||
{
|
||||
ChunkExtensions ext_;
|
||||
|
||||
chunk_extensions_impl(ChunkExtensions&& ext) noexcept
|
||||
: ext_(std::move(ext))
|
||||
{
|
||||
}
|
||||
|
||||
chunk_extensions_impl(ChunkExtensions const& ext)
|
||||
: ext_(ext)
|
||||
{
|
||||
}
|
||||
|
||||
net::const_buffer
|
||||
str() override
|
||||
{
|
||||
auto const s = ext_.str();
|
||||
return {s.data(), s.size()};
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_chunk_extensions : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_chunk_extensions<T, beast::detail::void_t<decltype(
|
||||
std::declval<string_view&>() = std::declval<T&>().str()
|
||||
)>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A buffer sequence containing a chunk-encoding header
|
||||
*/
|
||||
class chunk_size
|
||||
{
|
||||
template<class OutIter>
|
||||
static
|
||||
OutIter
|
||||
to_hex(OutIter last, std::size_t n)
|
||||
{
|
||||
if(n == 0)
|
||||
{
|
||||
*--last = '0';
|
||||
return last;
|
||||
}
|
||||
while(n)
|
||||
{
|
||||
*--last = "0123456789abcdef"[n&0xf];
|
||||
n>>=4;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
struct sequence
|
||||
{
|
||||
net::const_buffer b;
|
||||
char data[1 + 2 * sizeof(std::size_t)];
|
||||
|
||||
explicit
|
||||
sequence(std::size_t n)
|
||||
{
|
||||
char* it0 = data + sizeof(data);
|
||||
auto it = to_hex(it0, n);
|
||||
b = {it,
|
||||
static_cast<std::size_t>(it0 - it)};
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<sequence> sp_;
|
||||
|
||||
public:
|
||||
using value_type = net::const_buffer;
|
||||
|
||||
using const_iterator = value_type const*;
|
||||
|
||||
chunk_size(chunk_size const& other) = default;
|
||||
|
||||
/** Construct a chunk header
|
||||
|
||||
@param n The number of octets in this chunk.
|
||||
*/
|
||||
chunk_size(std::size_t n)
|
||||
: sp_(std::make_shared<sequence>(n))
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return &sp_->b;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return begin() + 1;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// Returns a buffer sequence holding a CRLF for chunk encoding
|
||||
inline
|
||||
net::const_buffer const&
|
||||
chunk_crlf()
|
||||
{
|
||||
static net::const_buffer const cb{"\r\n", 2};
|
||||
return cb;
|
||||
}
|
||||
|
||||
/// Returns a buffer sequence holding a final chunk header
|
||||
inline
|
||||
net::const_buffer const&
|
||||
chunk_last()
|
||||
{
|
||||
static net::const_buffer const cb{"0\r\n", 3};
|
||||
return cb;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
template<class = void>
|
||||
struct chunk_crlf_iter_type
|
||||
{
|
||||
class value_type
|
||||
{
|
||||
char const s[2] = {'\r', '\n'};
|
||||
|
||||
public:
|
||||
value_type() = default;
|
||||
|
||||
operator
|
||||
net::const_buffer() const
|
||||
{
|
||||
return {s, sizeof(s)};
|
||||
}
|
||||
};
|
||||
static value_type value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
typename chunk_crlf_iter_type<T>::value_type
|
||||
chunk_crlf_iter_type<T>::value;
|
||||
|
||||
using chunk_crlf_iter = chunk_crlf_iter_type<void>;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct chunk_size0
|
||||
{
|
||||
using value_type = net::const_buffer;
|
||||
using const_iterator = value_type const*;
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return &chunk_last();
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return begin() + 1;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T,
|
||||
bool = is_fields<T>::value>
|
||||
struct buffers_or_fields
|
||||
{
|
||||
using type = typename
|
||||
T::writer::const_buffers_type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct buffers_or_fields<T, false>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// 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_RFC7230_HPP
|
||||
#define BOOST_BEAST_HTTP_DETAIL_RFC7230_HPP
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
is_digit(char c);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
char
|
||||
is_alpha(char c);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
char
|
||||
is_text(char c);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
char
|
||||
is_token_char(char c);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
char
|
||||
is_qdchar(char c);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
char
|
||||
is_qpchar(char c);
|
||||
|
||||
|
||||
// converts to lower case,
|
||||
// returns 0 if not a valid text char
|
||||
//
|
||||
BOOST_BEAST_DECL
|
||||
char
|
||||
to_value_char(char c);
|
||||
|
||||
// VFALCO TODO Make this return unsigned?
|
||||
BOOST_BEAST_DECL
|
||||
std::int8_t
|
||||
unhex(char c);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
string_view
|
||||
trim(string_view s);
|
||||
|
||||
struct param_iter
|
||||
{
|
||||
using iter_type = string_view::const_iterator;
|
||||
|
||||
iter_type it;
|
||||
iter_type first;
|
||||
iter_type last;
|
||||
std::pair<string_view, string_view> v;
|
||||
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return first == it;
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
increment();
|
||||
};
|
||||
|
||||
/*
|
||||
#token = [ ( "," / token ) *( OWS "," [ OWS token ] ) ]
|
||||
*/
|
||||
struct opt_token_list_policy
|
||||
{
|
||||
using value_type = string_view;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
operator()(value_type& v,
|
||||
char const*& it, string_view s) const;
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/beast/http/detail/rfc7230.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+390
@@ -0,0 +1,390 @@
|
||||
//
|
||||
// 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_RFC7230_IPP
|
||||
#define BOOST_BEAST_HTTP_DETAIL_RFC7230_IPP
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
bool
|
||||
is_digit(char c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
char
|
||||
is_alpha(char c)
|
||||
{
|
||||
static char constexpr tab[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 80
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 112
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240
|
||||
};
|
||||
BOOST_STATIC_ASSERT(sizeof(tab) == 256);
|
||||
return tab[static_cast<unsigned char>(c)];
|
||||
}
|
||||
|
||||
char
|
||||
is_text(char c)
|
||||
{
|
||||
// TEXT = <any OCTET except CTLs, but including LWS>
|
||||
static char constexpr tab[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
|
||||
};
|
||||
BOOST_STATIC_ASSERT(sizeof(tab) == 256);
|
||||
return tab[static_cast<unsigned char>(c)];
|
||||
}
|
||||
|
||||
char
|
||||
is_token_char(char c)
|
||||
{
|
||||
/*
|
||||
tchar = "!" | "#" | "$" | "%" | "&" |
|
||||
"'" | "*" | "+" | "-" | "." |
|
||||
"^" | "_" | "`" | "|" | "~" |
|
||||
DIGIT | ALPHA
|
||||
*/
|
||||
static char constexpr tab[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||
0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240
|
||||
};
|
||||
BOOST_STATIC_ASSERT(sizeof(tab) == 256);
|
||||
return tab[static_cast<unsigned char>(c)];
|
||||
}
|
||||
|
||||
char
|
||||
is_qdchar(char c)
|
||||
{
|
||||
/*
|
||||
qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
|
||||
*/
|
||||
static char constexpr tab[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||
1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 80
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
|
||||
};
|
||||
BOOST_STATIC_ASSERT(sizeof(tab) == 256);
|
||||
return tab[static_cast<unsigned char>(c)];
|
||||
}
|
||||
|
||||
char
|
||||
is_qpchar(char c)
|
||||
{
|
||||
/*
|
||||
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
|
||||
obs-text = %x80-FF
|
||||
*/
|
||||
static char constexpr tab[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
|
||||
};
|
||||
BOOST_STATIC_ASSERT(sizeof(tab) == 256);
|
||||
return tab[static_cast<unsigned char>(c)];
|
||||
}
|
||||
|
||||
// converts to lower case,
|
||||
// returns 0 if not a valid text char
|
||||
//
|
||||
char
|
||||
to_value_char(char c)
|
||||
{
|
||||
// TEXT = <any OCTET except CTLs, but including LWS>
|
||||
static unsigned char constexpr tab[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 32
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 48
|
||||
64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 64
|
||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, // 80
|
||||
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 96
|
||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 0, // 112
|
||||
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 128
|
||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 144
|
||||
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // 160
|
||||
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // 176
|
||||
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, // 192
|
||||
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, // 208
|
||||
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // 224
|
||||
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // 240
|
||||
};
|
||||
BOOST_STATIC_ASSERT(sizeof(tab) == 256);
|
||||
return static_cast<char>(tab[static_cast<unsigned char>(c)]);
|
||||
}
|
||||
|
||||
// VFALCO TODO Make this return unsigned?
|
||||
std::int8_t
|
||||
unhex(char c)
|
||||
{
|
||||
static signed char constexpr tab[] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 112
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240
|
||||
};
|
||||
BOOST_STATIC_ASSERT(sizeof(tab) == 256);
|
||||
return tab[static_cast<unsigned char>(c)];
|
||||
}
|
||||
|
||||
template <class ForwardIt>
|
||||
void
|
||||
skip_ows(ForwardIt& it, ForwardIt end)
|
||||
{
|
||||
while(it != end)
|
||||
{
|
||||
if(*it != ' ' && *it != '\t')
|
||||
break;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ForwardIt>
|
||||
void
|
||||
skip_token(ForwardIt& it, ForwardIt last)
|
||||
{
|
||||
while(it != last && is_token_char(*it))
|
||||
++it;
|
||||
}
|
||||
|
||||
string_view
|
||||
trim(string_view s)
|
||||
{
|
||||
auto first = s.begin();
|
||||
auto last = s.end();
|
||||
skip_ows(first, last);
|
||||
while(first != last)
|
||||
{
|
||||
auto const c = *std::prev(last);
|
||||
if(c != ' ' && c != '\t')
|
||||
break;
|
||||
--last;
|
||||
}
|
||||
if(first == last)
|
||||
return {};
|
||||
return {&*first,
|
||||
static_cast<std::size_t>(last - first)};
|
||||
}
|
||||
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
param_iter::
|
||||
increment()
|
||||
{
|
||||
/*
|
||||
param-list = *( OWS ";" OWS param )
|
||||
param = token OWS [ "=" OWS ( token / quoted-string ) ]
|
||||
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
|
||||
qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
|
||||
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
|
||||
obs-text = %x80-FF
|
||||
*/
|
||||
auto const err =
|
||||
[&]
|
||||
{
|
||||
it = first;
|
||||
};
|
||||
v.first = {};
|
||||
v.second = {};
|
||||
detail::skip_ows(it, last);
|
||||
first = it;
|
||||
if(it == last)
|
||||
return err();
|
||||
if(*it != ';')
|
||||
return err();
|
||||
++it;
|
||||
detail::skip_ows(it, last);
|
||||
if(it == last)
|
||||
return err();
|
||||
// param
|
||||
if(! detail::is_token_char(*it))
|
||||
return err();
|
||||
auto const p0 = it;
|
||||
skip_token(++it, last);
|
||||
auto const p1 = it;
|
||||
v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
|
||||
detail::skip_ows(it, last);
|
||||
if(it == last)
|
||||
return;
|
||||
if(*it == ';')
|
||||
return;
|
||||
if(*it != '=')
|
||||
return err();
|
||||
++it;
|
||||
detail::skip_ows(it, last);
|
||||
if(it == last)
|
||||
return;
|
||||
if(*it == '"')
|
||||
{
|
||||
// quoted-string
|
||||
auto const p2 = it;
|
||||
++it;
|
||||
for(;;)
|
||||
{
|
||||
if(it == last)
|
||||
return err();
|
||||
auto c = *it++;
|
||||
if(c == '"')
|
||||
break;
|
||||
if(detail::is_qdchar(c))
|
||||
continue;
|
||||
if(c != '\\')
|
||||
return err();
|
||||
if(it == last)
|
||||
return err();
|
||||
c = *it++;
|
||||
if(! detail::is_qpchar(c))
|
||||
return err();
|
||||
}
|
||||
v.second = { &*p2, static_cast<std::size_t>(it - p2) };
|
||||
}
|
||||
else
|
||||
{
|
||||
// token
|
||||
if(! detail::is_token_char(*it))
|
||||
return err();
|
||||
auto const p2 = it;
|
||||
skip_token(++it, last);
|
||||
v.second = { &*p2, static_cast<std::size_t>(it - p2) };
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
opt_token_list_policy::operator()(value_type& v,
|
||||
char const*& it, string_view s) const
|
||||
{
|
||||
v = {};
|
||||
auto need_comma = it != s.data();
|
||||
for(;;)
|
||||
{
|
||||
detail::skip_ows(it, (s.data() + s.size()));
|
||||
if(it == (s.data() + s.size()))
|
||||
{
|
||||
it = nullptr;
|
||||
return true;
|
||||
}
|
||||
auto const c = *it;
|
||||
if(detail::is_token_char(c))
|
||||
{
|
||||
if(need_comma)
|
||||
return false;
|
||||
auto const p0 = it;
|
||||
for(;;)
|
||||
{
|
||||
++it;
|
||||
if(it == (s.data() + s.size()))
|
||||
break;
|
||||
if(! detail::is_token_char(*it))
|
||||
break;
|
||||
}
|
||||
v = string_view{p0,
|
||||
static_cast<std::size_t>(it - p0)};
|
||||
return true;
|
||||
}
|
||||
if(c != ',')
|
||||
return false;
|
||||
need_comma = false;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_BEAST_HTTP_DETAIL_RFC7230_IPP
|
||||
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
//
|
||||
// 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_TYPE_TRAITS_HPP
|
||||
#define BOOST_BEAST_HTTP_DETAIL_TYPE_TRAITS_HPP
|
||||
|
||||
#include <boost/beast/core/detail/type_traits.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
template<bool isRequest, class Fields>
|
||||
class header;
|
||||
|
||||
template<bool, class, class>
|
||||
class message;
|
||||
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
class parser;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
class is_header_impl
|
||||
{
|
||||
template<bool b, class F>
|
||||
static std::true_type check(
|
||||
header<b, F> const*);
|
||||
static std::false_type check(...);
|
||||
public:
|
||||
using type = decltype(check((T*)0));
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using is_header = typename is_header_impl<T>::type;
|
||||
|
||||
template<class T>
|
||||
struct is_parser : std::false_type {};
|
||||
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
struct is_parser<parser<isRequest, Body, Fields>> : std::true_type {};
|
||||
|
||||
struct fields_model
|
||||
{
|
||||
struct writer;
|
||||
|
||||
string_view method() const;
|
||||
string_view reason() const;
|
||||
string_view target() const;
|
||||
|
||||
protected:
|
||||
string_view get_method_impl() const;
|
||||
string_view get_target_impl() const;
|
||||
string_view get_reason_impl() const;
|
||||
bool get_chunked_impl() const;
|
||||
bool get_keep_alive_impl(unsigned) const;
|
||||
bool has_content_length_impl() const;
|
||||
void set_method_impl(string_view);
|
||||
void set_target_impl(string_view);
|
||||
void set_reason_impl(string_view);
|
||||
void set_chunked_impl(bool);
|
||||
void set_content_length_impl(boost::optional<std::uint64_t>);
|
||||
void set_keep_alive_impl(unsigned, bool);
|
||||
};
|
||||
|
||||
template<class T, class = beast::detail::void_t<>>
|
||||
struct has_value_type : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct has_value_type<T, beast::detail::void_t<
|
||||
typename T::value_type
|
||||
> > : std::true_type {};
|
||||
|
||||
/** Determine if a <em>Body</em> type has a size
|
||||
|
||||
This metafunction is equivalent to `std::true_type` if
|
||||
Body contains a static member function called `size`.
|
||||
*/
|
||||
template<class T, class = void>
|
||||
struct is_body_sized : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_body_sized<T, beast::detail::void_t<
|
||||
typename T::value_type,
|
||||
decltype(
|
||||
std::declval<std::uint64_t&>() =
|
||||
T::size(std::declval<typename T::value_type const&>())
|
||||
)>> : std::true_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_fields_helper : T
|
||||
{
|
||||
template<class U = is_fields_helper>
|
||||
static auto f1(int) -> decltype(
|
||||
std::declval<string_view&>() = std::declval<U const&>().get_method_impl(),
|
||||
std::true_type());
|
||||
static auto f1(...) -> std::false_type;
|
||||
using t1 = decltype(f1(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f2(int) -> decltype(
|
||||
std::declval<string_view&>() = std::declval<U const&>().get_target_impl(),
|
||||
std::true_type());
|
||||
static auto f2(...) -> std::false_type;
|
||||
using t2 = decltype(f2(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f3(int) -> decltype(
|
||||
std::declval<string_view&>() = std::declval<U const&>().get_reason_impl(),
|
||||
std::true_type());
|
||||
static auto f3(...) -> std::false_type;
|
||||
using t3 = decltype(f3(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f4(int) -> decltype(
|
||||
std::declval<bool&>() = std::declval<U const&>().get_chunked_impl(),
|
||||
std::true_type());
|
||||
static auto f4(...) -> std::false_type;
|
||||
using t4 = decltype(f4(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f5(int) -> decltype(
|
||||
std::declval<bool&>() = std::declval<U const&>().get_keep_alive_impl(
|
||||
std::declval<unsigned>()),
|
||||
std::true_type());
|
||||
static auto f5(...) -> std::false_type;
|
||||
using t5 = decltype(f5(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f6(int) -> decltype(
|
||||
std::declval<bool&>() = std::declval<U const&>().has_content_length_impl(),
|
||||
std::true_type());
|
||||
static auto f6(...) -> std::false_type;
|
||||
using t6 = decltype(f6(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f7(int) -> decltype(
|
||||
void(std::declval<U&>().set_method_impl(std::declval<string_view>())),
|
||||
std::true_type());
|
||||
static auto f7(...) -> std::false_type;
|
||||
using t7 = decltype(f7(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f8(int) -> decltype(
|
||||
void(std::declval<U&>().set_target_impl(std::declval<string_view>())),
|
||||
std::true_type());
|
||||
static auto f8(...) -> std::false_type;
|
||||
using t8 = decltype(f8(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f9(int) -> decltype(
|
||||
void(std::declval<U&>().set_reason_impl(std::declval<string_view>())),
|
||||
std::true_type());
|
||||
static auto f9(...) -> std::false_type;
|
||||
using t9 = decltype(f9(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f10(int) -> decltype(
|
||||
void(std::declval<U&>().set_chunked_impl(std::declval<bool>())),
|
||||
std::true_type());
|
||||
static auto f10(...) -> std::false_type;
|
||||
using t10 = decltype(f10(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f11(int) -> decltype(
|
||||
void(std::declval<U&>().set_content_length_impl(
|
||||
std::declval<boost::optional<std::uint64_t>>())),
|
||||
std::true_type());
|
||||
static auto f11(...) -> std::false_type;
|
||||
using t11 = decltype(f11(0));
|
||||
|
||||
template<class U = is_fields_helper>
|
||||
static auto f12(int) -> decltype(
|
||||
void(std::declval<U&>().set_keep_alive_impl(
|
||||
std::declval<unsigned>(),
|
||||
std::declval<bool>())),
|
||||
std::true_type());
|
||||
static auto f12(...) -> std::false_type;
|
||||
using t12 = decltype(f12(0));
|
||||
|
||||
using type = std::integral_constant<bool,
|
||||
t1::value && t2::value && t3::value &&
|
||||
t4::value && t5::value && t6::value &&
|
||||
t7::value && t8::value && t9::value &&
|
||||
t10::value && t11::value && t12::value>;
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user