From fb7f6739c5bc041a28ae45fea80f840459523f8e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 31 Jul 2009 23:46:21 -0700 Subject: unicorn_http: small cleanups and size reduction Use Data_Make_Struct instead of Data_Wrap_Struct to avoid extra steps/code in object allocation. The GC will also free() implicitly if no free callback is passed to Data_Make_Struct, and we don't need an extra method here... Since we're more comfortable with object management nowadays, just make the data_get() fail with an assertion failure if it somehow (very unlikely) ends up getting a NULL parser object. Unicorn itself has no way of recovering other than throwing errors to clients anyways and we have bigger problems if there's a GC bug causing this. Then, finally, reduce the size of our http_parser struct even more (we'll add an int back later) since we know it's safe to do so... --- ext/unicorn_http/ext_help.h | 9 +- ext/unicorn_http/unicorn_http.c | 99 ++++--------- ext/unicorn_http/unicorn_http.h | 304 ++++++++++++++++++--------------------- ext/unicorn_http/unicorn_http.rl | 84 +++++------ 4 files changed, 205 insertions(+), 291 deletions(-) diff --git a/ext/unicorn_http/ext_help.h b/ext/unicorn_http/ext_help.h index 17f7b01..8220600 100644 --- a/ext/unicorn_http/ext_help.h +++ b/ext/unicorn_http/ext_help.h @@ -3,10 +3,11 @@ #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) -#ifdef DEBUG -#define TRACE() fprintf(stderr, "> %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__) -#else -#define TRACE() +#ifndef RSTRING_PTR +#define RSTRING_PTR(s) (RSTRING(s)->ptr) +#endif +#ifndef RSTRING_LEN +#define RSTRING_LEN(s) (RSTRING(s)->len) #endif #endif diff --git a/ext/unicorn_http/unicorn_http.c b/ext/unicorn_http/unicorn_http.c index 41936cd..51ddeaa 100644 --- a/ext/unicorn_http/unicorn_http.c +++ b/ext/unicorn_http/unicorn_http.c @@ -3,8 +3,6 @@ * Copyright (c) 2005 Zed A. Shaw * You can redistribute it and/or modify it under the same terms as Ruby. */ -#include "ruby.h" -#include "ext_help.h" #include #include #include "unicorn_http.h" @@ -14,18 +12,10 @@ static http_parser *data_get(VALUE self) http_parser *http; Data_Get_Struct(self, http_parser, http); - if (!http) - rb_raise(rb_eArgError, "NULL found for http when shouldn't be."); + assert(http); return http; } -#ifndef RSTRING_PTR -#define RSTRING_PTR(s) (RSTRING(s)->ptr) -#endif -#ifndef RSTRING_LEN -#define RSTRING_LEN(s) (RSTRING(s)->len) -#endif - static VALUE mUnicorn; static VALUE cHttpParser; static VALUE eHttpParserError; @@ -169,10 +159,9 @@ static VALUE find_common_field_value(const char *field, size_t flen) return Qnil; } -static void http_field(void *data, const char *field, +static void http_field(VALUE req, const char *field, size_t flen, const char *value, size_t vlen) { - VALUE req = (VALUE)data; VALUE f = Qnil; VALIDATE_MAX_LENGTH(flen, FIELD_NAME); @@ -203,57 +192,44 @@ static void http_field(void *data, const char *field, rb_hash_aset(req, f, rb_str_new(value, vlen)); } -static void request_method(void *data, const char *at, size_t length) +static void request_method(VALUE req, const char *at, size_t length) { - VALUE req = (VALUE)data; - VALUE val = Qnil; - - val = rb_str_new(at, length); - rb_hash_aset(req, global_request_method, val); + rb_hash_aset(req, global_request_method, rb_str_new(at, length)); } -static void scheme(void *data, const char *at, size_t length) +static void scheme(VALUE req, const char *at, size_t length) { - rb_hash_aset((VALUE)data, global_rack_url_scheme, rb_str_new(at, length)); + rb_hash_aset(req, global_rack_url_scheme, rb_str_new(at, length)); } -static void host(void *data, const char *at, size_t length) +static void host(VALUE req, const char *at, size_t length) { - rb_hash_aset((VALUE)data, global_http_host, rb_str_new(at, length)); + rb_hash_aset(req, global_http_host, rb_str_new(at, length)); } -static void request_uri(void *data, const char *at, size_t length) +static void request_uri(VALUE req, const char *at, size_t length) { - VALUE req = (VALUE)data; - VALUE val = Qnil; - VALIDATE_MAX_LENGTH(length, REQUEST_URI); - val = rb_str_new(at, length); - rb_hash_aset(req, global_request_uri, val); + rb_hash_aset(req, global_request_uri, rb_str_new(at, length)); /* "OPTIONS * HTTP/1.1\r\n" is a valid request */ if (length == 1 && *at == '*') { - val = rb_str_new(NULL, 0); + VALUE val = rb_str_new(NULL, 0); rb_hash_aset(req, global_request_path, val); rb_hash_aset(req, global_path_info, val); } } -static void fragment(void *data, const char *at, size_t length) +static void fragment(VALUE req, const char *at, size_t length) { - VALUE req = (VALUE)data; - VALUE val = Qnil; - VALIDATE_MAX_LENGTH(length, FRAGMENT); - val = rb_str_new(at, length); - rb_hash_aset(req, global_fragment, val); + rb_hash_aset(req, global_fragment, rb_str_new(at, length)); } -static void request_path(void *data, const char *at, size_t length) +static void request_path(VALUE req, const char *at, size_t length) { - VALUE req = (VALUE)data; VALUE val = Qnil; VALIDATE_MAX_LENGTH(length, REQUEST_PATH); @@ -266,28 +242,21 @@ static void request_path(void *data, const char *at, size_t length) rb_hash_aset(req, global_path_info, val); } -static void query_string(void *data, const char *at, size_t length) +static void query_string(VALUE req, const char *at, size_t length) { - VALUE req = (VALUE)data; - VALUE val = Qnil; - VALIDATE_MAX_LENGTH(length, QUERY_STRING); - val = rb_str_new(at, length); - rb_hash_aset(req, global_query_string, val); + rb_hash_aset(req, global_query_string, rb_str_new(at, length)); } -static void http_version(void *data, const char *at, size_t length) +static void http_version(VALUE req, const char *at, size_t length) { - VALUE req = (VALUE)data; - VALUE val = rb_str_new(at, length); - rb_hash_aset(req, global_http_version, val); + rb_hash_aset(req, global_http_version, rb_str_new(at, length)); } /** Finalizes the request header to have a bunch of stuff that's needed. */ -static void header_done(void *data, const char *at, size_t length) +static void header_done(VALUE req, const char *at, size_t length) { - VALUE req = (VALUE)data; VALUE server_name = global_localhost; VALUE server_port = global_port_80; VALUE temp; @@ -337,25 +306,10 @@ static void header_done(void *data, const char *at, size_t length) } } -static void HttpParser_free(void *data) { - TRACE(); - - if(data) { - free(data); - } -} - - static VALUE HttpParser_alloc(VALUE klass) { - VALUE obj; - http_parser *hp = ALLOC_N(http_parser, 1); - TRACE(); - http_parser_init(hp); - - obj = Data_Wrap_Struct(klass, NULL, HttpParser_free, hp); - - return obj; + http_parser *hp; + return Data_Make_Struct(klass, http_parser, NULL, NULL, hp); } @@ -390,7 +344,7 @@ static VALUE HttpParser_reset(VALUE self) /** * call-seq: - * parser.execute(req_hash, data) -> true/false + * parser.execute(req, data) -> true/false * * Takes a Hash and a String of data, parses the String of data filling * in the Hash returning a boolean to indicate whether or not parsing @@ -401,17 +355,16 @@ static VALUE HttpParser_reset(VALUE self) * will need to wrap the parser with an exception handling block. */ -static VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data) +static VALUE HttpParser_execute(VALUE self, VALUE req, VALUE data) { http_parser *http = data_get(self); char *dptr = RSTRING_PTR(data); long dlen = RSTRING_LEN(data); - if (http->nread < dlen) { - http->data = (void *)req_hash; - http_parser_execute(http, dptr, dlen); + if (http->start.offset < dlen) { + http_parser_execute(http, req, dptr, dlen); - VALIDATE_MAX_LENGTH(http->nread, HEADER); + VALIDATE_MAX_LENGTH(http->start.offset, HEADER); if (!http_parser_has_error(http)) return http_parser_is_finished(http) ? Qtrue : Qfalse; diff --git a/ext/unicorn_http/unicorn_http.h b/ext/unicorn_http/unicorn_http.h index d39a22b..c651ed3 100644 --- a/ext/unicorn_http/unicorn_http.h +++ b/ext/unicorn_http/unicorn_http.h @@ -7,30 +7,32 @@ #ifndef unicorn_http_h #define unicorn_http_h +#include "ruby.h" +#include "ext_help.h" #include -static void http_field(void *data, const char *field, +static void http_field(VALUE req, const char *field, size_t flen, const char *value, size_t vlen); -static void request_method(void *data, const char *at, size_t length); -static void scheme(void *data, const char *at, size_t length); -static void host(void *data, const char *at, size_t length); -static void request_uri(void *data, const char *at, size_t length); -static void fragment(void *data, const char *at, size_t length); -static void request_path(void *data, const char *at, size_t length); -static void query_string(void *data, const char *at, size_t length); -static void http_version(void *data, const char *at, size_t length); -static void header_done(void *data, const char *at, size_t length); +static void request_method(VALUE req, const char *at, size_t length); +static void scheme(VALUE req, const char *at, size_t length); +static void host(VALUE req, const char *at, size_t length); +static void request_uri(VALUE req, const char *at, size_t length); +static void fragment(VALUE req, const char *at, size_t length); +static void request_path(VALUE req, const char *at, size_t length); +static void query_string(VALUE req, const char *at, size_t length); +static void http_version(VALUE req, const char *at, size_t length); +static void header_done(VALUE req, const char *at, size_t length); typedef struct http_parser { int cs; - size_t body_start; - size_t nread; + union { + size_t body; + size_t field; + size_t query; + size_t offset; + } start; size_t mark; - size_t field_start; size_t field_len; - size_t query_start; - - void *data; } http_parser; static int http_parser_has_error(http_parser *parser); @@ -61,12 +63,12 @@ static void downcase_char(char *c) /** Machine **/ -#line 109 "unicorn_http.rl" +#line 101 "unicorn_http.rl" /** Data **/ -#line 70 "unicorn_http.h" +#line 72 "unicorn_http.h" static const int http_parser_start = 1; static const int http_parser_first_final = 63; static const int http_parser_error = 0; @@ -74,28 +76,28 @@ static const int http_parser_error = 0; static const int http_parser_en_main = 1; -#line 113 "unicorn_http.rl" +#line 105 "unicorn_http.rl" static void http_parser_init(http_parser *parser) { int cs = 0; memset(parser, 0, sizeof(*parser)); -#line 84 "unicorn_http.h" +#line 86 "unicorn_http.h" { cs = http_parser_start; } -#line 118 "unicorn_http.rl" +#line 110 "unicorn_http.rl" parser->cs = cs; } /** exec **/ static void http_parser_execute( - http_parser *parser, const char *buffer, size_t len) + http_parser *parser, VALUE req, const char *buffer, size_t len) { const char *p, *pe; int cs = parser->cs; - size_t off = parser->nread; + size_t off = parser->start.offset; assert(off <= len && "offset past end of buffer"); @@ -106,7 +108,7 @@ static void http_parser_execute( assert(pe - p == len - off && "pointers aren't same distance"); -#line 110 "unicorn_http.h" +#line 112 "unicorn_http.h" { if ( p == pe ) goto _test_eof; @@ -130,14 +132,14 @@ st0: cs = 0; goto _out; tr0: -#line 64 "unicorn_http.rl" +#line 66 "unicorn_http.rl" {MARK(mark, p); } goto st2; st2: if ( ++p == pe ) goto _test_eof2; case 2: -#line 141 "unicorn_http.h" +#line 143 "unicorn_http.h" switch( (*p) ) { case 32: goto tr2; case 36: goto st44; @@ -153,10 +155,8 @@ case 2: goto st44; goto st0; tr2: -#line 77 "unicorn_http.rl" - { - request_method(parser->data, PTR_TO(mark), LEN(mark, p)); - } +#line 80 "unicorn_http.rl" + { request_method(req, PTR_TO(mark), LEN(mark, p)); } goto st3; st3: if ( ++p == pe ) @@ -171,7 +171,7 @@ case 3: } goto st0; tr4: -#line 64 "unicorn_http.rl" +#line 66 "unicorn_http.rl" {MARK(mark, p); } goto st4; st4: @@ -185,74 +185,60 @@ case 4: } goto st0; tr7: -#line 82 "unicorn_http.rl" - { - request_uri(parser->data, PTR_TO(mark), LEN(mark, p)); - } +#line 83 "unicorn_http.rl" + { request_uri(req, PTR_TO(mark), LEN(mark, p)); } goto st5; tr30: -#line 64 "unicorn_http.rl" +#line 66 "unicorn_http.rl" {MARK(mark, p); } -#line 85 "unicorn_http.rl" - { - fragment(parser->data, PTR_TO(mark), LEN(mark, p)); - } +#line 84 "unicorn_http.rl" + { fragment(req, PTR_TO(mark), LEN(mark, p)); } goto st5; tr33: -#line 85 "unicorn_http.rl" - { - fragment(parser->data, PTR_TO(mark), LEN(mark, p)); - } +#line 84 "unicorn_http.rl" + { fragment(req, PTR_TO(mark), LEN(mark, p)); } goto st5; tr37: -#line 98 "unicorn_http.rl" - { - request_path(parser->data, PTR_TO(mark), LEN(mark,p)); - } -#line 82 "unicorn_http.rl" - { - request_uri(parser->data, PTR_TO(mark), LEN(mark, p)); - } +#line 92 "unicorn_http.rl" + { request_path(req, PTR_TO(mark), LEN(mark,p)); } +#line 83 "unicorn_http.rl" + { request_uri(req, PTR_TO(mark), LEN(mark, p)); } goto st5; tr48: -#line 89 "unicorn_http.rl" - {MARK(query_start, p); } -#line 90 "unicorn_http.rl" +#line 86 "unicorn_http.rl" + {MARK(start.query, p); } +#line 87 "unicorn_http.rl" { - query_string(parser->data, PTR_TO(query_start), LEN(query_start, p)); - } -#line 82 "unicorn_http.rl" - { - request_uri(parser->data, PTR_TO(mark), LEN(mark, p)); + query_string(req, PTR_TO(start.query), LEN(start.query, p)); } +#line 83 "unicorn_http.rl" + { request_uri(req, PTR_TO(mark), LEN(mark, p)); } goto st5; tr52: -#line 90 "unicorn_http.rl" +#line 87 "unicorn_http.rl" { - query_string(parser->data, PTR_TO(query_start), LEN(query_start, p)); - } -#line 82 "unicorn_http.rl" - { - request_uri(parser->data, PTR_TO(mark), LEN(mark, p)); + query_string(req, PTR_TO(start.query), LEN(start.query, p)); } +#line 83 "unicorn_http.rl" + { request_uri(req, PTR_TO(mark), LEN(mark, p)); } goto st5; st5: if ( ++p == pe ) goto _test_eof5; case 5: -#line 244 "unicorn_http.h" +#line 230 "unicorn_http.h" if ( (*p) == 72 ) goto tr9; goto st0; tr9: -#line 64 "unicorn_http.rl" +#line 66 "unicorn_http.rl" {MARK(mark, p); } goto st6; st6: if ( ++p == pe ) goto _test_eof6; case 6: -#line 256 "unicorn_http.h" +#line 242 "unicorn_http.h" if ( (*p) == 84 ) goto st7; goto st0; @@ -310,30 +296,30 @@ case 13: goto st13; goto st0; tr17: -#line 94 "unicorn_http.rl" - { - http_version(parser->data, PTR_TO(mark), LEN(mark, p)); - } +#line 91 "unicorn_http.rl" + { http_version(req, PTR_TO(mark), LEN(mark, p)); } goto st14; tr25: -#line 73 "unicorn_http.rl" +#line 75 "unicorn_http.rl" { MARK(mark, p); } -#line 74 "unicorn_http.rl" +#line 76 "unicorn_http.rl" { - http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p)); + http_field(req, PTR_TO(start.field), parser->field_len, + PTR_TO(mark), LEN(mark, p)); } goto st14; tr28: -#line 74 "unicorn_http.rl" +#line 76 "unicorn_http.rl" { - http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p)); + http_field(req, PTR_TO(start.field), parser->field_len, + PTR_TO(mark), LEN(mark, p)); } goto st14; st14: if ( ++p == pe ) goto _test_eof14; case 14: -#line 337 "unicorn_http.h" +#line 323 "unicorn_http.h" if ( (*p) == 10 ) goto st15; goto st0; @@ -373,10 +359,10 @@ case 16: goto tr21; goto st0; tr21: -#line 102 "unicorn_http.rl" +#line 94 "unicorn_http.rl" { - parser->body_start = p - buffer + 1; - header_done(parser->data, p + 1, pe - p - 1); + parser->start.body = p - buffer + 1; + header_done(req, p + 1, pe - p - 1); {p++; cs = 63; goto _out;} } goto st63; @@ -384,23 +370,23 @@ st63: if ( ++p == pe ) goto _test_eof63; case 63: -#line 388 "unicorn_http.h" +#line 374 "unicorn_http.h" goto st0; tr20: -#line 66 "unicorn_http.rl" - { MARK(field_start, p); } -#line 67 "unicorn_http.rl" +#line 68 "unicorn_http.rl" + { MARK(start.field, p); } +#line 69 "unicorn_http.rl" { snake_upcase_char((char *)p); } goto st17; tr22: -#line 67 "unicorn_http.rl" +#line 69 "unicorn_http.rl" { snake_upcase_char((char *)p); } goto st17; st17: if ( ++p == pe ) goto _test_eof17; case 17: -#line 404 "unicorn_http.h" +#line 390 "unicorn_http.h" switch( (*p) ) { case 33: goto tr22; case 58: goto tr23; @@ -426,80 +412,70 @@ case 17: goto tr22; goto st0; tr23: -#line 69 "unicorn_http.rl" +#line 71 "unicorn_http.rl" { - parser->field_len = LEN(field_start, p); + parser->field_len = LEN(start.field, p); } goto st18; tr26: -#line 73 "unicorn_http.rl" +#line 75 "unicorn_http.rl" { MARK(mark, p); } goto st18; st18: if ( ++p == pe ) goto _test_eof18; case 18: -#line 443 "unicorn_http.h" +#line 429 "unicorn_http.h" switch( (*p) ) { case 13: goto tr25; case 32: goto tr26; } goto tr24; tr24: -#line 73 "unicorn_http.rl" +#line 75 "unicorn_http.rl" { MARK(mark, p); } goto st19; st19: if ( ++p == pe ) goto _test_eof19; case 19: -#line 457 "unicorn_http.h" +#line 443 "unicorn_http.h" if ( (*p) == 13 ) goto tr28; goto st19; tr8: -#line 82 "unicorn_http.rl" - { - request_uri(parser->data, PTR_TO(mark), LEN(mark, p)); - } +#line 83 "unicorn_http.rl" + { request_uri(req, PTR_TO(mark), LEN(mark, p)); } goto st20; tr38: -#line 98 "unicorn_http.rl" - { - request_path(parser->data, PTR_TO(mark), LEN(mark,p)); - } -#line 82 "unicorn_http.rl" - { - request_uri(parser->data, PTR_TO(mark), LEN(mark, p)); - } +#line 92 "unicorn_http.rl" + { request_path(req, PTR_TO(mark), LEN(mark,p)); } +#line 83 "unicorn_http.rl" + { request_uri(req, PTR_TO(mark), LEN(mark, p)); } goto st20; tr49: -#line 89 "unicorn_http.rl" - {MARK(query_start, p); } -#line 90 "unicorn_http.rl" +#line 86 "unicorn_http.rl" + {MARK(start.query, p); } +#line 87 "unicorn_http.rl" { - query_string(parser->data, PTR_TO(query_start), LEN(query_start, p)); - } -#line 82 "unicorn_http.rl" - { - request_uri(parser->data, PTR_TO(mark), LEN(mark, p)); + query_string(req, PTR_TO(start.query), LEN(start.query, p)); } +#line 83 "unicorn_http.rl" + { request_uri(req, PTR_TO(mark), LEN(mark, p)); } goto st20; tr53: -#line 90 "unicorn_http.rl" +#line 87 "unicorn_http.rl" { - query_string(parser->data, PTR_TO(query_start), LEN(query_start, p)); - } -#line 82 "unicorn_http.rl" - { - request_uri(parser->data, PTR_TO(mark), LEN(mark, p)); + query_string(req, PTR_TO(start.query), LEN(start.query, p)); } +#line 83 "unicorn_http.rl" + { request_uri(req, PTR_TO(mark), LEN(mark, p)); } goto st20; st20: if ( ++p == pe ) goto _test_eof20; case 20: -#line 503 "unicorn_http.h" +#line 479 "unicorn_http.h" switch( (*p) ) { case 32: goto tr30; case 35: goto st0; @@ -510,14 +486,14 @@ case 20: goto st0; goto tr29; tr29: -#line 64 "unicorn_http.rl" +#line 66 "unicorn_http.rl" {MARK(mark, p); } goto st21; st21: if ( ++p == pe ) goto _test_eof21; case 21: -#line 521 "unicorn_http.h" +#line 497 "unicorn_http.h" switch( (*p) ) { case 32: goto tr33; case 35: goto st0; @@ -528,14 +504,14 @@ case 21: goto st0; goto st21; tr31: -#line 64 "unicorn_http.rl" +#line 66 "unicorn_http.rl" {MARK(mark, p); } goto st22; st22: if ( ++p == pe ) goto _test_eof22; case 22: -#line 539 "unicorn_http.h" +#line 515 "unicorn_http.h" if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st23; @@ -559,20 +535,20 @@ case 23: goto st21; goto st0; tr5: -#line 64 "unicorn_http.rl" +#line 66 "unicorn_http.rl" {MARK(mark, p); } goto st24; tr65: -#line 81 "unicorn_http.rl" - { host(parser->data, PTR_TO(mark), LEN(mark, p)); } -#line 64 "unicorn_http.rl" +#line 82 "unicorn_http.rl" + { host(req, PTR_TO(mark), LEN(mark, p)); } +#line 66 "unicorn_http.rl" {MARK(mark, p); } goto st24; st24: if ( ++p == pe ) goto _test_eof24; case 24: -#line 576 "unicorn_http.h" +#line 552 "unicorn_http.h" switch( (*p) ) { case 32: goto tr37; case 35: goto tr38; @@ -611,16 +587,14 @@ case 26: goto st24; goto st0; tr40: -#line 98 "unicorn_http.rl" - { - request_path(parser->data, PTR_TO(mark), LEN(mark,p)); - } +#line 92 "unicorn_http.rl" + { request_path(req, PTR_TO(mark), LEN(mark,p)); } goto st27; st27: if ( ++p == pe ) goto _test_eof27; case 27: -#line 624 "unicorn_http.h" +#line 598 "unicorn_http.h" switch( (*p) ) { case 32: goto tr7; case 35: goto tr8; @@ -658,16 +632,14 @@ case 29: goto st27; goto st0; tr41: -#line 98 "unicorn_http.rl" - { - request_path(parser->data, PTR_TO(mark), LEN(mark,p)); - } +#line 92 "unicorn_http.rl" + { request_path(req, PTR_TO(mark), LEN(mark,p)); } goto st30; st30: if ( ++p == pe ) goto _test_eof30; case 30: -#line 671 "unicorn_http.h" +#line 643 "unicorn_http.h" switch( (*p) ) { case 32: goto tr48; case 35: goto tr49; @@ -678,14 +650,14 @@ case 30: goto st0; goto tr47; tr47: -#line 89 "unicorn_http.rl" - {MARK(query_start, p); } +#line 86 "unicorn_http.rl" + {MARK(start.query, p); } goto st31; st31: if ( ++p == pe ) goto _test_eof31; case 31: -#line 689 "unicorn_http.h" +#line 661 "unicorn_http.h" switch( (*p) ) { case 32: goto tr52; case 35: goto tr53; @@ -696,14 +668,14 @@ case 31: goto st0; goto st31; tr50: -#line 89 "unicorn_http.rl" - {MARK(query_start, p); } +#line 86 "unicorn_http.rl" + {MARK(start.query, p); } goto st32; st32: if ( ++p == pe ) goto _test_eof32; case 32: -#line 707 "unicorn_http.h" +#line 679 "unicorn_http.h" if ( (*p) < 65 ) { if ( 48 <= (*p) && (*p) <= 57 ) goto st33; @@ -727,58 +699,58 @@ case 33: goto st31; goto st0; tr6: -#line 64 "unicorn_http.rl" +#line 66 "unicorn_http.rl" {MARK(mark, p); } -#line 68 "unicorn_http.rl" +#line 70 "unicorn_http.rl" { downcase_char((char *)p); } goto st34; st34: if ( ++p == pe ) goto _test_eof34; case 34: -#line 740 "unicorn_http.h" +#line 712 "unicorn_http.h" switch( (*p) ) { case 84: goto tr56; case 116: goto tr56; } goto st0; tr56: -#line 68 "unicorn_http.rl" +#line 70 "unicorn_http.rl" { downcase_char((char *)p); } goto st35; st35: if ( ++p == pe ) goto _test_eof35; case 35: -#line 754 "unicorn_http.h" +#line 726 "unicorn_http.h" switch( (*p) ) { case 84: goto tr57; case 116: goto tr57; } goto st0; tr57: -#line 68 "unicorn_http.rl" +#line 70 "unicorn_http.rl" { downcase_char((char *)p); } goto st36; st36: if ( ++p == pe ) goto _test_eof36; case 36: -#line 768 "unicorn_http.h" +#line 740 "unicorn_http.h" switch( (*p) ) { case 80: goto tr58; case 112: goto tr58; } goto st0; tr58: -#line 68 "unicorn_http.rl" +#line 70 "unicorn_http.rl" { downcase_char((char *)p); } goto st37; st37: if ( ++p == pe ) goto _test_eof37; case 37: -#line 782 "unicorn_http.h" +#line 754 "unicorn_http.h" switch( (*p) ) { case 58: goto tr59; case 83: goto tr60; @@ -786,14 +758,14 @@ case 37: } goto st0; tr59: -#line 80 "unicorn_http.rl" - { scheme(parser->data, PTR_TO(mark), LEN(mark, p)); } +#line 81 "unicorn_http.rl" + { scheme(req, PTR_TO(mark), LEN(mark, p)); } goto st38; st38: if ( ++p == pe ) goto _test_eof38; case 38: -#line 797 "unicorn_http.h" +#line 769 "unicorn_http.h" if ( (*p) == 47 ) goto st39; goto st0; @@ -823,14 +795,14 @@ case 40: goto tr63; goto st0; tr63: -#line 64 "unicorn_http.rl" +#line 66 "unicorn_http.rl" {MARK(mark, p); } goto st41; st41: if ( ++p == pe ) goto _test_eof41; case 41: -#line 834 "unicorn_http.h" +#line 806 "unicorn_http.h" switch( (*p) ) { case 47: goto tr65; case 58: goto st42; @@ -855,14 +827,14 @@ case 42: goto st42; goto st0; tr60: -#line 68 "unicorn_http.rl" +#line 70 "unicorn_http.rl" { downcase_char((char *)p); } goto st43; st43: if ( ++p == pe ) goto _test_eof43; case 43: -#line 866 "unicorn_http.h" +#line 838 "unicorn_http.h" if ( (*p) == 58 ) goto tr59; goto st0; @@ -1265,18 +1237,16 @@ case 62: _out: {} } -#line 138 "unicorn_http.rl" +#line 130 "unicorn_http.rl" if (!http_parser_has_error(parser)) parser->cs = cs; - parser->nread += p - (buffer + off); + parser->start.offset = p - buffer; assert(p <= pe && "buffer overflow after parsing execute"); - assert(parser->nread <= len && "nread longer than length"); - assert(parser->body_start <= len && "body starts after buffer end"); + assert(parser->start.offset <= len && "start.offset longer than length"); assert(parser->mark < len && "mark is after buffer end"); assert(parser->field_len <= len && "field has length longer than whole buffer"); - assert(parser->field_start < len && "field starts after buffer end"); } static int http_parser_has_error(http_parser *parser) { diff --git a/ext/unicorn_http/unicorn_http.rl b/ext/unicorn_http/unicorn_http.rl index d487a83..ceb4073 100644 --- a/ext/unicorn_http/unicorn_http.rl +++ b/ext/unicorn_http/unicorn_http.rl @@ -5,30 +5,32 @@ #ifndef unicorn_http_h #define unicorn_http_h +#include "ruby.h" +#include "ext_help.h" #include -static void http_field(void *data, const char *field, +static void http_field(VALUE req, const char *field, size_t flen, const char *value, size_t vlen); -static void request_method(void *data, const char *at, size_t length); -static void scheme(void *data, const char *at, size_t length); -static void host(void *data, const char *at, size_t length); -static void request_uri(void *data, const char *at, size_t length); -static void fragment(void *data, const char *at, size_t length); -static void request_path(void *data, const char *at, size_t length); -static void query_string(void *data, const char *at, size_t length); -static void http_version(void *data, const char *at, size_t length); -static void header_done(void *data, const char *at, size_t length); +static void request_method(VALUE req, const char *at, size_t length); +static void scheme(VALUE req, const char *at, size_t length); +static void host(VALUE req, const char *at, size_t length); +static void request_uri(VALUE req, const char *at, size_t length); +static void fragment(VALUE req, const char *at, size_t length); +static void request_path(VALUE req, const char *at, size_t length); +static void query_string(VALUE req, const char *at, size_t length); +static void http_version(VALUE req, const char *at, size_t length); +static void header_done(VALUE req, const char *at, size_t length); typedef struct http_parser { int cs; - size_t body_start; - size_t nread; + union { + size_t body; + size_t field; + size_t query; + size_t offset; + } start; size_t mark; - size_t field_start; size_t field_len; - size_t query_start; - - void *data; } http_parser; static int http_parser_has_error(http_parser *parser); @@ -63,45 +65,35 @@ static void downcase_char(char *c) action mark {MARK(mark, fpc); } - action start_field { MARK(field_start, fpc); } + action start_field { MARK(start.field, fpc); } action snake_upcase_field { snake_upcase_char((char *)fpc); } action downcase_char { downcase_char((char *)fpc); } action write_field { - parser->field_len = LEN(field_start, fpc); + parser->field_len = LEN(start.field, fpc); } action start_value { MARK(mark, fpc); } action write_value { - http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc)); - } - action request_method { - request_method(parser->data, PTR_TO(mark), LEN(mark, fpc)); - } - action scheme { scheme(parser->data, PTR_TO(mark), LEN(mark, fpc)); } - action host { host(parser->data, PTR_TO(mark), LEN(mark, fpc)); } - action request_uri { - request_uri(parser->data, PTR_TO(mark), LEN(mark, fpc)); - } - action fragment { - fragment(parser->data, PTR_TO(mark), LEN(mark, fpc)); + http_field(req, PTR_TO(start.field), parser->field_len, + PTR_TO(mark), LEN(mark, fpc)); } + action request_method { request_method(req, PTR_TO(mark), LEN(mark, fpc)); } + action scheme { scheme(req, PTR_TO(mark), LEN(mark, fpc)); } + action host { host(req, PTR_TO(mark), LEN(mark, fpc)); } + action request_uri { request_uri(req, PTR_TO(mark), LEN(mark, fpc)); } + action fragment { fragment(req, PTR_TO(mark), LEN(mark, fpc)); } - action start_query {MARK(query_start, fpc); } + action start_query {MARK(start.query, fpc); } action query_string { - query_string(parser->data, PTR_TO(query_start), LEN(query_start, fpc)); + query_string(req, PTR_TO(start.query), LEN(start.query, fpc)); } - action http_version { - http_version(parser->data, PTR_TO(mark), LEN(mark, fpc)); - } - - action request_path { - request_path(parser->data, PTR_TO(mark), LEN(mark,fpc)); - } + action http_version { http_version(req, PTR_TO(mark), LEN(mark, fpc)); } + action request_path { request_path(req, PTR_TO(mark), LEN(mark,fpc)); } action done { - parser->body_start = fpc - buffer + 1; - header_done(parser->data, fpc + 1, pe - fpc - 1); + parser->start.body = fpc - buffer + 1; + header_done(req, fpc + 1, pe - fpc - 1); fbreak; } @@ -120,11 +112,11 @@ static void http_parser_init(http_parser *parser) { /** exec **/ static void http_parser_execute( - http_parser *parser, const char *buffer, size_t len) + http_parser *parser, VALUE req, const char *buffer, size_t len) { const char *p, *pe; int cs = parser->cs; - size_t off = parser->nread; + size_t off = parser->start.offset; assert(off <= len && "offset past end of buffer"); @@ -138,14 +130,12 @@ static void http_parser_execute( if (!http_parser_has_error(parser)) parser->cs = cs; - parser->nread += p - (buffer + off); + parser->start.offset = p - buffer; assert(p <= pe && "buffer overflow after parsing execute"); - assert(parser->nread <= len && "nread longer than length"); - assert(parser->body_start <= len && "body starts after buffer end"); + assert(parser->start.offset <= len && "start.offset longer than length"); assert(parser->mark < len && "mark is after buffer end"); assert(parser->field_len <= len && "field has length longer than whole buffer"); - assert(parser->field_start < len && "field starts after buffer end"); } static int http_parser_has_error(http_parser *parser) { -- cgit v1.2.3-24-ge0c7