#ifndef FHP_H_ #define FHP_H #include // for uint8_t #include // for size_t #include // for size_t // // hash functions (djb2) // (see http://aras-p.info/blog/2016/08/02/Hash-Functions-all-the-way-down/) // uint32_t fhp_hash_init(void); uint32_t fhp_hash_push(uint32_t, uint8_t * const, size_t); uint32_t fhp_hash_string(char * const); uint32_t fhp_lc_hash_push(uint32_t, uint8_t * const, size_t); uint32_t fhp_lc_hash_string(char * const); // // error functions // typedef enum { FHP_OK, FHP_ERR_CB, FHP_ERR_BAD_STATE, FHP_ERR_INVALID_CHAR, FHP_ERR_INVALID_CHAR_IN_METHOD, FHP_ERR_INVALID_CHAR_IN_URL, FHP_ERR_INVALID_CHAR_IN_URL_PERCENT, FHP_ERR_INVALID_CHAR_IN_VERSION, FHP_ERR_INVALID_CHAR_AFTER_CR, FHP_ERR_INVALID_CHAR_IN_HEADER_NAME, FHP_ERR_INVALID_ERROR, FHP_ERR_BUFFER_TOO_SMALL, FHP_ERR_LAST } fhp_err_t; fhp_err_t fhp_strerror(fhp_err_t, char * const, size_t); // // token functions // typedef enum { FHP_TOKEN_METHOD_START, FHP_TOKEN_METHOD_FRAGMENT, FHP_TOKEN_METHOD_END, FHP_TOKEN_METHOD_GET, FHP_TOKEN_METHOD_POST, FHP_TOKEN_METHOD_HEAD, FHP_TOKEN_METHOD_PUT, FHP_TOKEN_METHOD_DELETE, FHP_TOKEN_METHOD_OPTIONS, FHP_TOKEN_METHOD_OTHER, FHP_TOKEN_URL_START, FHP_TOKEN_URL_FRAGMENT, FHP_TOKEN_URL_END, FHP_TOKEN_VERSION_START, FHP_TOKEN_VERSION_FRAGMENT, FHP_TOKEN_VERSION_END, FHP_TOKEN_VERSION_HTTP_10, FHP_TOKEN_VERSION_HTTP_11, FHP_TOKEN_VERSION_OTHER, FHP_TOKEN_HEADER_NAME_START, FHP_TOKEN_HEADER_NAME_FRAGMENT, FHP_TOKEN_HEADER_NAME_END, FHP_TOKEN_HEADER_VALUE_START, FHP_TOKEN_HEADER_VALUE_FRAGMENT, FHP_TOKEN_HEADER_VALUE_END, FHP_TOKEN_LAST } fhp_token_t; fhp_err_t fhp_strtoken(fhp_token_t, char * const, size_t); // // env functions // #define FHP_ENV_NUM_HASHES 6 typedef struct { uint32_t hashes[FHP_ENV_NUM_HASHES]; } fhp_env_t; void fhp_env_init(fhp_env_t * const env); fhp_env_t *fhp_get_default_env(void); // // context functions // typedef struct fhp_t_ fhp_t; typedef bool (*fhp_cb_t)( fhp_t * const, fhp_token_t, uint8_t * const, size_t ); typedef enum { FHP_STATE_INIT, FHP_STATE_ERROR, FHP_STATE_METHOD, FHP_STATE_METHOD_END, FHP_STATE_URL, FHP_STATE_URL_PERCENT, FHP_STATE_URL_PERCENT_LAST, FHP_STATE_URL_END, FHP_STATE_VERSION, FHP_STATE_VERSION_END, FHP_STATE_VERSION_END_CR, FHP_STATE_STATUS_END, FHP_STATE_STATUS_END_CR, FHP_STATE_HEADER_NAME, FHP_STATE_HEADER_NAME_END, FHP_STATE_HEADER_NAME_END_CR, FHP_STATE_HEADER_VALUE, FHP_STATE_HEADER_VALUE_END_CR, FHP_STATE_HEADER_VALUE_END, FHP_STATE_HEADERS_END, FHP_STATE_HEADERS_END_CR, FHP_STATE_LAST } fhp_state_t; #define FHP_BUF_SIZE 1024 struct fhp_t_ { // env pointer fhp_env_t *env; // opaque user data void *user_data; // current parser state fhp_state_t state; // user callback fhp_cb_t cb; // last error fhp_err_t err; // number of bytes read uint64_t ofs; // fragment data buffer uint8_t buf[FHP_BUF_SIZE]; size_t buf_len; // buffer hashing state bool is_hashing; uint32_t buf_hash; // cached http method and version fhp_token_t http_method, http_version; // state for url hex decoder uint32_t hex; }; fhp_err_t fhp_init(fhp_t * const, fhp_env_t * const, fhp_cb_t, void * const); fhp_err_t fhp_push(fhp_t * const, uint8_t * const, size_t); fhp_env_t * fhp_get_env(fhp_t * const); void * fhp_get_user_data(fhp_t * const); #endif /* FHP_H */