Skip to content

Commit

Permalink
src: refactor callback #defines into C++ templates
Browse files Browse the repository at this point in the history
Use template helpers instead of `#define`s to generate
the raw C callbacks that are passed to the HTTP parser library.

A nice effect of this is that it is more obvious what
parameters the `Parser` methods take.

PR-URL: nodejs#18133
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Jon Moss <[email protected]>
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Joyee Cheung <[email protected]>
Reviewed-By: Franziska Hinkelmann <[email protected]>
  • Loading branch information
addaleax authored and MayaLekova committed May 8, 2018
1 parent 1ce221b commit 15e75dc
Showing 1 changed file with 31 additions and 33 deletions.
64 changes: 31 additions & 33 deletions src/node_http_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,6 @@ const uint32_t kOnMessageComplete = 3;
const uint32_t kOnExecute = 4;


#define HTTP_CB(name) \
static int name(http_parser* p_) { \
Parser* self = ContainerOf(&Parser::parser_, p_); \
return self->name##_(); \
} \
int name##_()


#define HTTP_DATA_CB(name) \
static int name(http_parser* p_, const char* at, size_t length) { \
Parser* self = ContainerOf(&Parser::parser_, p_); \
return self->name##_(at, length); \
} \
int name##_(const char* at, size_t length)


// helper class for the Parser
struct StringPtr {
StringPtr() {
Expand Down Expand Up @@ -182,27 +166,27 @@ class Parser : public AsyncWrap {
}


HTTP_CB(on_message_begin) {
int on_message_begin() {
num_fields_ = num_values_ = 0;
url_.Reset();
status_message_.Reset();
return 0;
}


HTTP_DATA_CB(on_url) {
int on_url(const char* at, size_t length) {
url_.Update(at, length);
return 0;
}


HTTP_DATA_CB(on_status) {
int on_status(const char* at, size_t length) {
status_message_.Update(at, length);
return 0;
}


HTTP_DATA_CB(on_header_field) {
int on_header_field(const char* at, size_t length) {
if (num_fields_ == num_values_) {
// start of new field name
num_fields_++;
Expand All @@ -224,7 +208,7 @@ class Parser : public AsyncWrap {
}


HTTP_DATA_CB(on_header_value) {
int on_header_value(const char* at, size_t length) {
if (num_values_ != num_fields_) {
// start of new header value
num_values_++;
Expand All @@ -240,7 +224,7 @@ class Parser : public AsyncWrap {
}


HTTP_CB(on_headers_complete) {
int on_headers_complete() {
// Arguments for the on-headers-complete javascript callback. This
// list needs to be kept in sync with the actual argument list for
// `parserOnHeadersComplete` in lib/_http_common.js.
Expand Down Expand Up @@ -317,7 +301,7 @@ class Parser : public AsyncWrap {
}


HTTP_DATA_CB(on_body) {
int on_body(const char* at, size_t length) {
EscapableHandleScope scope(env()->isolate());

Local<Object> obj = object();
Expand Down Expand Up @@ -354,7 +338,7 @@ class Parser : public AsyncWrap {
}


HTTP_CB(on_message_complete) {
int on_message_complete() {
HandleScope scope(env()->isolate());

if (num_fields_)
Expand Down Expand Up @@ -751,21 +735,35 @@ class Parser : public AsyncWrap {
StreamResource::Callback<StreamResource::AllocCb> prev_alloc_cb_;
StreamResource::Callback<StreamResource::ReadCb> prev_read_cb_;
int refcount_ = 1;

// These are helper functions for filling `http_parser_settings`, which turn
// a member function of Parser into a C-style HTTP parser callback.
template <typename Parser, Parser> struct Proxy;
template <typename Parser, typename ...Args, int (Parser::*Member)(Args...)>
struct Proxy<int (Parser::*)(Args...), Member> {
static int Raw(http_parser* p, Args ... args) {
Parser* parser = ContainerOf(&Parser::parser_, p);
return (parser->*Member)(std::forward<Args>(args)...);
}
};

typedef int (Parser::*Call)();
typedef int (Parser::*DataCall)(const char* at, size_t length);

static const struct http_parser_settings settings;

friend class ScopedRetainParser;
};


const struct http_parser_settings Parser::settings = {
Parser::on_message_begin,
Parser::on_url,
Parser::on_status,
Parser::on_header_field,
Parser::on_header_value,
Parser::on_headers_complete,
Parser::on_body,
Parser::on_message_complete,
Proxy<Call, &Parser::on_message_begin>::Raw,
Proxy<DataCall, &Parser::on_url>::Raw,
Proxy<DataCall, &Parser::on_status>::Raw,
Proxy<DataCall, &Parser::on_header_field>::Raw,
Proxy<DataCall, &Parser::on_header_value>::Raw,
Proxy<Call, &Parser::on_headers_complete>::Raw,
Proxy<DataCall, &Parser::on_body>::Raw,
Proxy<Call, &Parser::on_message_complete>::Raw,
nullptr, // on_chunk_header
nullptr // on_chunk_complete
};
Expand Down

0 comments on commit 15e75dc

Please sign in to comment.