#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_CL_STATE_DONE; // save number of tes if (ret_val) *ret_val = p->val; // return success return FHP_OK; }