Added thirdparty: boost library

This commit is contained in:
Viacheslav Demydiuk
2024-01-06 19:55:56 +02:00
parent bf49f439e1
commit bccd1e7051
15683 changed files with 3239840 additions and 0 deletions
+197
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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