summaryrefslogtreecommitdiff
path: root/te-parser.c
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2016-08-28 00:37:50 -0400
committerPaul Duncan <pabs@pablotron.org>2016-08-28 00:37:50 -0400
commit0089842c454e51367a10dd86856cca8884bd2f01 (patch)
tree22837d11a1c7776f38b77ab487cbf2f759380e01 /te-parser.c
parent14b04c962ee670e459f3e829e701da7fe1e57048 (diff)
downloadlibfhp-0089842c454e51367a10dd86856cca8884bd2f01.tar.bz2
libfhp-0089842c454e51367a10dd86856cca8884bd2f01.zip
add internal.h and te-parser.c
Diffstat (limited to 'te-parser.c')
-rw-r--r--te-parser.c203
1 files changed, 203 insertions, 0 deletions
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;
+}