From c10bcfa7def7a1093d78dcb15fd95388a633fc99 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Sun, 28 Aug 2016 03:22:19 -0400 Subject: add cl-parser.c --- cl-parser.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 cl-parser.c (limited to 'cl-parser.c') diff --git a/cl-parser.c b/cl-parser.c new file mode 100644 index 0000000..83863c5 --- /dev/null +++ b/cl-parser.c @@ -0,0 +1,150 @@ +#include "internal.h" + +// +// content length functions +// + +static const fhp_cl_parser_t FHP_DEFAULT_CL_PARSER = { + .state = FHP_CL_STATE_INIT, + .val = 0, + .err = FHP_OK, +}; + +fhp_err_t +fhp_cl_parser_init(fhp_cl_parser_t * const p) { + // init parser + *p = FHP_DEFAULT_CL_PARSER; + + // return succes + return FHP_OK; +} + +static fhp_err_t +fhp_cl_parser_push_byte( + fhp_cl_parser_t * const p, + uint8_t byte +) { +retry: + switch (p->state) { + case FHP_CL_STATE_INIT: + switch (byte) { + CASE_OWS_CHARS + // ignore + break; + CASE_DIGIT_CHARS + // set state + p->state = FHP_CL_STATE_DATA; + goto retry; + + break; + default: + // invalid character before content-length + return FHP_ERR_INVALID_CHAR_BEFORE_CL; + } + + break; + case FHP_CL_STATE_DATA: + switch (byte) { + CASE_OWS_CHARS + // set state + p->state = FHP_CL_STATE_TRAILING_SPACES; + goto retry; + + break; + CASE_DIGIT_CHARS + { + // cache old value + uint64_t old_val = p->val; + + // update value + p->val = p->val * 10 + (byte - '0'); + + // check for overflow + if (p->val < old_val) + return FHP_ERR_CL_OVERFLOW; + } + + break; + default: + // invalid character in content-length + return FHP_ERR_INVALID_CHAR_IN_CL; + } + + break; + case FHP_CL_STATE_TRAILING_SPACES: + switch (byte) { + CASE_OWS_CHARS + // ignore trailing spaces + + break; + default: + // invalid character after content-length + return FHP_ERR_INVALID_CHAR_AFTER_CL; + } + + break; + case FHP_CL_STATE_ERROR: + // return last error + return p->err; + + break; + case FHP_CL_STATE_DONE: + // shouldn't be reached + return FHP_ERR_CL_PARSER_DONE; + + break; + default: + // never reached + return FHP_ERR_BAD_CL_STATE; + } + + // return succes + return FHP_OK; +} + +fhp_err_t +fhp_cl_parser_push( + fhp_cl_parser_t *p, + uint8_t * const buf, + size_t len +) { + for (size_t i = 0; i < len; i++) { + // push byte + fhp_err_t err = fhp_cl_parser_push_byte(p, buf[i]); + + // check error + if (err != FHP_OK) { + // cache error + p->err = err; + + // set state + p->state = FHP_CL_STATE_ERROR; + + // return error + return err; + } + } + + // return succes + return FHP_OK; +} + +fhp_err_t +fhp_cl_parser_done( + fhp_cl_parser_t * const p, + uint64_t * const ret_val +) { + // check for error + if (p->err != FHP_OK) + return p->err; + + // set state + p->state = FHP_TE_STATE_DONE; + + // save number of tes + if (ret_val) + *ret_val = p->val; + + // return success + return FHP_OK; +} -- cgit v1.2.3