httpp-benchmark

httpp-benchmark.git
git clone git://git.lenczewski.org/httpp-benchmark.git
Log | Files | Refs | README | LICENSE

commit 223a7eee1a93f61f1cd381cdc790faacfc6fd3be
parent eb01fd0234ade747eea2d425829d6fc66553f30c
Author: cebem1nt <mineewarik@gmail.com>
Date:   Sun, 23 Nov 2025 22:44:57 -0300

Bugfixes, removed nomem function, now returning NULL

Diffstat:
Mhttpp.h | 139++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Mtest.c | 14++++++++++++++
2 files changed, 95 insertions(+), 58 deletions(-)

diff --git a/httpp.h b/httpp.h @@ -9,16 +9,19 @@ #include <stdlib.h> #include <string.h> -#define _HTTPP_LINE_BUFSIZE 4096 -#define _HTTPP_INITIAL_HEADERS_ARR_CAP 20 +#define HTTPP_LINE_BUFSIZE 4096 +#define HTTPP_INITIAL_HEADERS_ARR_CAP 20 -#define _HTTPP_MAX_METHOD_LENGTH (10 + 1) -#define _HTTPP_VERSION_BUFSIZE (10 + 1) +#define HTTPP_MAX_METHOD_LENGTH (10 + 1) +#define HTTPP_VERSION_BUFSIZE (10 + 1) #define httpp_string_to_method(s) (strcmp(s, "GET") == 0 ? 0 : \ strcmp(s, "POST") == 0 ? 1 : \ strcmp(s, "DELETE") == 0 ? 2 : -1) +#define HTTPP_ERRMEMRY 3 +#define HTTPP_ERRLOGIC 1 + typedef enum { GET, POST, @@ -49,45 +52,33 @@ http_req_t* httpp_req_new(); http_req_t* httpp_parse_request(char* raw); int httpp_parse_header(http_headers_arr_t* hs, char* line); -void httpp_headers_append(http_headers_arr_t* hs, http_header_t header); +int httpp_headers_append(http_headers_arr_t* hs, http_header_t header); +void http_headers_arr_free(http_headers_arr_t* hs); void httpp_req_free(http_req_t* req); +#define HTTPP_IMPLEMENTATION #ifdef HTTPP_IMPLEMENTATION #define HTTP_DELIMITER "\r\n" #define HTTP_DELIMITER_SIZE 2 #define HTTP_VERSION "HTTP/1.1" -#define nomem() do { fprintf(stderr, "No memory, see ya!\n"); exit(1); } while (0) -#define ltrim(str) \ - while(*(str) && isspace(*(str))) { \ - (str)++; \ - } +#define trim(str) do { ltrim(str); rtrim(str); } while (0) -#define rtrim(str) do { \ - char* end = (str) + strlen(str) - 1; \ - while (end >= (str) && isspace(*end)) { \ - *end = '\0'; \ - --end; \ +#define ltrim(str) do { \ + char* __str = (str); \ + while(*__str && isspace(*__str)) { \ + __str++; \ } \ } while (0) -static inline void* emalloc(size_t size) -{ - void* ptr = malloc(size); - if (!ptr) - nomem(); - - return ptr; -} - -static inline void* erealloc(void* ptr, size_t size) -{ - void* new_ptr = realloc(ptr, size); - if (!new_ptr) - nomem(); - return new_ptr; -} +#define rtrim(str) do { \ + char* __str = (str); \ + char* end = __str + strlen(__str) - 1; \ + while (end >= __str && isspace(*end)) { \ + *end-- = '\0'; \ + } \ + } while (0) static int chop_until(char c, char** src, char* dest, size_t n) { @@ -113,7 +104,9 @@ static char* dchop_until(char c, char** src) return NULL; size_t chopped_size = pos - *src; - char* out = (char*) emalloc(chopped_size + 1); + char* out = (char*) malloc(chopped_size + 1); + if (!out) + return NULL; memcpy(out, *src, chopped_size); out[chopped_size] = '\0'; @@ -134,11 +127,24 @@ const char* httpp_method_to_string(http_method_t m) http_req_t* httpp_req_new() { - http_req_t* out = (http_req_t*) emalloc(sizeof(http_req_t)); + http_req_t* out = (http_req_t*) malloc(sizeof(http_req_t)); + if (!out) + return NULL; + + out->headers = (http_headers_arr_t*) malloc(sizeof(http_headers_arr_t)); + if (!out->headers) { + free(out); + return NULL; + } - out->headers = (http_headers_arr_t*) emalloc(sizeof(http_headers_arr_t)); - out->headers->arr = (http_header_t*) emalloc(sizeof(http_header_t) * _HTTPP_INITIAL_HEADERS_ARR_CAP); - out->headers->capacity = _HTTPP_INITIAL_HEADERS_ARR_CAP; + out->headers->arr = (http_header_t*) malloc(sizeof(http_header_t) * HTTPP_INITIAL_HEADERS_ARR_CAP); + if (!out->headers->arr) { + free(out->headers); + free(out); + return NULL; + } + + out->headers->capacity = HTTPP_INITIAL_HEADERS_ARR_CAP; out->headers->length = 0; out->route = NULL; out->body = NULL; @@ -146,14 +152,19 @@ http_req_t* httpp_req_new() return out; } -void httpp_req_free(http_req_t* req) +void http_headers_arr_free(http_headers_arr_t* hs) { - if (!req) return; - - for (size_t i = 0; i < req->headers->length; i++) { - free(req->headers->arr[i].name); - free(req->headers->arr[i].value); + if (!hs) return; + for (size_t i = 0; i < hs->length; i++) { + free(hs->arr[i].name); + free(hs->arr[i].value); } +} + +void httpp_req_free(http_req_t* req) +{ + if (!req) return; + http_headers_arr_free(req->headers); free(req->headers->arr); free(req->headers); @@ -162,51 +173,63 @@ void httpp_req_free(http_req_t* req) free(req); } -void httpp_headers_append(http_headers_arr_t* hs, http_header_t header) +int httpp_headers_append(http_headers_arr_t* hs, http_header_t header) { if (hs->length >= hs->capacity) { size_t new_cap = hs->capacity * 2; - hs->arr = (http_header_t*) erealloc(hs->arr, new_cap * sizeof(http_header_t)); + if (new_cap <= hs->capacity) // Doesn't free on failure. Make a note about it + return HTTPP_ERRMEMRY; + + hs->arr = (http_header_t*) realloc(hs->arr, new_cap * sizeof(http_header_t)); + if (!hs->arr) + return HTTPP_ERRMEMRY; + hs->capacity = new_cap; } hs->arr[hs->length++] = header; + return 0; } int httpp_parse_header(http_headers_arr_t* hs, char* line) { char* delim_pos = strchr(line, ':'); if (!delim_pos) - return 1; + return HTTPP_ERRLOGIC; size_t name_len = (delim_pos - line); if (name_len == 0) - return 2; + return HTTPP_ERRLOGIC; - char* name = (char*) emalloc(name_len + 1); + char* name = (char*) malloc(name_len + 1); + if (!name) + return HTTPP_ERRMEMRY; + memcpy(name, line, name_len); name[name_len] = '\0'; + trim(name); char* value_start = delim_pos + 1; - ltrim(value_start); + trim(value_start); char* value = strdup(value_start); if (!value) - nomem(); + return HTTPP_ERRMEMRY; + + if (httpp_headers_append(hs, (http_header_t){name, value}) != 0) + return HTTPP_ERRMEMRY; - httpp_headers_append(hs, (http_header_t){name, value}); return 0; } static int http_parse_start_line(char** itr, http_req_t* dest) { - char method_buf[_HTTPP_MAX_METHOD_LENGTH]; - char version_buf[_HTTPP_VERSION_BUFSIZE]; + char method_buf[HTTPP_MAX_METHOD_LENGTH]; + char version_buf[HTTPP_VERSION_BUFSIZE]; char* route; ltrim(*itr); - - if (chop_until(' ', itr, method_buf, _HTTPP_MAX_METHOD_LENGTH) != 0) + if (chop_until(' ', itr, method_buf, HTTPP_MAX_METHOD_LENGTH) != 0) return 1; ltrim(*itr); // Route might have extra spaces at the bginning, for our implementation thats fine @@ -214,12 +237,12 @@ static int http_parse_start_line(char** itr, http_req_t* dest) return 1; ltrim(*itr); - if (chop_until('\n', itr, version_buf, _HTTPP_VERSION_BUFSIZE) != 0) { + if (chop_until('\n', itr, version_buf, HTTPP_VERSION_BUFSIZE) != 0) { free(route); return 1; } - rtrim(version_buf); + trim(version_buf); if (strcmp(version_buf, HTTP_VERSION) != 0) { free(route); return 1; @@ -236,7 +259,7 @@ http_req_t* httpp_parse_request(char* raw) char* itr = raw; char* end = raw + strlen(raw); - char line[_HTTPP_LINE_BUFSIZE]; + char line[HTTPP_LINE_BUFSIZE]; if (http_parse_start_line(&itr, out) != 0) { httpp_req_free(out); @@ -254,7 +277,7 @@ http_req_t* httpp_parse_request(char* raw) break; } - if (line_size >= _HTTPP_LINE_BUFSIZE) { + if (line_size >= HTTPP_LINE_BUFSIZE) { httpp_req_free(out); return NULL; } diff --git a/test.c b/test.c @@ -52,6 +52,20 @@ int main() parsed = httpp_parse_request(req2); print(parsed); + httpp_req_free(parsed); + + char* req3 = + "POST /api/items HTTP/1.1\r\n" + "Host: api.example.com\r\n" + "User-Agent: MyClient/1.0\r\n" + "Content-Type: application/json; charset=utf-8\r\n" + "Content-Length: 106\r\n" + "X-Trace-ID: ;;--TRACE--;;\r\n" + "X-Feature-Flags: ,enable-new, ,\r\n" + "\r\n"; + + parsed = httpp_parse_request(req3); + print(parsed); return 0; } \ No newline at end of file