diff asyncdreactor/protocol/http11_parser.rl @ 11:5836613d16ac

reorg! reorg!
author rick@minifunk
date Tue, 12 Aug 2008 16:59:56 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/asyncdreactor/protocol/http11_parser.rl	Tue Aug 12 16:59:56 2008 -0400
@@ -0,0 +1,192 @@
+/**
+ * Copyright (c) 2005 Zed A. Shaw, 
+ * Modified for D/DReactor by Rick Richardson, 2008
+ * You can redistribute it and/or modify it under the same terms as Ruby.
+ */
+
+alias void delegate (void *data, const char *at, size_t length) element_cb;
+alias void delegate (void *data, const char *field, size_t flen, const char *value, size_t vlen) field_cb;
+
+class Http11Parser
+{
+  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;
+
+  void *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 int LEN(char* at, char* fpc)
+{
+    return (fpc - buffer.ptr - at);
+}
+
+//#define MARK(M,FPC) (parser->M = (FPC) - buffer)
+private void MARK(size_t* item, char* fpc)
+{
+    *item = fpc - buffer.ptr;
+}
+
+//#define PTR_TO(F) (buffer + parser->F)
+private char* PTR_TO(size_t F)
+{
+    return (buffer.ptr + F);
+}
+/** Machine **/
+
+%%{
+  
+  machine http_parser;
+
+  action mark {MARK(mark, fpc); }
+
+
+  action start_field { MARK(field_start, fpc); }
+  action snake_upcase_field { snake_upcase_char((char *)fpc); }
+  action write_field { 
+    field_len = LEN(field_start, fpc);
+  }
+
+  action start_value { MARK(mark, fpc); }
+  action write_value { 
+    if(http_field) 
+      http_field(data, 
+                 PTR_TO(field_start), 
+                 field_len, 
+                 PTR_TO(mark), 
+                 LEN(mark, fpc));
+  }
+  action request_method { 
+    if(request_method) 
+      request_method(data, PTR_TO(mark), LEN(mark, fpc));
+  }
+
+  action request_uri { 
+    if(request_uri)
+      request_uri(data, PTR_TO(mark), LEN(mark, fpc));
+  }
+
+  action fragment { 
+    if(fragment)
+      fragment(data, PTR_TO(mark), LEN(mark, fpc));
+  }
+
+  action start_query {MARK(query_start, fpc); }
+
+  action query_string { 
+    if(query_string)
+      query_string(data, PTR_TO(query_start), LEN(query_start, fpc));
+  }
+
+  action http_version {	
+    if(http_version)
+      http_version(data, PTR_TO(mark), LEN(mark, fpc));
+  }
+
+  action request_path {
+    if(request_path)
+      request_path(data, PTR_TO(mark), LEN(mark,fpc));
+  }
+
+  action done { 
+    body_start = fpc - buffer + 1; 
+    if(header_done)
+      header_done(data, fpc + 1, pe - fpc - 1);
+    fbreak;
+  }
+
+  include http_parser_common "http11_parser_common.rl";
+
+}%%
+
+/** Data **/
+%% write data;
+
+this ()  
+{
+  cs = 0;
+  %% write init;
+  
+  body_start = 0;
+  content_len = 0;
+  mark = 0;
+  nread = 0;
+  field_len = 0;
+  field_start = 0;    
+}
+
+
+/** exec **/
+size_t execute(const char[] buffer, size_t off)  {
+  const 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");
+
+  %% write exec;
+
+  //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);
+}
+
+int finish()
+{
+  if (has_error() ) {
+    return -1;
+  } else if (is_finished() ) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+bool has_error() {
+  return cs == http_parser_error;
+}
+
+bool is_finished() {
+  return cs >= http_parser_first_final;
+}
+
+}