view dreactor/protocol/http11_parser.d @ 11:5836613d16ac

reorg! reorg!
author rick@minifunk
date Tue, 12 Aug 2008 16:59:56 -0400
parents
children
line wrap: on
line source

module dreactor.protocol.http11_parser;

//#line 1 "http11_parser.rl"
/**
 * Copyright (c) 2005 Zed A. Shaw, 
 * Modified for D by Rick Richardson, 2008
 * You can redistribute it and/or modify it under the same terms as Ruby.
 */


alias void delegate (Object data, char[] buf) element_cb;
alias void delegate (Object data, char[] field, char[] value) field_cb;

class Http11Parser
{
private
  int cs;
  size_t body_start;
  int content_len;
  size_t nread;
  size_t mark;
  size_t field_start;
  size_t field_len;
  size_t query_start;

  Object data;

  field_cb http_field;
  element_cb request_method;
  element_cb request_uri;
  element_cb fragment;
  element_cb request_path;
  element_cb query_string;
  element_cb http_version;
  element_cb header_done;
  
/*
 * capitalizes all lower-case ASCII characters,
 * converts dashes to underscores.
 */
private void snake_upcase_char(char *c)
{
    if (*c >= 'a' && *c <= 'z')
      *c &= ~0x20;
    else if (*c == '-')
      *c = '_';
}

//#define LEN(AT, FPC) (FPC - buffer - parser->AT)
private size_t LEN(char[] buffer, size_t at, char* fpc)
{
    return (fpc - buffer.ptr - at);
}

//#define MARK(M,FPC) (parser->M = (FPC) - buffer)
private void MARK(char[] buffer, size_t* item, char* fpc)
{
    *item = fpc - buffer.ptr;
}

/** Machine **/

//#line 126 "http11_parser.rl"


/** Data **/

//#line 70 "http11_parser.d"
static byte[] _http_parser_actions = [
	0, 1, 0, 1, 2, 1, 3, 1, 
	4, 1, 5, 1, 6, 1, 7, 1, 
	8, 1, 9, 1, 11, 1, 12, 1, 
	13, 2, 1, 2, 2, 10, 7, 2, 
	12, 7, 3, 9, 10, 7
];

static short[] _http_parser_key_offsets = [
	0, 0, 8, 17, 27, 29, 30, 31, 
	32, 33, 34, 36, 39, 41, 44, 45, 
	61, 62, 78, 80, 81, 90, 99, 105, 
	111, 121, 130, 136, 142, 153, 159, 165, 
	175, 181, 187, 196, 205, 211, 217, 226, 
	235, 244, 253, 262, 271, 280, 289, 298, 
	307, 316, 325, 334, 343, 352, 361, 370, 
	379, 380
];

static char[] _http_parser_trans_keys = [
	36u, 95u, 45u, 46u, 48u, 57u, 65u, 90u, 
	32u, 36u, 95u, 45u, 46u, 48u, 57u, 65u, 
	90u, 42u, 43u, 47u, 58u, 45u, 57u, 65u, 
	90u, 97u, 122u, 32u, 35u, 72u, 84u, 84u, 
	80u, 47u, 48u, 57u, 46u, 48u, 57u, 48u, 
	57u, 13u, 48u, 57u, 10u, 13u, 33u, 124u, 
	126u, 35u, 39u, 42u, 43u, 45u, 46u, 48u, 
	57u, 65u, 90u, 94u, 122u, 10u, 33u, 58u, 
	124u, 126u, 35u, 39u, 42u, 43u, 45u, 46u, 
	48u, 57u, 65u, 90u, 94u, 122u, 13u, 32u, 
	13u, 32u, 37u, 60u, 62u, 127u, 0u, 31u, 
	34u, 35u, 32u, 37u, 60u, 62u, 127u, 0u, 
	31u, 34u, 35u, 48u, 57u, 65u, 70u, 97u, 
	102u, 48u, 57u, 65u, 70u, 97u, 102u, 43u, 
	58u, 45u, 46u, 48u, 57u, 65u, 90u, 97u, 
	122u, 32u, 34u, 35u, 37u, 60u, 62u, 127u, 
	0u, 31u, 48u, 57u, 65u, 70u, 97u, 102u, 
	48u, 57u, 65u, 70u, 97u, 102u, 32u, 34u, 
	35u, 37u, 59u, 60u, 62u, 63u, 127u, 0u, 
	31u, 48u, 57u, 65u, 70u, 97u, 102u, 48u, 
	57u, 65u, 70u, 97u, 102u, 32u, 34u, 35u, 
	37u, 60u, 62u, 63u, 127u, 0u, 31u, 48u, 
	57u, 65u, 70u, 97u, 102u, 48u, 57u, 65u, 
	70u, 97u, 102u, 32u, 34u, 35u, 37u, 60u, 
	62u, 127u, 0u, 31u, 32u, 34u, 35u, 37u, 
	60u, 62u, 127u, 0u, 31u, 48u, 57u, 65u, 
	70u, 97u, 102u, 48u, 57u, 65u, 70u, 97u, 
	102u, 32u, 36u, 95u, 45u, 46u, 48u, 57u, 
	65u, 90u, 32u, 36u, 95u, 45u, 46u, 48u, 
	57u, 65u, 90u, 32u, 36u, 95u, 45u, 46u, 
	48u, 57u, 65u, 90u, 32u, 36u, 95u, 45u, 
	46u, 48u, 57u, 65u, 90u, 32u, 36u, 95u, 
	45u, 46u, 48u, 57u, 65u, 90u, 32u, 36u, 
	95u, 45u, 46u, 48u, 57u, 65u, 90u, 32u, 
	36u, 95u, 45u, 46u, 48u, 57u, 65u, 90u, 
	32u, 36u, 95u, 45u, 46u, 48u, 57u, 65u, 
	90u, 32u, 36u, 95u, 45u, 46u, 48u, 57u, 
	65u, 90u, 32u, 36u, 95u, 45u, 46u, 48u, 
	57u, 65u, 90u, 32u, 36u, 95u, 45u, 46u, 
	48u, 57u, 65u, 90u, 32u, 36u, 95u, 45u, 
	46u, 48u, 57u, 65u, 90u, 32u, 36u, 95u, 
	45u, 46u, 48u, 57u, 65u, 90u, 32u, 36u, 
	95u, 45u, 46u, 48u, 57u, 65u, 90u, 32u, 
	36u, 95u, 45u, 46u, 48u, 57u, 65u, 90u, 
	32u, 36u, 95u, 45u, 46u, 48u, 57u, 65u, 
	90u, 32u, 36u, 95u, 45u, 46u, 48u, 57u, 
	65u, 90u, 32u, 36u, 95u, 45u, 46u, 48u, 
	57u, 65u, 90u, 32u, 0
];

static byte[] _http_parser_single_lengths = [
	0, 2, 3, 4, 2, 1, 1, 1, 
	1, 1, 0, 1, 0, 1, 1, 4, 
	1, 4, 2, 1, 5, 5, 0, 0, 
	2, 7, 0, 0, 9, 0, 0, 8, 
	0, 0, 7, 7, 0, 0, 3, 3, 
	3, 3, 3, 3, 3, 3, 3, 3, 
	3, 3, 3, 3, 3, 3, 3, 3, 
	1, 0
];

static byte[] _http_parser_range_lengths = [
	0, 3, 3, 3, 0, 0, 0, 0, 
	0, 0, 1, 1, 1, 1, 0, 6, 
	0, 6, 0, 0, 2, 2, 3, 3, 
	4, 1, 3, 3, 1, 3, 3, 1, 
	3, 3, 1, 1, 3, 3, 3, 3, 
	3, 3, 3, 3, 3, 3, 3, 3, 
	3, 3, 3, 3, 3, 3, 3, 3, 
	0, 0
];

static short[] _http_parser_index_offsets = [
	0, 0, 6, 13, 21, 24, 26, 28, 
	30, 32, 34, 36, 39, 41, 44, 46, 
	57, 59, 70, 73, 75, 83, 91, 95, 
	99, 106, 115, 119, 123, 134, 138, 142, 
	152, 156, 160, 169, 178, 182, 186, 193, 
	200, 207, 214, 221, 228, 235, 242, 249, 
	256, 263, 270, 277, 284, 291, 298, 305, 
	312, 314
];

static byte[] _http_parser_indicies = [
	0, 0, 0, 0, 0, 1, 2, 3, 
	3, 3, 3, 3, 1, 4, 5, 6, 
	7, 5, 5, 5, 1, 8, 9, 1, 
	10, 1, 11, 1, 12, 1, 13, 1, 
	14, 1, 15, 1, 16, 15, 1, 17, 
	1, 18, 17, 1, 19, 1, 20, 21, 
	21, 21, 21, 21, 21, 21, 21, 21, 
	1, 22, 1, 23, 24, 23, 23, 23, 
	23, 23, 23, 23, 23, 1, 26, 27, 
	25, 26, 28, 29, 31, 1, 1, 1, 
	1, 1, 30, 29, 33, 1, 1, 1, 
	1, 1, 32, 34, 34, 34, 1, 32, 
	32, 32, 1, 35, 36, 35, 35, 35, 
	35, 1, 8, 1, 9, 37, 1, 1, 
	1, 1, 36, 38, 38, 38, 1, 36, 
	36, 36, 1, 39, 1, 41, 42, 43, 
	1, 1, 44, 1, 1, 40, 45, 45, 
	45, 1, 40, 40, 40, 1, 8, 1, 
	9, 47, 1, 1, 48, 1, 1, 46, 
	49, 49, 49, 1, 46, 46, 46, 1, 
	50, 1, 52, 53, 1, 1, 1, 1, 
	51, 54, 1, 56, 57, 1, 1, 1, 
	1, 55, 58, 58, 58, 1, 55, 55, 
	55, 1, 2, 59, 59, 59, 59, 59, 
	1, 2, 60, 60, 60, 60, 60, 1, 
	2, 61, 61, 61, 61, 61, 1, 2, 
	62, 62, 62, 62, 62, 1, 2, 63, 
	63, 63, 63, 63, 1, 2, 64, 64, 
	64, 64, 64, 1, 2, 65, 65, 65, 
	65, 65, 1, 2, 66, 66, 66, 66, 
	66, 1, 2, 67, 67, 67, 67, 67, 
	1, 2, 68, 68, 68, 68, 68, 1, 
	2, 69, 69, 69, 69, 69, 1, 2, 
	70, 70, 70, 70, 70, 1, 2, 71, 
	71, 71, 71, 71, 1, 2, 72, 72, 
	72, 72, 72, 1, 2, 73, 73, 73, 
	73, 73, 1, 2, 74, 74, 74, 74, 
	74, 1, 2, 75, 75, 75, 75, 75, 
	1, 2, 76, 76, 76, 76, 76, 1, 
	2, 1, 1, 0
];

static byte[] _http_parser_trans_targs_wi = [
	2, 0, 3, 38, 4, 24, 28, 25, 
	5, 20, 6, 7, 8, 9, 10, 11, 
	12, 13, 14, 15, 16, 17, 57, 17, 
	18, 19, 14, 18, 19, 5, 21, 22, 
	21, 22, 23, 24, 25, 26, 27, 5, 
	28, 20, 29, 31, 34, 30, 31, 32, 
	34, 33, 5, 35, 20, 36, 5, 35, 
	20, 36, 37, 39, 40, 41, 42, 43, 
	44, 45, 46, 47, 48, 49, 50, 51, 
	52, 53, 54, 55, 56
];

static byte[] _http_parser_trans_actions_wi = [
	1, 0, 11, 0, 1, 1, 1, 1, 
	13, 13, 1, 0, 0, 0, 0, 0, 
	0, 0, 19, 0, 0, 25, 23, 3, 
	5, 7, 9, 7, 0, 15, 1, 1, 
	0, 0, 0, 0, 0, 0, 0, 31, 
	0, 31, 0, 21, 21, 0, 0, 0, 
	0, 0, 34, 17, 34, 17, 28, 0, 
	28, 0, 0, 0, 0, 0, 0, 0, 
	0, 0, 0, 0, 0, 0, 0, 0, 
	0, 0, 0, 0, 0
];

static int http_parser_start = 1;
static int http_parser_first_final = 57;
static int http_parser_error = 0;

static int http_parser_en_main = 1;

//#line 130 "http11_parser.rl"

this ()  
{
  cs = 0;
  
//#line 255 "http11_parser.d"
	{
	cs = http_parser_start;
	}
//#line 135 "http11_parser.rl"
  
  body_start = 0;
  content_len = 0;
  mark = 0;
  nread = 0;
  field_len = 0;
  field_start = 0;    
}


/** exec **/
public size_t execute(char[] buffer, size_t off = 0)  {
  char* p, pe;
  int len = buffer.length;

  assert(off <= len && "offset past end of buffer");

  p = buffer.ptr+off;
  pe = buffer.ptr+len;

  /* assert(*pe == '\0' && "pointer does not end on NUL"); */
  assert(pe - p == len - off && "pointers aren't same distance");

  
//#line 284 "http11_parser.d"
	{
	int _klen;
	uint _trans;
	byte* _acts;
	uint _nacts;
	char* _keys;

	if ( p == pe )
		goto _out;
	if ( cs == 0 )
		goto _out;
_resume:
	_keys = &_http_parser_trans_keys[_http_parser_key_offsets[cs]];
	_trans = _http_parser_index_offsets[cs];

	_klen = _http_parser_single_lengths[cs];
	if ( _klen > 0 ) {
		char* _lower = _keys;
		char* _mid;
		char* _upper = _keys + _klen - 1;
		while (1) {
			if ( _upper < _lower )
				break;

			_mid = _lower + ((_upper-_lower) >> 1);
			if ( (*p) < *_mid )
				_upper = _mid - 1;
			else if ( (*p) > *_mid )
				_lower = _mid + 1;
			else {
				_trans += (_mid - _keys);
				goto _match;
			}
		}
		_keys += _klen;
		_trans += _klen;
	}

	_klen = _http_parser_range_lengths[cs];
	if ( _klen > 0 ) {
		char* _lower = _keys;
		char* _mid;
		char* _upper = _keys + (_klen<<1) - 2;
		while (1) {
			if ( _upper < _lower )
				break;

			_mid = _lower + (((_upper-_lower) >> 1) & ~1);
			if ( (*p) < _mid[0] )
				_upper = _mid - 2;
			else if ( (*p) > _mid[1] )
				_lower = _mid + 2;
			else {
				_trans += ((_mid - _keys)>>1);
				goto _match;
			}
		}
		_trans += _klen;
	}

_match:
	_trans = _http_parser_indicies[_trans];
	cs = _http_parser_trans_targs_wi[_trans];

	if ( _http_parser_trans_actions_wi[_trans] == 0 )
		goto _again;

	_acts = &_http_parser_actions[_http_parser_trans_actions_wi[_trans]];
	_nacts = cast(uint) *_acts++;
	while ( _nacts-- > 0 )
	{
		switch ( *_acts++ )
		{
	case 0:
//#line 67 "http11_parser.rl"
	{buffer.MARK(&mark, p); }
	break;
	case 1:
//#line 70 "http11_parser.rl"
	{ buffer.MARK(&field_start, p); }
	break;
	case 2:
//#line 71 "http11_parser.rl"
	{ snake_upcase_char(cast(char *)p); }
	break;
	case 3:
//#line 72 "http11_parser.rl"
	{ 
    field_len = buffer.LEN(field_start, p);
  }
	break;
	case 4:
//#line 76 "http11_parser.rl"
	{ buffer.MARK(&mark, p); }
	break;
	case 5:
//#line 77 "http11_parser.rl"
	{ 
    if(http_field) 
      http_field(data, 
                 buffer[field_start .. field_start+field_len], 
                 buffer[mark .. $]);
  }
	break;
	case 6:
//#line 85 "http11_parser.rl"
	{ 
    if(request_method) 
      request_method(data, buffer[mark .. $]);
  }
	break;
	case 7:
//#line 90 "http11_parser.rl"
	{ 
    if(request_uri)
      request_uri(data, buffer[mark .. $]);
  }
	break;
	case 8:
//#line 95 "http11_parser.rl"
	{ 
    if(fragment)
      fragment(data, buffer[mark .. $]);
  }
	break;
	case 9:
//#line 100 "http11_parser.rl"
	{buffer.MARK(&query_start, p); }
	break;
	case 10:
//#line 102 "http11_parser.rl"
	{ 
    if(query_string)
      query_string(data, buffer[query_start .. $]);
  }
	break;
	case 11:
//#line 107 "http11_parser.rl"
	{	
    if(http_version)
      http_version(data, buffer[mark .. $]);
  }
	break;
	case 12:
//#line 112 "http11_parser.rl"
	{
    if(request_path)
      request_path(data, buffer[mark .. $]);
  }
	break;
	case 13:
//#line 117 "http11_parser.rl"
	{ 
    body_start = p - buffer.ptr + 1; 
    if(header_done)
      header_done(data, p[1 .. (pe - p - 1)]);
    if (true) goto _out;
  }
	break;
//#line 446 "http11_parser.d"
		default: break;
		}
	}

_again:
	if ( cs == 0 )
		goto _out;
	if ( ++p != pe )
		goto _resume;
	_out: {}
	}
//#line 159 "http11_parser.rl"

  //parser->cs = cs;
  nread += p - (buffer.ptr + off);

  assert(p <= pe && "buffer overflow after parsing execute");
  assert(nread <= len && "nread longer than length");
  assert(body_start <= len && "body starts after buffer end");
  assert(mark < len && "mark is after buffer end");
  assert(field_len <= len && "field has length longer than whole buffer");
  assert(field_start < len && "field starts after buffer end");

  return(nread);
}

public int finish()
{
  if (has_error() ) {
    return -1;
  } else if (is_finished() ) {
    return 1;
  } else {
    return 0;
  }
}

public bool has_error() {
  return cs == http_parser_error;
}

public bool is_finished() {
  return cs >= http_parser_first_final;
}

public void setData(Object d)
{
    data = d;
}
}