#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; }