From 0089842c454e51367a10dd86856cca8884bd2f01 Mon Sep 17 00:00:00 2001
From: Paul Duncan <pabs@pablotron.org>
Date: Sun, 28 Aug 2016 00:37:50 -0400
Subject: add internal.h and te-parser.c

---
 Makefile    |   4 +-
 env.c       |   3 +-
 error.c     |   3 +-
 fhp.c       | 403 +-----------------------------------------------------------
 hash.c      |   3 +-
 internal.h  | 200 ++++++++++++++++++++++++++++++
 te-parser.c | 203 ++++++++++++++++++++++++++++++
 token.c     |   3 +-
 8 files changed, 410 insertions(+), 412 deletions(-)
 create mode 100644 internal.h
 create mode 100644 te-parser.c

diff --git a/Makefile b/Makefile
index 32976d7..7878027 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 CC ?= cc
 CFLAGS=-std=c99 -W -Wall -pedantic -O2 -Iinclude -fPIC
-OBJS=fhp.o hash.o error.o token.o env.o
+OBJS=fhp.o hash.o error.o token.o env.o te-parser.o
 SONAME=libfhp.so
 LIB=libfhp.so
 
@@ -22,5 +22,5 @@ $(LIB): $(OBJS)
 $(TEST_APP): $(LIB) $(TEST_OBJS)
 	$(CC) -o $(TEST_APP) $(TEST_OBJS) $(TEST_LDFLAGS)
 
-%.o: %.c include/fhp/fhp.h
+%.o: %.c internal.h include/fhp/fhp.h
 	$(CC) -c $(CFLAGS) $<
