Optimize field lookups

This commit is contained in:
Vinnie Falco committed 2017-07-20 08:15:29 -07:00
1 parent 64ff766b23
commit 2d6859831c
5 files changed
+205 -295

No files matched your search

+45 -254
View File
@@ -211,6 +211,9 @@ public:
void
write_eof(error_code& ec);
void
check_header();
private:
Derived&
impl()
@@ -218,231 +221,6 @@ private:
return *static_cast<Derived*>(this);
}
template<class C>
class has_on_start_t
{
template<class T, class R =
decltype(std::declval<T>().on_start(), std::true_type{})>
static R check(int);
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
static bool const value = type::value;
};
template<class C>
using has_on_start =
std::integral_constant<bool, has_on_start_t<C>::value>;
void
call_on_start(std::true_type)
{
impl().on_start();
}
void
call_on_start(std::false_type)
{
}
template<class C>
class has_on_field_t
{
template<class T, class R =
decltype(std::declval<T>().on_field(
std::declval<std::string const&>(),
std::declval<std::string const&>()),
std::true_type{})>
static R check(int);
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
static bool const value = type::value;
};
template<class C>
using has_on_field =
std::integral_constant<bool, has_on_field_t<C>::value>;
void
call_on_field(std::string const& field,
std::string const& value, std::true_type)
{
impl().on_field(field, value);
}
void
call_on_field(std::string const&, std::string const&,
std::false_type)
{
}
template<class C>
class has_on_headers_complete_t
{
template<class T, class R =
decltype(std::declval<T>().on_headers_complete(
std::declval<error_code&>()), std::true_type{})>
static R check(int);
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
static bool const value = type::value;
};
template<class C>
using has_on_headers_complete =
std::integral_constant<bool, has_on_headers_complete_t<C>::value>;
void
call_on_headers_complete(error_code& ec, std::true_type)
{
impl().on_headers_complete(ec);
}
void
call_on_headers_complete(error_code&, std::false_type)
{
}
template<class C>
class has_on_request_t
{
template<class T, class R =
decltype(std::declval<T>().on_request(
std::declval<unsigned>(), std::declval<std::string>(),
std::declval<int>(), std::declval<int>(),
std::declval<bool>(), std::declval<bool>()),
std::true_type{})>
static R check(int);
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
static bool const value = type::value;
};
template<class C>
using has_on_request =
std::integral_constant<bool, has_on_request_t<C>::value>;
void
call_on_request(unsigned method, std::string url,
int major, int minor, bool keep_alive, bool upgrade,
std::true_type)
{
impl().on_request(
method, url, major, minor, keep_alive, upgrade);
}
void
call_on_request(unsigned, std::string, int, int, bool, bool,
std::false_type)
{
}
template<class C>
class has_on_response_t
{
template<class T, class R =
decltype(std::declval<T>().on_response(
std::declval<int>(), std::declval<std::string>,
std::declval<int>(), std::declval<int>(),
std::declval<bool>(), std::declval<bool>()),
std::true_type{})>
static R check(int);
template<class>
static std::false_type check(...);
#if 0
using type = decltype(check<C>(0));
#else
// VFALCO Trait seems broken for http::parser
using type = std::true_type;
#endif
public:
static bool const value = type::value;
};
template<class C>
using has_on_response =
std::integral_constant<bool, has_on_response_t<C>::value>;
bool
call_on_response(int status, std::string text,
int major, int minor, bool keep_alive, bool upgrade,
std::true_type)
{
return impl().on_response(
status, text, major, minor, keep_alive, upgrade);
}
bool
call_on_response(int, std::string, int, int, bool, bool,
std::false_type)
{
// VFALCO Certainly incorrect
return true;
}
template<class C>
class has_on_body_t
{
template<class T, class R =
decltype(std::declval<T>().on_body(
std::declval<void const*>(), std::declval<std::size_t>(),
std::declval<error_code&>()), std::true_type{})>
static R check(int);
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
static bool const value = type::value;
};
template<class C>
using has_on_body =
std::integral_constant<bool, has_on_body_t<C>::value>;
void
call_on_body(void const* data, std::size_t bytes,
error_code& ec, std::true_type)
{
impl().on_body(data, bytes, ec);
}
void
call_on_body(void const*, std::size_t,
error_code&, std::false_type)
{
}
template<class C>
class has_on_complete_t
{
template<class T, class R =
decltype(std::declval<T>().on_complete(), std::true_type{})>
static R check(int);
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
static bool const value = type::value;
};
template<class C>
using has_on_complete =
std::integral_constant<bool, has_on_complete_t<C>::value>;
void
call_on_complete(std::true_type)
{
impl().on_complete();
}
void
call_on_complete(std::false_type)
{
}
void
check_header();
static int cb_message_start(http_parser*);
static int cb_url(http_parser*, char const*, std::size_t);
static int cb_status(http_parser*, char const*, std::size_t);
@@ -526,7 +304,8 @@ nodejs_basic_parser(nodejs_basic_parser&& other)
template<class Derived>
auto
nodejs_basic_parser<Derived>::operator=(nodejs_basic_parser&& other) ->
nodejs_basic_parser<Derived>::
operator=(nodejs_basic_parser&& other) ->
nodejs_basic_parser&
{
state_ = other.state_;
@@ -569,7 +348,8 @@ operator=(nodejs_basic_parser const& other) ->
}
template<class Derived>
nodejs_basic_parser<Derived>::nodejs_basic_parser(bool request) noexcept
nodejs_basic_parser<Derived>::
nodejs_basic_parser(bool request) noexcept
{
state_.data = this;
http_parser_init(&state_, request
@@ -579,7 +359,8 @@ nodejs_basic_parser<Derived>::nodejs_basic_parser(bool request) noexcept
template<class Derived>
std::size_t
nodejs_basic_parser<Derived>::write(void const* data,
nodejs_basic_parser<Derived>::
write(void const* data,
std::size_t size, error_code& ec)
{
ec_ = &ec;
@@ -596,11 +377,11 @@ nodejs_basic_parser<Derived>::write(void const* data,
template<class Derived>
void
nodejs_basic_parser<Derived>::write_eof(error_code& ec)
nodejs_basic_parser<Derived>::
write_eof(error_code& ec)
{
ec_ = &ec;
http_parser_execute(
&state_, hooks(), nullptr, 0);
http_parser_execute(&state_, hooks(), nullptr, 0);
if(! ec)
ec = detail::make_nodejs_error(
static_cast<int>(state_.http_errno));
@@ -608,13 +389,12 @@ nodejs_basic_parser<Derived>::write_eof(error_code& ec)
template<class Derived>
void
nodejs_basic_parser<Derived>::check_header()
nodejs_basic_parser<Derived>::
check_header()
{
if(! value_.empty())
{
//detail::trim(value_);
call_on_field(field_, value_,
has_on_field<Derived>{});
impl().on_field(field_, value_);
field_.clear();
value_.clear();
}
@@ -622,7 +402,8 @@ nodejs_basic_parser<Derived>::check_header()
template<class Derived>
int
nodejs_basic_parser<Derived>::cb_message_start(http_parser* p)
nodejs_basic_parser<Derived>::
cb_message_start(http_parser* p)
{
auto& t = *reinterpret_cast<nodejs_basic_parser*>(p->data);
t.complete_ = false;
@@ -630,13 +411,14 @@ nodejs_basic_parser<Derived>::cb_message_start(http_parser* p)
t.status_.clear();
t.field_.clear();
t.value_.clear();
t.call_on_start(has_on_start<Derived>{});
t.impl().on_start();
return 0;
}
template<class Derived>
int
nodejs_basic_parser<Derived>::cb_url(http_parser* p,
nodejs_basic_parser<Derived>::
cb_url(http_parser* p,
char const* in, std::size_t bytes)
{
auto& t = *reinterpret_cast<nodejs_basic_parser*>(p->data);
@@ -646,7 +428,8 @@ nodejs_basic_parser<Derived>::cb_url(http_parser* p,
template<class Derived>
int
nodejs_basic_parser<Derived>::cb_status(http_parser* p,
nodejs_basic_parser<Derived>::
cb_status(http_parser* p,
char const* in, std::size_t bytes)
{
auto& t = *reinterpret_cast<nodejs_basic_parser*>(p->data);
@@ -656,7 +439,8 @@ nodejs_basic_parser<Derived>::cb_status(http_parser* p,
template<class Derived>
int
nodejs_basic_parser<Derived>::cb_header_field(http_parser* p,
nodejs_basic_parser<Derived>::
cb_header_field(http_parser* p,
char const* in, std::size_t bytes)
{
auto& t = *reinterpret_cast<nodejs_basic_parser*>(p->data);
@@ -667,7 +451,8 @@ nodejs_basic_parser<Derived>::cb_header_field(http_parser* p,
template<class Derived>
int
nodejs_basic_parser<Derived>::cb_header_value(http_parser* p,
nodejs_basic_parser<Derived>::
cb_header_value(http_parser* p,
char const* in, std::size_t bytes)
{
auto& t = *reinterpret_cast<nodejs_basic_parser*>(p->data);
@@ -677,62 +462,68 @@ nodejs_basic_parser<Derived>::cb_header_value(http_parser* p,
template<class Derived>
int
nodejs_basic_parser<Derived>::cb_headers_complete(http_parser* p)
nodejs_basic_parser<Derived>::
cb_headers_complete(http_parser* p)
{
auto& t = *reinterpret_cast<nodejs_basic_parser*>(p->data);
t.check_header();
t.call_on_headers_complete(*t.ec_,
has_on_headers_complete<Derived>{});
t.impl().on_headers_complete(*t.ec_);
if(*t.ec_)
return 1;
bool const keep_alive =
http_should_keep_alive(p) != 0;
if(p->type == http_parser_type::HTTP_REQUEST)
{
t.call_on_request(p->method, t.url_,
t.impl().on_request(p->method, t.url_,
p->http_major, p->http_minor, keep_alive,
p->upgrade, has_on_request<Derived>{});
p->upgrade);
return 0;
}
return t.call_on_response(p->status_code, t.status_,
return t.impl().on_response(p->status_code, t.status_,
p->http_major, p->http_minor, keep_alive,
p->upgrade, has_on_response<Derived>{}) ? 0 : 1;
p->upgrade) ? 0 : 1;
}
template<class Derived>
int
nodejs_basic_parser<Derived>::cb_body(http_parser* p,
nodejs_basic_parser<Derived>::
cb_body(http_parser* p,
char const* in, std::size_t bytes)
{
auto& t = *reinterpret_cast<nodejs_basic_parser*>(p->data);
t.call_on_body(in, bytes, *t.ec_, has_on_body<Derived>{});
t.impl().on_body(in, bytes, *t.ec_);
return *t.ec_ ? 1 : 0;
}
template<class Derived>
int
nodejs_basic_parser<Derived>::cb_message_complete(http_parser* p)
nodejs_basic_parser<Derived>::
cb_message_complete(http_parser* p)
{
auto& t = *reinterpret_cast<nodejs_basic_parser*>(p->data);
t.complete_ = true;
t.call_on_complete(has_on_complete<Derived>{});
t.impl().on_complete();
return 0;
}
template<class Derived>
int
nodejs_basic_parser<Derived>::cb_chunk_header(http_parser*)
nodejs_basic_parser<Derived>::
cb_chunk_header(http_parser*)
{
return 0;
}
template<class Derived>
int
nodejs_basic_parser<Derived>::cb_chunk_complete(http_parser*)
nodejs_basic_parser<Derived>::
cb_chunk_complete(http_parser*)
{
return 0;
}
//------------------------------------------------------------------------------
/** A HTTP parser.
The parser may only be used once.