From 59f13304e1e15de145a625e70231d85d28931a77 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sat, 13 Jan 2018 14:41:16 +0100 Subject: [PATCH] src: refactor callback #defines into C++ templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: https://github.com/nodejs/node/pull/18133 Reviewed-By: James M Snell Reviewed-By: Jon Moss Reviewed-By: Tobias Nießen Reviewed-By: Joyee Cheung Reviewed-By: Franziska Hinkelmann --- src/node_http_parser.cc | 64 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index 31dd013736e42b..627bce37913ed6 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -74,22 +74,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() { @@ -184,7 +168,7 @@ class Parser : public AsyncWrap { } - HTTP_CB(on_message_begin) { + int on_message_begin() { num_fields_ = num_values_ = 0; url_.Reset(); status_message_.Reset(); @@ -192,19 +176,19 @@ class Parser : public AsyncWrap { } - 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_++; @@ -226,7 +210,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_++; @@ -242,7 +226,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. @@ -319,7 +303,7 @@ class Parser : public AsyncWrap { } - HTTP_DATA_CB(on_body) { + int on_body(const char* at, size_t length) { EscapableHandleScope scope(env()->isolate()); Local obj = object(); @@ -356,7 +340,7 @@ class Parser : public AsyncWrap { } - HTTP_CB(on_message_complete) { + int on_message_complete() { HandleScope scope(env()->isolate()); if (num_fields_) @@ -753,21 +737,35 @@ class Parser : public AsyncWrap { StreamResource::Callback prev_alloc_cb_; StreamResource::Callback 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 struct Proxy; + template + struct Proxy { + static int Raw(http_parser* p, Args ... args) { + Parser* parser = ContainerOf(&Parser::parser_, p); + return (parser->*Member)(std::forward(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::Raw, + Proxy::Raw, + Proxy::Raw, + Proxy::Raw, + Proxy::Raw, + Proxy::Raw, + Proxy::Raw, + Proxy::Raw, nullptr, // on_chunk_header nullptr // on_chunk_complete };