diff --git a/env.c b/env.c
index 721d392..8994598 100644
--- a/env.c
+++ b/env.c
@@ -1,5 +1,4 @@
-#include <string.h>
-#include "fhp/fhp.h"
+#include "internal.h"
 
 static char * const
 fhp_strings[] = {
diff --git a/error.c b/error.c
index e88ab4f..3a5ea9c 100644
--- a/error.c
+++ b/error.c
@@ -1,5 +1,4 @@
-#include <string.h>
-#include "fhp/fhp.h"
+#include "internal.h"
 
 //
 // error functions
diff --git a/fhp.c b/fhp.c
index 917141d..a2ba7a2 100644
--- a/fhp.c
+++ b/fhp.c
@@ -1,405 +1,4 @@
-#include <string.h>
-#include "fhp/fhp.h"
-
-#define UNUSED(a) ((void) (a))
-
-#define CASE_ALNUM_CHARS \
-  case '0': \
-  case '1': \
-  case '2': \
-  case '3': \
-  case '4': \
-  case '5': \
-  case '6': \
-  case '7': \
-  case '8': \
-  case '9': \
-  case 'a': \
-  case 'b': \
-  case 'c': \
-  case 'd': \
-  case 'e': \
-  case 'f': \
-  case 'g': \
-  case 'h': \
-  case 'i': \
-  case 'j': \
-  case 'k': \
-  case 'l': \
-  case 'm': \
-  case 'n': \
-  case 'o': \
-  case 'p': \
-  case 'q': \
-  case 'r': \
-  case 's': \
-  case 't': \
-  case 'u': \
-  case 'v': \
-  case 'w': \
-  case 'x': \
-  case 'y': \
-  case 'z': \
-  case 'A': \
-  case 'B': \
-  case 'C': \
-  case 'D': \
-  case 'E': \
-  case 'F': \
-  case 'G': \
-  case 'H': \
-  case 'I': \
-  case 'J': \
-  case 'K': \
-  case 'L': \
-  case 'M': \
-  case 'N': \
-  case 'O': \
-  case 'P': \
-  case 'Q': \
-  case 'R': \
-  case 'S': \
-  case 'T': \
-  case 'U': \
-  case 'V': \
-  case 'W': \
-  case 'X': \
-  case 'Y': \
-  case 'Z':
-
-#define CASE_DIGIT_CHARS \
-  case '0': \
-  case '1': \
-  case '2': \
-  case '3': \
-  case '4': \
-  case '5': \
-  case '6': \
-  case '7': \
-  case '8': \
-  case '9':
-
-#define CASE_HEX_ALPHA_CHARS \
-  case 'a': \
-  case 'b': \
-  case 'c': \
-  case 'd': \
-  case 'e': \
-  case 'f': \
-  case 'A': \
-  case 'B': \
-  case 'C': \
-  case 'D': \
-  case 'E': \
-  case 'F':
-
-//
-// rfc7230, Appendix B
-// https://tools.ietf.org/html/rfc7230
-//
-//   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
-//           "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
-//   token = 1*tchar
-//
-#define CASE_TOKEN_CHARS \
-  CASE_ALNUM_CHARS \
-  case '!': \
-  case '#': \
-  case '$': \
-  case '%': \
-  case '&': \
-  case '\'': \
-  case '*': \
-  case '+': \
-  case '-': \
-  case '.': \
-  case '^': \
-  case '_': \
-  case '|': \
-  case '~': \
-
-#define CASE_URL_CHARS \
-  CASE_ALNUM_CHARS \
-  case '!': \
-  case '"': \
-  case '#': \
-  case '$': \
-  case '&': \
-  case '\'': \
-  case '(': \
-  case ')': \
-  case '*': \
-  case '+': \
-  case ',': \
-  case '-': \
-  case '.': \
-  case '/': \
-  case ':': \
-  case ';': \
-  case '<': \
-  case '=': \
-  case '>': \
-  case '?': \
-  case '@': \
-  case '[': \
-  case '\\': \
-  case ']': \
-  case '^': \
-  case '_': \
-  case '`': \
-  case '{': \
-  case '|': \
-  case '}': \
-  case '~':
-
-#define CASE_VISUAL_CHARS \
-  CASE_URL_CHARS \
-  case '%':
-
-#define CASE_VERSION_CHARS \
-  CASE_TOKEN_CHARS \
-  case '/':
-
-#define CASE_TE_CHARS \
-  CASE_ALNUM_CHARS \
-  case '-':
-
-//
-// rfc7230, Appendix B
-// https://tools.ietf.org/html/rfc7230
-//
-//   OWS = *( SP / HTAB )
-//
-#define CASE_OWS_CHARS \
-  case ' ': \
-  case '\t':
-
-//
-// strings
-//
-
-typedef enum {
-  FHP_STR_GET,
-  FHP_STR_POST,
-  FHP_STR_HEAD,
-  FHP_STR_PUT,
-  FHP_STR_DELETE,
-  FHP_STR_OPTIONS,
-  FHP_STR_HTTP_10,
-  FHP_STR_HTTP_11,
-  FHP_STR_CONTENT_LENGTH,
-  FHP_STR_TRANSFER_ENCODING,
-  FHP_STR_GZIP,
-  FHP_STR_X_GZIP,
-  FHP_STR_DEFLATE,
-  FHP_STR_X_DEFLATE,
-  FHP_STR_COMPRESS,
-  FHP_STR_X_COMPRESS,
-  FHP_STR_CHUNKED,
-  FHP_STR_LAST
-} fhp_str_t;
-
-//
-// transfer encoding buffer functions
-//
-
-static void
-fhp_te_parser_buf_flush(fhp_te_parser_t * const te) {
-  te->buf_hash = fhp_lc_hash_push(te->buf_hash, te->buf, te->len);
-  te->len = 0;
-}
-
-static void
-fhp_te_parser_buf_push(
-  fhp_te_parser_t * const te,
-  uint8_t byte
-) {
-  // flush buffer (if necessary)
-  if (te->len + 1 >= FHP_TE_MAX_BUF_SIZE)
-    fhp_te_parser_buf_flush(te);
-
-  // push to buffer
-  te->buf[te->len] = byte;
-  te->len++;
-}
-
-//
-// transfer encoding parser functions
-//
-
-static const fhp_te_parser_t FHP_DEFAULT_TE_PARSER = {
-  .state = FHP_TE_STATE_INIT,
-  .len = 0,
-  .num_tes = 0,
-  .err = FHP_OK,
-};
-
-fhp_err_t
-fhp_te_parser_init(fhp_te_parser_t * const te) {
-  // init parser
-  *te = FHP_DEFAULT_TE_PARSER;
-
-  // return succes
-  return FHP_OK;
-}
-
-static fhp_err_t
-fhp_te_parser_push_byte(
-  fhp_te_parser_t * const te,
-  uint8_t byte
-) {
-retry:
-  switch (te->state) {
-  case FHP_TE_STATE_INIT:
-    // set state
-    te->state = FHP_TE_STATE_SPACE;
-    goto retry;
-
-    break;
-  case FHP_TE_STATE_NAME:
-    switch (byte) {
-    CASE_TE_CHARS
-      // add to buffer
-      fhp_te_parser_buf_push(te, byte);
-
-      break;
-    CASE_OWS_CHARS
-      // flush buffer (if necessary)
-      if (te->len > 0)
-        fhp_te_parser_buf_flush(te);
-
-      // check number of encodings
-      if (te->num_tes + 1 >= FHP_TE_MAX_TES)
-        return FHP_ERR_TOO_MANY_TES;
-
-      // add to list of transfer encodings
-      // FIXME: check length
-      te->tes[te->num_tes] = te->buf_hash;
-      te->num_tes++;
-
-      // set state
-      te->state = FHP_TE_STATE_IGNORE_UNTIL_COMMA;
-
-      break;
-    case ',':
-      // flush buffer (if necessary)
-      if (te->len > 0)
-        fhp_te_parser_buf_flush(te);
-
-      // check number of encodings
-      if (te->num_tes + 1 >= FHP_TE_MAX_TES)
-        return FHP_ERR_TOO_MANY_TES;
-
-      // add to list of transfer encodings
-      // FIXME: check length
-      te->tes[te->num_tes] = te->buf_hash;
-      te->num_tes++;
-
-      // set state
-      te->state = FHP_TE_STATE_SPACE;
-
-      break;
-    default:
-      // invalid transfer encoding character
-      return FHP_ERR_INVALID_CHAR_IN_TE_NAME;
-    }
-
-    break;
-  case FHP_TE_STATE_IGNORE_UNTIL_COMMA:
-    switch (byte) {
-    case ',':
-      // set state
-      te->state = FHP_TE_STATE_SPACE;
-
-      break;
-    default:
-      // do nothing (ignore)
-      NULL;
-    }
-
-    break;
-  case FHP_TE_STATE_SPACE:
-    switch (byte) {
-    CASE_OWS_CHARS
-      // ignore leading spaces
-      break;
-    CASE_TE_CHARS
-      // clear buffer, init hash
-      te->len = 0;
-      te->buf_hash = fhp_hash_init();
-
-      // set state
-      te->state = FHP_TE_STATE_NAME;
-      goto retry;
-
-      break;
-    default:
-      // return error
-      return FHP_ERR_INVALID_CHAR_IN_TE;
-    }
-
-    break;
-  case FHP_TE_STATE_ERROR:
-    // return last error
-    return te->err;
-
-    break;
-  case FHP_TE_STATE_DONE:
-    // shouldn't be reached
-    return FHP_ERR_TE_PARSER_DONE;
-
-    break;
-  default:
-    // never reached
-    return FHP_ERR_BAD_TE_STATE;
-  }
-
-  // return succes
-  return FHP_OK;
-}
-
-fhp_err_t
-fhp_te_parser_push(
-  fhp_te_parser_t *te,
-  uint8_t * const buf,
-  size_t len
-) {
-  for (size_t i = 0; i < len; i++) {
-    // push byte
-    fhp_err_t err = fhp_te_parser_push_byte(te, buf[len]);
-
-    // check error
-    if (err != FHP_OK) {
-      // cache error
-      te->err = err;
-
-      // set state
-      te->state = FHP_TE_STATE_ERROR;
-
-      // return error
-      return err;
-    }
-  }
-
-  // return succes
-  return FHP_OK;
-}
-
-fhp_err_t
-fhp_te_parser_done(fhp_te_parser_t * const te) {
-  uint8_t buf[1] = { 20 };
-
-  // flush data, check for error
-  fhp_err_t err = fhp_te_parser_push(te, buf, 1);
-  if (err != FHP_OK)
-    return err;
-
-  // set state
-  te->state = FHP_TE_STATE_DONE;
-
-  // return success
-  return FHP_OK;
-}
+#include "internal.h"
 
 //
 // context functions
diff --git a/hash.c b/hash.c
index deae792..c35590e 100644
--- a/hash.c
+++ b/hash.c
@@ -1,5 +1,4 @@
-#include <string.h>
-#include "fhp/fhp.h"
+#include "internal.h"
 
 //
 // hash functions (djb2)
diff --git a/internal.h b/internal.h
new file mode 100644
index 0000000..94caebd
--- /dev/null
+++ b/internal.h
@@ -0,0 +1,200 @@
+#include <string.h>
+#include "fhp/fhp.h"
+
+#define UNUSED(a) ((void) (a))
+
+#define CASE_ALNUM_CHARS \
+  case '0': \
+  case '1': \
+  case '2': \
+  case '3': \
+  case '4': \
+  case '5': \
+  case '6': \
+  case '7': \
+  case '8': \
+  case '9': \
+  case 'a': \
+  case 'b': \
+  case 'c': \
+  case 'd': \
+  case 'e': \
+  case 'f': \
+  case 'g': \
+  case 'h': \
+  case 'i': \
+  case 'j': \
+  case 'k': \
+  case 'l': \
+  case 'm': \
+  case 'n': \
+  case 'o': \
+  case 'p': \
+  case 'q': \
+  case 'r': \
+  case 's': \
+  case 't': \
+  case 'u': \
+  case 'v': \
+  case 'w': \
+  case 'x': \
+  case 'y': \
+  case 'z': \
+  case 'A': \
+  case 'B': \
+  case 'C': \
+  case 'D': \
+  case 'E': \
+  case 'F': \
+  case 'G': \
+  case 'H': \
+  case 'I': \
+  case 'J': \
+  case 'K': \
+  case 'L': \
+  case 'M': \
+  case 'N': \
+  case 'O': \
+  case 'P': \
+  case 'Q': \
+  case 'R': \
+  case 'S': \
+  case 'T': \
+  case 'U': \
+  case 'V': \
+  case 'W': \
+  case 'X': \
+  case 'Y': \
+  case 'Z':
+
+#define CASE_DIGIT_CHARS \
+  case '0': \
+  case '1': \
+  case '2': \
+  case '3': \
+  case '4': \
+  case '5': \
+  case '6': \
+  case '7': \
+  case '8': \
+  case '9':
+
+#define CASE_HEX_ALPHA_CHARS \
+  case 'a': \
+  case 'b': \
+  case 'c': \
+  case 'd': \
+  case 'e': \
+  case 'f': \
+  case 'A': \
+  case 'B': \
+  case 'C': \
+  case 'D': \
+  case 'E': \
+  case 'F':
+
+//
+// rfc7230, Appendix B
+// https://tools.ietf.org/html/rfc7230
+//
+//   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
+//           "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
+//   token = 1*tchar
+//
+#define CASE_TOKEN_CHARS \
+  CASE_ALNUM_CHARS \
+  case '!': \
+  case '#': \
+  case '$': \
+  case '%': \
+  case '&': \
+  case '\'': \
+  case '*': \
+  case '+': \
+  case '-': \
+  case '.': \
+  case '^': \
+  case '_': \
+  case '|': \
+  case '~': \
+
+#define CASE_URL_CHARS \
+  CASE_ALNUM_CHARS \
+  case '!': \
+  case '"': \
+  case '#': \
+  case '$': \
+  case '&': \
+  case '\'': \
+  case '(': \
+  case ')': \
+  case '*': \
+  case '+': \
+  case ',': \
+  case '-': \
+  case '.': \
+  case '/': \
+  case ':': \
+  case ';': \
+  case '<': \
+  case '=': \
+  case '>': \
+  case '?': \
+  case '@': \
+  case '[': \
+  case '\\': \
+  case ']': \
+  case '^': \
+  case '_': \
+  case '`': \
+  case '{': \
+  case '|': \
+  case '}': \
+  case '~':
+
+#define CASE_VISUAL_CHARS \
+  CASE_URL_CHARS \
+  case '%':
+
+#define CASE_VERSION_CHARS \
+  CASE_TOKEN_CHARS \
+  case '/':
+
+#define CASE_TE_CHARS \
+  CASE_ALNUM_CHARS \
+  case '-':
+
+//
+// rfc7230, Appendix B
+// https://tools.ietf.org/html/rfc7230
+//
+//   OWS = *( SP / HTAB )
+//
+#define CASE_OWS_CHARS \
+  case ' ': \
+  case '\t':
+
+//
+// strings
+//
+
+typedef enum {
+  FHP_STR_GET,
+  FHP_STR_POST,
+  FHP_STR_HEAD,
+  FHP_STR_PUT,
+  FHP_STR_DELETE,
+  FHP_STR_OPTIONS,
+  FHP_STR_HTTP_10,
+  FHP_STR_HTTP_11,
+  FHP_STR_CONTENT_LENGTH,
+  FHP_STR_TRANSFER_ENCODING,
+  FHP_STR_GZIP,
+  FHP_STR_X_GZIP,
+  FHP_STR_DEFLATE,
+  FHP_STR_X_DEFLATE,
+  FHP_STR_COMPRESS,
+  FHP_STR_X_COMPRESS,
+  FHP_STR_CHUNKED,
+  FHP_STR_LAST
+} fhp_str_t;
diff --git a/te-parser.c b/te-parser.c
new file mode 100644
index 0000000..507038b
--- /dev/null
+++ b/te-parser.c
@@ -0,0 +1,203 @@
+#include "internal.h"
+
+//
+// transfer encoding buffer functions
+//
+
+static void
+fhp_te_parser_buf_flush(fhp_te_parser_t * const te) {
+  te->buf_hash = fhp_lc_hash_push(te->buf_hash, te->buf, te->len);
+  te->len = 0;
+}
+
+static void
+fhp_te_parser_buf_push(
+  fhp_te_parser_t * const te,
+  uint8_t byte
+) {
+  // flush buffer (if necessary)
+  if (te->len + 1 >= FHP_TE_MAX_BUF_SIZE)
+    fhp_te_parser_buf_flush(te);
+
+  // push to buffer
+  te->buf[te->len] = byte;
+  te->len++;
+}
+
+//
+// transfer encoding parser functions
+//
+
+static const fhp_te_parser_t FHP_DEFAULT_TE_PARSER = {
+  .state = FHP_TE_STATE_INIT,
+  .len = 0,
+  .num_tes = 0,
+  .err = FHP_OK,
+};
+
+fhp_err_t
+fhp_te_parser_init(fhp_te_parser_t * const te) {
+  // init parser
+  *te = FHP_DEFAULT_TE_PARSER;
+
+  // return succes
+  return FHP_OK;
+}
+
+static fhp_err_t
+fhp_te_parser_push_byte(
+  fhp_te_parser_t * const te,
+  uint8_t byte
+) {
+retry:
+  switch (te->state) {
+  case FHP_TE_STATE_INIT:
+    // set state
+    te->state = FHP_TE_STATE_SPACE;
+    goto retry;
+
+    break;
+  case FHP_TE_STATE_NAME:
+    switch (byte) {
+    CASE_TE_CHARS
+      // add to buffer
+      fhp_te_parser_buf_push(te, byte);
+
+      break;
+    CASE_OWS_CHARS
+      // flush buffer (if necessary)
+      if (te->len > 0)
+        fhp_te_parser_buf_flush(te);
+
+      // check number of encodings
+      if (te->num_tes + 1 >= FHP_TE_MAX_TES)
+        return FHP_ERR_TOO_MANY_TES;
+
+      // add to list of transfer encodings
+      // FIXME: check length
+      te->tes[te->num_tes] = te->buf_hash;
+      te->num_tes++;
+
+      // set state
+      te->state = FHP_TE_STATE_IGNORE_UNTIL_COMMA;
+
+      break;
+    case ',':
+      // flush buffer (if necessary)
+      if (te->len > 0)
+        fhp_te_parser_buf_flush(te);
+
+      // check number of encodings
+      if (te->num_tes + 1 >= FHP_TE_MAX_TES)
+        return FHP_ERR_TOO_MANY_TES;
+
+      // add to list of transfer encodings
+      // FIXME: check length
+      te->tes[te->num_tes] = te->buf_hash;
+      te->num_tes++;
+
+      // set state
+      te->state = FHP_TE_STATE_SPACE;
+
+      break;
+    default:
+      // invalid transfer encoding character
+      return FHP_ERR_INVALID_CHAR_IN_TE_NAME;
+    }
+
+    break;
+  case FHP_TE_STATE_IGNORE_UNTIL_COMMA:
+    switch (byte) {
+    case ',':
+      // set state
+      te->state = FHP_TE_STATE_SPACE;
+
+      break;
+    default:
+      // do nothing (ignore)
+      NULL;
+    }
+
+    break;
+  case FHP_TE_STATE_SPACE:
+    switch (byte) {
+    CASE_OWS_CHARS
+      // ignore leading spaces
+      break;
+    CASE_TE_CHARS
+      // clear buffer, init hash
+      te->len = 0;
+      te->buf_hash = fhp_hash_init();
+
+      // set state
+      te->state = FHP_TE_STATE_NAME;
+      goto retry;
+
+      break;
+    default:
+      // return error
+      return FHP_ERR_INVALID_CHAR_IN_TE;
+    }
+
+    break;
+  case FHP_TE_STATE_ERROR:
+    // return last error
+    return te->err;
+
+    break;
+  case FHP_TE_STATE_DONE:
+    // shouldn't be reached
+    return FHP_ERR_TE_PARSER_DONE;
+
+    break;
+  default:
+    // never reached
+    return FHP_ERR_BAD_TE_STATE;
+  }
+
+  // return succes
+  return FHP_OK;
+}
+
+fhp_err_t
+fhp_te_parser_push(
+  fhp_te_parser_t *te,
+  uint8_t * const buf,
+  size_t len
+) {
+  for (size_t i = 0; i < len; i++) {
+    // push byte
+    fhp_err_t err = fhp_te_parser_push_byte(te, buf[len]);
+
+    // check error
+    if (err != FHP_OK) {
+      // cache error
+      te->err = err;
+
+      // set state
+      te->state = FHP_TE_STATE_ERROR;
+
+      // return error
+      return err;
+    }
+  }
+
+  // return succes
+  return FHP_OK;
+}
+
+fhp_err_t
+fhp_te_parser_done(fhp_te_parser_t * const te) {
+  uint8_t buf[1] = { 20 };
+
+  // flush data, check for error
+  fhp_err_t err = fhp_te_parser_push(te, buf, 1);
+  if (err != FHP_OK)
+    return err;
+
+  // set state
+  te->state = FHP_TE_STATE_DONE;
+
+  // return success
+  return FHP_OK;
+}
diff --git a/token.c b/token.c
index d32c952..4e5dbfc 100644
--- a/token.c
+++ b/token.c
@@ -1,5 +1,4 @@
-#include <string.h>
-#include "fhp/fhp.h"
+#include "internal.h"
 
 //
 // token functions
-- 
cgit v1.2.3