save more space by removing buffer and shortening method

This also fixes test failures from the previous commit.

It also adds support for the LOCK method, which was previously
missing.

This brings the size of http_parser from 44 bytes to 32 bytes.  It
also makes the code substantially shorter, at a slight cost in
craziness.
event_stream
Cliff Frey 15 years ago committed by Ryan Dahl
parent 7a1103ae53
commit 9eac636531

@ -248,35 +248,6 @@ enum flags
#endif
#define ngx_str3_cmp(m, c0, c1, c2) \
m[0] == c0 && m[1] == c1 && m[2] == c2
#define ngx_str3Ocmp(m, c0, c1, c2, c3) \
m[0] == c0 && m[2] == c2 && m[3] == c3
#define ngx_str4cmp(m, c0, c1, c2, c3) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3
#define ngx_str5cmp(m, c0, c1, c2, c3, c4) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 && m[4] == c4
#define ngx_str6cmp(m, c0, c1, c2, c3, c4, c5) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
&& m[4] == c4 && m[5] == c5
#define ngx_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
&& m[4] == c4 && m[5] == c5 && m[6] == c6
#define ngx_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
&& m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7
#define ngx_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) \
m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
&& m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7 && m[8] == c8
size_t http_parser_execute (http_parser *parser,
const http_parser_settings *settings,
const char *data,
@ -354,10 +325,7 @@ size_t http_parser_execute (http_parser *parser,
state = s_res_or_resp_H;
else {
parser->type = HTTP_REQUEST;
if (ch < 'A' || 'Z' < ch) goto error;
parser->buffer[0] = ch;
index = 0;
state = s_req_method;
goto start_req_method_assign;
}
break;
}
@ -367,12 +335,10 @@ size_t http_parser_execute (http_parser *parser,
parser->type = HTTP_RESPONSE;
state = s_res_HT;
} else {
if (ch < 'A' || 'Z' < ch) goto error;
if (ch != 'E') goto error;
parser->type = HTTP_REQUEST;
parser->method = (enum http_method) 0;
parser->buffer[0] = 'H';
parser->buffer[1] = ch;
index = 1;
parser->method = HTTP_HEAD;
index = 2;
state = s_req_method;
}
break;
@ -535,128 +501,69 @@ size_t http_parser_execute (http_parser *parser,
if (ch < 'A' || 'Z' < ch) goto error;
start_req_method_assign:
parser->method = (enum http_method) 0;
index = 0;
parser->buffer[0] = ch;
index = 1;
switch (ch) {
case 'C': parser->method = HTTP_CONNECT; /* or COPY */ break;
case 'D': parser->method = HTTP_DELETE; break;
case 'G': parser->method = HTTP_GET; break;
case 'H': parser->method = HTTP_HEAD; break;
case 'L': parser->method = HTTP_LOCK; break;
case 'M': parser->method = HTTP_MKCOL; /* or MOVE */ break;
case 'O': parser->method = HTTP_OPTIONS; break;
case 'P': parser->method = HTTP_POST; /* or PROPFIND or PROPPATCH or PUT */ break;
case 'T': parser->method = HTTP_TRACE; break;
case 'U': parser->method = HTTP_UNLOCK; break;
default: goto error;
}
state = s_req_method;
break;
}
case s_req_method:
if (ch == ' ') {
assert(index+1 < HTTP_PARSER_MAX_METHOD_LEN);
parser->buffer[index+1] = '\0';
switch (index+1) {
case 3:
if (ngx_str3_cmp(parser->buffer, 'G', 'E', 'T')) {
parser->method = HTTP_GET;
break;
}
if (ngx_str3_cmp(parser->buffer, 'P', 'U', 'T')) {
parser->method = HTTP_PUT;
break;
}
break;
case 4:
if (ngx_str4cmp(parser->buffer, 'P', 'O', 'S', 'T')) {
parser->method = HTTP_POST;
break;
}
if (ngx_str4cmp(parser->buffer, 'H', 'E', 'A', 'D')) {
parser->method = HTTP_HEAD;
break;
}
{
if (ch == '\0')
goto error;
if (ngx_str4cmp(parser->buffer, 'C', 'O', 'P', 'Y')) {
static const char *match_strs[] = {
"DELETE",
"GET",
"HEAD",
"POST",
"PUT",
"CONNECT",
"OPTIONS",
"TRACE",
"COPY",
"LOCK",
"MKCOL",
"MOVE",
"PROPFIND",
"PROPPATCH",
"UNLOCK" };
const char *matcher = match_strs[parser->method];
if (ch == ' ' && matcher[index] == '\0')
state = s_req_spaces_before_url;
else if (ch == matcher[index])
; // nada
else if (index == 2 && parser->method == HTTP_CONNECT && ch == 'P')
parser->method = HTTP_COPY;
break;
}
if (ngx_str4cmp(parser->buffer, 'M', 'O', 'V', 'E')) {
else if (index == 1 && parser->method == HTTP_MKCOL && ch == 'O')
parser->method = HTTP_MOVE;
break;
}
break;
case 5:
if (ngx_str5cmp(parser->buffer, 'M', 'K', 'C', 'O', 'L')) {
parser->method = HTTP_MKCOL;
break;
}
if (ngx_str5cmp(parser->buffer, 'T', 'R', 'A', 'C', 'E')) {
parser->method = HTTP_TRACE;
break;
}
break;
case 6:
if (ngx_str6cmp(parser->buffer, 'D', 'E', 'L', 'E', 'T', 'E')) {
parser->method = HTTP_DELETE;
break;
}
if (ngx_str6cmp(parser->buffer, 'U', 'N', 'L', 'O', 'C', 'K')) {
parser->method = HTTP_UNLOCK;
break;
}
break;
case 7:
if (ngx_str7_cmp(parser->buffer,
'O', 'P', 'T', 'I', 'O', 'N', 'S', '\0')) {
parser->method = HTTP_OPTIONS;
break;
}
if (ngx_str7_cmp(parser->buffer,
'C', 'O', 'N', 'N', 'E', 'C', 'T', '\0')) {
parser->method = HTTP_CONNECT;
break;
}
break;
case 8:
if (ngx_str8cmp(parser->buffer,
'P', 'R', 'O', 'P', 'F', 'I', 'N', 'D')) {
parser->method = HTTP_PROPFIND;
break;
}
break;
case 9:
if (ngx_str9cmp(parser->buffer,
'P', 'R', 'O', 'P', 'P', 'A', 'T', 'C', 'H')) {
else if (index == 1 && parser->method == HTTP_POST && ch == 'R')
parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
else if (index == 1 && parser->method == HTTP_POST && ch == 'U')
parser->method = HTTP_PUT;
else if (index == 4 && parser->method == HTTP_PROPFIND && ch == 'P')
parser->method = HTTP_PROPPATCH;
break;
}
break;
}
state = s_req_spaces_before_url;
break;
}
if (ch < 'A' || 'Z' < ch) goto error;
if (++index >= HTTP_PARSER_MAX_METHOD_LEN - 1) {
else
goto error;
}
parser->buffer[index] = ch;
++index;
break;
}
case s_req_spaces_before_url:
{
if (ch == ' ') break;

@ -63,29 +63,25 @@ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
typedef int (*http_cb) (http_parser*);
/* Should be at least one longer than the longest request method */
#define HTTP_PARSER_MAX_METHOD_LEN 10
/* Request Methods */
enum http_method
{ HTTP_DELETE = 0x0001
, HTTP_GET = 0x0002
, HTTP_HEAD = 0x0004
, HTTP_POST = 0x0008
, HTTP_PUT = 0x0010
{ HTTP_DELETE = 0
, HTTP_GET
, HTTP_HEAD
, HTTP_POST
, HTTP_PUT
/* pathological */
, HTTP_CONNECT = 0x0020
, HTTP_OPTIONS = 0x0040
, HTTP_TRACE = 0x0080
, HTTP_CONNECT
, HTTP_OPTIONS
, HTTP_TRACE
/* webdav */
, HTTP_COPY = 0x0100
, HTTP_LOCK = 0x0200
, HTTP_MKCOL = 0x0400
, HTTP_MOVE = 0x0800
, HTTP_PROPFIND = 0x1000
, HTTP_PROPPATCH = 0x2000
, HTTP_UNLOCK = 0x4000
, HTTP_COPY
, HTTP_LOCK
, HTTP_MKCOL
, HTTP_MOVE
, HTTP_PROPFIND
, HTTP_PROPPATCH
, HTTP_UNLOCK
};
@ -105,11 +101,10 @@ struct http_parser {
ssize_t content_length;
/** READ-ONLY **/
unsigned short status_code; /* responses only */
unsigned short method; /* requests only */
unsigned short http_major;
unsigned short http_minor;
char buffer[HTTP_PARSER_MAX_METHOD_LEN];
unsigned short status_code; /* responses only */
unsigned char method; /* requests only */
/* 1 = Upgrade header was present and the parser has exited because of that.
* 0 = No upgrade header present.

Loading…
Cancel
Save