diff --git a/CMakeLists.txt b/CMakeLists.txt index 091199b..fad8386 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,13 +5,6 @@ set(CMAKE_C_STANDARD 99) include(CheckIPOSupported) check_ipo_supported() -# Extra warnings, treat warnings as error -if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU") - SET(TH_WARNINGS -Wall -Wextra -Wpedantic -Werror) - message(STATUS "Using Clang/GNU compiler, enabling extra warnings: ${TH_WARNINGS}") - add_compile_options(${TH_WARNINGS}) -endif() - # Run gperf find_program(GPERF gperf) if (GPERF) @@ -92,6 +85,13 @@ add_library(tiny_http ) add_library(tiny_http::tiny_http ALIAS tiny_http) +# Extra warnings, treat warnings as error +if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU") + SET(TH_WOPTIONS -Wall -Wextra -Wpedantic -Werror -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Wconversion) + message(STATUS "Using Clang/GNU compiler, enabling extra warnings: ${TH_WOPTIONS}") + target_compile_options(tiny_http PRIVATE ${TH_WOPTIONS}) +endif() + # Link time optimization check_ipo_supported(RESULT ipo_supported) if (CMAKE_BUILD_TYPE STREQUAL "Release") diff --git a/README.md b/README.md index e6acbeb..fbd5e4f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ handler(void* userp, const th_request* req, th_response* resp) return TH_ERR_OK; } -int main() +int main(void) { th_server* server; th_server_create(&server, NULL); diff --git a/include/th.h b/include/th.h index eef4192..b61c7f0 100644 --- a/include/th.h +++ b/include/th.h @@ -172,13 +172,13 @@ typedef struct th_bind_opt { * @brief Date struct corresponding to the Date header in HTTP. Always in GMT. */ typedef struct th_date { - unsigned year : 16; - unsigned month : 8; - unsigned day : 8; - unsigned weekday : 8; - unsigned hour : 8; - unsigned minute : 8; - unsigned second : 8; + unsigned int year : 16; + unsigned int month : 8; + unsigned int day : 8; + unsigned int weekday : 8; + unsigned int hour : 8; + unsigned int minute : 8; + unsigned int second : 8; } th_date; typedef struct th_duration { diff --git a/src/th_align.h b/src/th_align.h index bedf473..1f969ad 100644 --- a/src/th_align.h +++ b/src/th_align.h @@ -3,9 +3,9 @@ #include -#define TH_ALIGNOF(type) offsetof(struct { char c; type member; }, member) -#define TH_ALIGNAS(align, ptr) ((void*)(((uintptr_t)(ptr) + ((align) - 1)) & ~((align) - 1))) -#define TH_ALIGNUP(n, align) (((n) + (align) - 1) & ~((align) - 1)) +#define TH_ALIGNOF(type) ((size_t)&(((struct { char c; type member; }*)0)->member)) +#define TH_ALIGNAS(align, ptr) ((void*)(((uintptr_t)(ptr) + ((uintptr_t)(align) - 1)) & ~((uintptr_t)(align) - 1))) +#define TH_ALIGNUP(n, align) (((n) + (size_t)(align) - 1) & ~((size_t)(align) - 1)) #define TH_ALIGNDOWN(n, align) ((n) & ~((align) - 1)) typedef long double th_max_align; diff --git a/src/th_allocator.c b/src/th_allocator.c index cc682c8..86818b2 100644 --- a/src/th_allocator.c +++ b/src/th_allocator.c @@ -58,7 +58,7 @@ th_default_allocator_set(th_allocator* allocator) /* th_arena_allocator implementation begin */ -TH_PRIVATE(void*) +TH_LOCAL(void*) th_arena_allocator_alloc(void* self, size_t size) { th_arena_allocator* allocator = self; @@ -73,7 +73,7 @@ th_arena_allocator_alloc(void* self, size_t size) return ptr; } -TH_PRIVATE(void*) +TH_LOCAL(void*) th_arena_allocator_realloc(void* self, void* ptr, size_t size) { th_arena_allocator* allocator = self; @@ -103,7 +103,7 @@ th_arena_allocator_realloc(void* self, void* ptr, size_t size) return newp; } -static void +TH_LOCAL(void) th_arena_allocator_free(void* self, void* ptr) { th_arena_allocator* allocator = self; @@ -124,7 +124,7 @@ th_arena_allocator_init_with_alignment(th_arena_allocator* allocator, void* buf, allocator->base.realloc = th_arena_allocator_realloc; allocator->base.free = th_arena_allocator_free; allocator->allocator = fallback; - allocator->alignment = alignment; + allocator->alignment = (uint16_t)alignment; void* aligned = TH_ALIGNAS(alignment, buf); allocator->size = size - (size_t)((uint8_t*)aligned - (uint8_t*)buf); allocator->buf = aligned; diff --git a/src/th_allocator.h b/src/th_allocator.h index 80cf6ad..5da3286 100644 --- a/src/th_allocator.h +++ b/src/th_allocator.h @@ -2,6 +2,7 @@ #define TH_ALLOCATOR_H #include +#include #include "th_config.h" #include "th_list.h" @@ -37,7 +38,7 @@ typedef struct th_arena_allocator { size_t size; size_t pos; size_t prev_pos; - unsigned int alignment; + uint16_t alignment; } th_arena_allocator; /** th_arena_allocator_init diff --git a/src/th_date.c b/src/th_date.c index d369e17..e09f3ab 100644 --- a/src/th_date.c +++ b/src/th_date.c @@ -36,13 +36,13 @@ th_date_now(void) struct tm tm = {0}; gmtime_r(&t, &tm); th_date date = {0}; - date.year = tm.tm_year; - date.month = tm.tm_mon; - date.day = tm.tm_mday; - date.weekday = tm.tm_wday; - date.hour = tm.tm_hour; - date.minute = tm.tm_min; - date.second = tm.tm_sec; + date.year = (unsigned int)tm.tm_year & 0xFFFF; + date.month = (unsigned int)tm.tm_mon & 0xFF; + date.day = (unsigned int)tm.tm_mday & 0xFF; + date.weekday = (unsigned int)tm.tm_wday & 0xFF; + date.hour = (unsigned int)tm.tm_hour & 0xFF; + date.minute = (unsigned int)tm.tm_min & 0xFF; + date.second = (unsigned int)tm.tm_sec & 0xFF; return date; } @@ -60,12 +60,12 @@ th_date_add(th_date date, th_duration d) t += d.seconds; gmtime_r(&t, &tm); th_date new_date = {0}; - new_date.year = (unsigned int)tm.tm_year; - new_date.month = (unsigned int)tm.tm_mon; - new_date.day = (unsigned int)tm.tm_mday; - new_date.weekday = (unsigned int)tm.tm_wday; - new_date.hour = (unsigned int)tm.tm_hour; - new_date.minute = (unsigned int)tm.tm_min; - new_date.second = (unsigned int)tm.tm_sec; + new_date.year = (unsigned int)tm.tm_year & 0xFFFF; + new_date.month = (unsigned int)tm.tm_mon & 0xFF; + new_date.day = (unsigned int)tm.tm_mday & 0xFF; + new_date.weekday = (unsigned int)tm.tm_wday & 0xFF; + new_date.hour = (unsigned int)tm.tm_hour & 0xFF; + new_date.minute = (unsigned int)tm.tm_min & 0xFF; + new_date.second = (unsigned int)tm.tm_sec & 0xFF; return new_date; } diff --git a/src/th_fcache.h b/src/th_fcache.h index 87d73c4..bf54d49 100644 --- a/src/th_fcache.h +++ b/src/th_fcache.h @@ -38,10 +38,10 @@ th_fcache_id_eq(th_fcache_id a, th_fcache_id b) return a.dir == b.dir && th_string_eq(a.path, b.path); } -TH_INLINE(uint32_t) +TH_INLINE(size_t) th_fcache_id_hash(th_fcache_id id) { - return th_string_hash(id.path) + id.dir->fd; + return th_string_hash(id.path) + (size_t)id.dir->fd; } TH_DEFINE_HASHMAP(th_fcache_map, th_fcache_id, th_fcache_entry*, th_fcache_id_hash, th_fcache_id_eq, (th_fcache_id){0}) diff --git a/src/th_file.c b/src/th_file.c index 51e485c..5e8d692 100644 --- a/src/th_file.c +++ b/src/th_file.c @@ -31,7 +31,7 @@ th_file_mmap_mmap_posix(th_file_mmap* view, th_file* file, size_t offset, size_t { size_t page_size = (size_t)sysconf(_SC_PAGESIZE); size_t moffset = TH_ALIGNDOWN(offset, page_size); - void* addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, file->fd, moffset); + void* addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, file->fd, (off_t)moffset); if (addr == MAP_FAILED) { return TH_ERR_SYSTEM(errno); } @@ -194,7 +194,7 @@ TH_PRIVATE(th_err) th_file_read(th_file* stream, void* addr, size_t len, size_t offset, size_t* read) { #if defined(TH_CONFIG_OS_POSIX) - off_t ret = pread(stream->fd, addr, len, offset); + off_t ret = pread(stream->fd, addr, len, (off_t)offset); if (ret == -1) { *read = 0; return TH_ERR_SYSTEM(errno); @@ -216,7 +216,7 @@ TH_PRIVATE(th_err) th_file_write(th_file* stream, const void* addr, size_t len, size_t offset, size_t* written) { #if defined(TH_CONFIG_OS_POSIX) - off_t ret = pwrite(stream->fd, addr, len, offset); + off_t ret = pwrite(stream->fd, addr, len, (off_t)offset); if (ret == -1) { *written = 0; return TH_ERR_SYSTEM(errno); diff --git a/src/th_fmt.c b/src/th_fmt.c index 192838c..27856c6 100644 --- a/src/th_fmt.c +++ b/src/th_fmt.c @@ -73,9 +73,9 @@ th_fmt_uint_to_str(char* buf, size_t len, unsigned int value) buf[len - 1] = '\0'; size_t i = len - 2; - unsigned v = value; + unsigned int v = value; while (v > 0 && i > 0) { - buf[i--] = '0' + (v % 10); + buf[i--] = '0' + (char)(v % 10); v /= 10; } return &buf[i + 1]; @@ -91,9 +91,9 @@ th_fmt_uint_to_str_ex(char* buf, size_t len, unsigned int val, size_t* out_len) buf[len - 1] = '\0'; size_t i = len - 2; - unsigned v = val; + unsigned int v = val; while (v > 0 && i > 0) { - buf[i--] = '0' + (v % 10); + buf[i--] = '0' + (char)(v % 10); v /= 10; } *out_len = len - i - 2; diff --git a/src/th_hash.h b/src/th_hash.h index 37287d8..d7a66ee 100644 --- a/src/th_hash.h +++ b/src/th_hash.h @@ -11,10 +11,10 @@ * @brief Fowler-Noll-Vo hash function (FNV-1a). * See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function */ -TH_INLINE(uint32_t) +TH_INLINE(size_t) th_hash_bytes(const void* data, size_t len) { - uint32_t hash = 2166136261u; + size_t hash = 2166136261u; const uint8_t* bytes = (const uint8_t*)data; for (size_t i = 0; i < len; ++i) { hash ^= bytes[i]; @@ -23,7 +23,7 @@ th_hash_bytes(const void* data, size_t len) return hash; } -TH_INLINE(uint32_t) +TH_INLINE(size_t) th_hash_cstr(const char* str) { return th_hash_bytes(str, strlen(str)); diff --git a/src/th_hashmap.h b/src/th_hashmap.h index 01a9c11..e11eefa 100644 --- a/src/th_hashmap.h +++ b/src/th_hashmap.h @@ -9,7 +9,7 @@ #include -#define TH_DEFINE_HASHMAP2(NAME, K, V, HASH, K_EQ, K_NULL, K_DEINIT, V_DEINIT) \ +#define TH_DEFINE_HASHMAP(NAME, K, V, HASH, K_EQ, K_NULL) \ typedef struct NAME##_entry { \ K key; \ V value; \ @@ -76,7 +76,14 @@ TH_INLINE(void) \ NAME##_deinit(NAME* map) \ { \ - NAME##_reset(map); \ + if (map->entries) { \ + th_allocator_free(map->allocator, map->entries); \ + map->entries = NULL; \ + } \ + map->size = 0; \ + map->capacity = 0; \ + map->begin = 0; \ + map->end = 0; \ } \ \ TH_INLINE(void) \ @@ -86,15 +93,10 @@ if (map->size > 0) { \ for (size_t i = map->begin; i < map->end; i++) { \ NAME##_entry* entry = &map->entries[i]; \ - if (!K_EQ(entry->key, K_NULL)) { \ - K_DEINIT(entry->key); \ - V_DEINIT(entry->value); \ - } \ + entry->key = K_NULL; \ } \ } \ - th_allocator_free(map->allocator, map->entries); \ } \ - map->entries = NULL; \ map->size = 0; \ map->capacity = 0; \ map->begin = 0; \ @@ -137,7 +139,7 @@ } \ \ TH_LOCAL(th_err) \ - NAME##_do_set(NAME* map, uint32_t hash, K key, V value) \ + NAME##_do_set(NAME* map, size_t hash, K key, V value) \ { \ for (size_t i = hash; i < map->capacity; i++) { \ NAME##_entry* entry = &map->entries[i]; \ @@ -149,9 +151,6 @@ return TH_ERR_OK; \ } \ if (K_EQ(entry->key, key)) { \ - K_DEINIT(entry->key); \ - V_DEINIT(entry->value); \ - entry->key = key; \ entry->value = value; \ return TH_ERR_OK; \ } \ @@ -166,9 +165,6 @@ return TH_ERR_OK; \ } \ if (K_EQ(entry->key, key)) { \ - K_DEINIT(entry->key); \ - V_DEINIT(entry->value); \ - entry->key = key; \ entry->value = value; \ return TH_ERR_OK; \ } \ @@ -182,9 +178,10 @@ TH_INLINE(void) \ NAME##_fix_hole(NAME* map, NAME##_entry* entry) \ { \ - size_t last_zeroed = entry - map->entries; \ - for (size_t i = entry - map->entries + 1; i < map->end; i++) { \ - uint32_t hash = 0; \ + TH_ASSERT(entry >= map->entries && entry < map->entries + map->capacity && "Entry is out of bounds"); \ + size_t last_zeroed = (size_t)(entry - map->entries); \ + for (size_t i = (size_t)(entry - map->entries + 1); i < map->end; i++) { \ + size_t hash = 0; \ if (K_EQ(map->entries[i].key, K_NULL)) { \ break; \ } else if ((hash = (HASH(map->entries[i].key) & (map->capacity - 1))) <= last_zeroed) { \ @@ -197,9 +194,9 @@ map->begin = 0; \ map->end = 0; \ } else if (last_zeroed == map->end - 1) { \ - map->end = NAME##_prev(map, &map->entries[last_zeroed]) - map->entries + 1; \ + map->end = (size_t)(NAME##_prev(map, &map->entries[last_zeroed]) - map->entries + 1); \ } else if (last_zeroed == map->begin) { \ - map->begin = NAME##_next(map, &map->entries[last_zeroed]) - map->entries; \ + map->begin = (size_t)(NAME##_next(map, &map->entries[last_zeroed]) - map->entries); \ } \ } \ \ @@ -222,7 +219,7 @@ /* rearranged == 0; */ \ continue; \ } \ - uint32_t hash = HASH(entry->key); \ + size_t hash = HASH(entry->key); \ /* Don't need to rehash every entry */ \ hash &= (new_capacity - 1); \ NAME##_entry e = *entry; \ @@ -245,14 +242,14 @@ return err; \ } \ } \ - uint32_t hash = HASH(key) & (map->capacity - 1); \ + size_t hash = HASH(key) & (map->capacity - 1); \ return NAME##_do_set(map, hash, key, value); \ } \ \ TH_INLINE(NAME##_entry*) \ NAME##_find(const NAME* map, K key) \ { \ - uint32_t hash = HASH(key) & (map->capacity - 1); \ + size_t hash = HASH(key) & (map->capacity - 1); \ if (map->size == 0) { \ return NULL; \ } \ @@ -306,7 +303,8 @@ TH_INLINE(NAME##_entry*) \ NAME##_next(NAME* map, NAME##_entry* entry) \ { \ - size_t i = entry - map->entries; \ + TH_ASSERT(entry >= map->entries && entry < map->entries + map->capacity && "Entry is out of bounds"); \ + size_t i = (size_t)(entry - map->entries); \ for (size_t j = i + 1; j < map->end; j++) { \ NAME##_entry* e = &map->entries[j]; \ if (!K_EQ(e->key, K_NULL)) { \ @@ -319,7 +317,8 @@ TH_INLINE(NAME##_entry*) \ NAME##_prev(NAME* map, NAME##_entry* entry) \ { \ - size_t i = entry - map->entries; \ + TH_ASSERT(entry >= map->entries && entry < map->entries + map->capacity && "Entry is out of bounds"); \ + size_t i = (size_t)(entry - map->entries); \ for (size_t j = i - 1; j >= map->begin; j--) { \ NAME##_entry* e = &map->entries[j]; \ if (!K_EQ(e->key, K_NULL)) { \ @@ -329,45 +328,9 @@ return NAME##_begin(map); \ } -/** TH_DEFINE_HASHMAP_FIND - * Define find functions for alternative key types. - * !!! Only makes sense if the HASH function for the alternative key type - * is the same as the HASH function for the primary key type. - */ -#define TH_DEFINE_HASHMAP_FIND(NAME, METHOD, K, K_HASH, K_EQ, K_NULL) \ - TH_INLINE(NAME##_entry*) \ - NAME##_##METHOD(const NAME* map, K key) \ - { \ - uint32_t hash = K_HASH(key) & (map->capacity - 1); \ - if (map->size == 0) { \ - return NULL; \ - } \ - for (size_t i = hash; i < map->end; i++) { \ - NAME##_entry* entry = &map->entries[i]; \ - if (K_EQ(entry->key, K_NULL)) { \ - return NULL; \ - } \ - if (K_EQ(entry->key, key)) { \ - return entry; \ - } \ - } \ - for (size_t i = map->begin; i < hash; i++) { \ - NAME##_entry* entry = &map->entries[i]; \ - if (K_EQ(entry->key, K_NULL)) { \ - return NULL; \ - } \ - if (K_EQ(entry->key, key)) { \ - return entry; \ - } \ - } \ - return NULL; \ - } - -#define TH_DEFINE_HASHMAP(NAME, K, V, HASH, K_EQ, K_NULL) TH_DEFINE_HASHMAP2(NAME, K, V, HASH, K_EQ, K_NULL, (void), (void)) -/* default hash maps begin */ /* th_cstr_map begin */ -TH_INLINE(uint32_t) +TH_INLINE(size_t) th_cstr_hash(const char* str) { return th_hash_cstr(str); diff --git a/src/th_header_id.gperf b/src/th_header_id.gperf index 4f9564c..591e7aa 100644 --- a/src/th_header_id.gperf +++ b/src/th_header_id.gperf @@ -5,6 +5,10 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wconversion" +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#endif %} %define lookup-function-name th_header_id_mapping_find %define constants-prefix TH_HEADER_ID_ diff --git a/src/th_heap_string.c b/src/th_heap_string.c index 78d1125..1c62f17 100644 --- a/src/th_heap_string.c +++ b/src/th_heap_string.c @@ -7,7 +7,7 @@ #define TH_HEAP_STRING_SMALL (sizeof(char*) + sizeof(size_t) + sizeof(size_t) - 2) #define TH_HEAP_STRING_ALIGNUP(size) TH_ALIGNUP(size, 16) -TH_PRIVATE(void) +TH_LOCAL(void) th_detail_small_string_init(th_detail_small_string* self, th_allocator* allocator) { self->small = 1; @@ -39,7 +39,7 @@ th_detail_small_string_set(th_detail_small_string* self, th_string str) if (str.len > 0) memcpy(self->buf, str.ptr, str.len); self->buf[str.len] = '\0'; - self->len = str.len; + self->len = str.len & 0x7F; } TH_LOCAL(th_err) @@ -103,7 +103,7 @@ th_detail_small_string_append(th_detail_small_string* self, th_string str) { TH_ASSERT(self->len + str.len <= TH_HEAP_STRING_SMALL_MAX_LEN); memcpy(self->buf + self->len, str.ptr, str.len); - self->len += str.len; + self->len += str.len & 0x7F; self->buf[self->len] = '\0'; } @@ -159,7 +159,7 @@ th_detail_small_string_resize(th_detail_small_string* self, size_t new_len, char { TH_ASSERT(new_len <= TH_HEAP_STRING_SMALL_MAX_LEN && "Invalid length"); memset(self->buf + self->len, fill, new_len - self->len); - self->len = new_len; + self->len = new_len & 0x7F; self->buf[new_len] = '\0'; } diff --git a/src/th_http.c b/src/th_http.c index 3c4f917..3f606d9 100644 --- a/src/th_http.c +++ b/src/th_http.c @@ -57,7 +57,7 @@ th_http_write_error_response(th_http* http, th_err err) th_response_set_code(&http->response, TH_ERR_CODE(err)); if (th_heap_string_len(&http->request.uri_path) == 0) { // Set default error message - th_printf_body(&http->response, "%d %s", TH_ERR_CODE(err), th_http_strerror(err)); + th_printf_body(&http->response, "%d %s", TH_ERR_CODE(err), th_http_strerror((int)err)); } if (http->close) { th_response_add_header(&http->response, TH_STRING("Connection"), TH_STRING("close")); @@ -292,7 +292,7 @@ th_http_start(void* self) th_socket_async_read(th_conn_get_socket(http->conn), th_buf_vec_at(&http->buf, 0), th_buf_vec_size(&http->buf), &http->io_handler.base); } -TH_PRIVATE(void) +TH_LOCAL(void) th_http_init(th_http* http, const th_conn_tracker* tracker, th_conn* conn, th_router* router, th_fcache* fcache, th_allocator* allocator) { @@ -313,7 +313,7 @@ th_http_init(th_http* http, const th_conn_tracker* tracker, th_conn* conn, http->close = TH_HTTP_KEEP_ALIVE; } -TH_PRIVATE(th_err) +TH_LOCAL(th_err) th_http_create(th_http** out, const th_conn_tracker* tracker, th_conn* conn, th_router* router, th_fcache* fcache, th_allocator* allocator) { @@ -325,7 +325,7 @@ th_http_create(th_http** out, const th_conn_tracker* tracker, th_conn* conn, return TH_ERR_OK; } -TH_PRIVATE(void) +TH_LOCAL(void) th_http_upgrader_upgrade(void* self, th_conn* conn) { th_http_upgrader* upgrader = self; diff --git a/src/th_http_error.h b/src/th_http_error.h index 6fcc267..5bc952f 100644 --- a/src/th_http_error.h +++ b/src/th_http_error.h @@ -19,17 +19,15 @@ th_http_error(th_err err) switch (TH_ERR_CATEGORY(err)) { case TH_ERR_CATEGORY_SYSTEM: switch (TH_ERR_CODE(err)) { - { - case TH_ENOENT: - return TH_ERR_HTTP(TH_CODE_NOT_FOUND); - break; - case TH_ETIMEDOUT: - return TH_ERR_HTTP(TH_CODE_REQUEST_TIMEOUT); - break; - default: - return TH_ERR_HTTP(TH_CODE_INTERNAL_SERVER_ERROR); - break; - } + case TH_ENOENT: + return TH_ERR_HTTP(TH_CODE_NOT_FOUND); + break; + case TH_ETIMEDOUT: + return TH_ERR_HTTP(TH_CODE_REQUEST_TIMEOUT); + break; + default: + return TH_ERR_HTTP(TH_CODE_INTERNAL_SERVER_ERROR); + break; } break; case TH_ERR_CATEGORY_HTTP: diff --git a/src/th_io_op_bsd.c b/src/th_io_op_bsd.c index 9817a59..9bde771 100644 --- a/src/th_io_op_bsd.c +++ b/src/th_io_op_bsd.c @@ -21,10 +21,10 @@ th_io_op_bsd_sendfile(void* self, size_t* result) off_t len = (off_t)iot->len2; int ret = 0; if (iot->len == 0) { - ret = sendfile(((th_file*)iot->addr2)->fd, iot->fd, iot->offset, &len, NULL, 0); + ret = sendfile(((th_file*)iot->addr2)->fd, iot->fd, (off_t)iot->offset, &len, NULL, 0); } else { - struct sf_hdtr hdtr = {.headers = (struct iovec*)iov, .hdr_cnt = iot->len, .trailers = NULL, .trl_cnt = 0}; - ret = sendfile(((th_file*)iot->addr2)->fd, iot->fd, iot->offset, &len, &hdtr, 0); + struct sf_hdtr hdtr = {.headers = (struct iovec*)iov, .hdr_cnt = (int)iot->len, .trailers = NULL, .trl_cnt = 0}; + ret = sendfile(((th_file*)iot->addr2)->fd, iot->fd, (off_t)iot->offset, &len, &hdtr, 0); } th_err err = TH_ERR_OK; if (ret < 0 && len == 0) { diff --git a/src/th_io_op_mock.c b/src/th_io_op_mock.c index de62818..edf200a 100644 --- a/src/th_io_op_mock.c +++ b/src/th_io_op_mock.c @@ -14,7 +14,7 @@ th_io_op_mock_read(void* self, size_t* result) return TH_ERR_SYSTEM(-r); else if (r == 0) return TH_ERR_EOF; - *result = r; + *result = (size_t)r; return TH_ERR_OK; } @@ -35,7 +35,7 @@ th_io_op_mock_readv(void* self, size_t* result) err = TH_ERR_EOF; break; } - *result += r; + *result += (size_t)r; } return err; } @@ -65,7 +65,7 @@ th_io_op_mock_writev(void* self, size_t* result) err = TH_ERR_SYSTEM(-r); break; } - *result += r; + *result += (size_t)r; } return err; } diff --git a/src/th_io_op_posix.c b/src/th_io_op_posix.c index f20d581..76f2497 100644 --- a/src/th_io_op_posix.c +++ b/src/th_io_op_posix.c @@ -17,6 +17,12 @@ #include #include +#if defined(TH_CONFIG_OS_BSD) +#define CAST_MSG_IOVLEN(len) ((int)(len)) +#else +#define CAST_MSG_IOVLEN(len) ((size_t)(len)) +#endif + TH_PRIVATE(th_err) th_io_op_posix_read(void* self, size_t* result) { @@ -37,7 +43,7 @@ th_io_op_posix_readv(void* self, size_t* result) th_err err = TH_ERR_OK; th_io_task* iot = self; th_iov* iov = iot->addr; - ssize_t ret = readv(iot->fd, (struct iovec*)iov, iot->len); + ssize_t ret = readv(iot->fd, (struct iovec*)iov, (int)iot->len); if (ret < 0) err = TH_ERR_SYSTEM(errno); else if (ret == 0) @@ -64,7 +70,7 @@ th_io_op_posix_writev(void* self, size_t* result) th_err err = TH_ERR_OK; th_io_task* iot = self; th_iov* iov = iot->addr; - ssize_t ret = writev(iot->fd, (struct iovec*)iov, iot->len); + ssize_t ret = writev(iot->fd, (struct iovec*)iov, (int)iot->len); if (ret < 0) err = TH_ERR_SYSTEM(errno); (*result) = (size_t)ret; @@ -98,7 +104,7 @@ th_io_op_posix_sendv(void* self, size_t* result) #endif struct msghdr msg = {0}; msg.msg_iov = iot->addr; - msg.msg_iovlen = iot->len; + msg.msg_iovlen = CAST_MSG_IOVLEN(iot->len); ssize_t ret = sendmsg(iot->fd, &msg, flags); if (ret < 0) err = TH_ERR_SYSTEM(errno); @@ -146,11 +152,11 @@ th_io_op_posix_sendfile_mmap(void* self, size_t* result) #endif struct msghdr msg = {0}; msg.msg_iov = vec; - msg.msg_iovlen = veclen; + msg.msg_iovlen = CAST_MSG_IOVLEN(veclen); ssize_t ret = sendmsg(iot->fd, &msg, flags); if (ret < 0) err = TH_ERR_SYSTEM(errno); - *result = ret; + *result = (size_t)ret; return err; } @@ -171,7 +177,7 @@ th_io_op_posix_sendfile_buffered(void* self, size_t* result) } } size_t toread = TH_MIN(sizeof(buffer), iot->len2); - ssize_t readlen = pread(((th_file*)iot->addr2)->fd, buffer, toread, iot->offset); + ssize_t readlen = pread(((th_file*)iot->addr2)->fd, buffer, toread, (off_t)iot->offset); if (readlen < 0) return TH_ERR_SYSTEM(errno); int flags = 0; @@ -183,7 +189,7 @@ th_io_op_posix_sendfile_buffered(void* self, size_t* result) veclen++; struct msghdr msg = {0}; msg.msg_iov = vec; - msg.msg_iovlen = veclen; + msg.msg_iovlen = CAST_MSG_IOVLEN(veclen); ssize_t writelen = sendmsg(iot->fd, &msg, flags); if (writelen < 0) return TH_ERR_SYSTEM(errno); diff --git a/src/th_kqueue_service.c b/src/th_kqueue_service.c index 5aa8ca1..da35e4b 100644 --- a/src/th_kqueue_service.c +++ b/src/th_kqueue_service.c @@ -111,7 +111,7 @@ th_kqueue_service_run(void* self, int timeout_ms) TH_ASSERT(0 && "Invalid filter"); break; } - int idx = op_type - 1; + int idx = (int)(op_type - 1); if (handle->iot[idx]) { if (evlist[i].flags & EV_ERROR) { th_runner_push_uncounted_task(service->runner, (th_task*)th_io_task_abort(TH_MOVE_PTR(handle->iot[idx]), TH_ERR_SYSTEM(errno))); diff --git a/src/th_method.gperf b/src/th_method.gperf index 402aa22..bdd207b 100644 --- a/src/th_method.gperf +++ b/src/th_method.gperf @@ -4,6 +4,10 @@ #include "th_method.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#pragma GCC diagnostic ignored "-Wconversion" +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#endif %} %define lookup-function-name th_method_mapping_find %define constants-prefix TH_METHOD_ diff --git a/src/th_mime.gperf b/src/th_mime.gperf index 371245b..9d9de47 100644 --- a/src/th_mime.gperf +++ b/src/th_mime.gperf @@ -5,6 +5,10 @@ #include "th_string.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#pragma GCC diagnostic ignored "-Wconversion" +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#endif %} %define lookup-function-name th_mime_mapping_find %define constants-prefix TH_MIME_ diff --git a/src/th_mock_syscall.c b/src/th_mock_syscall.c index 8b6459c..db8a120 100644 --- a/src/th_mock_syscall.c +++ b/src/th_mock_syscall.c @@ -23,12 +23,12 @@ static int th_mock_close_default(void) static int th_mock_read_default(void* buf, size_t len) { (void)buf; - return len; + return (int)len; } static int th_mock_write_default(size_t len) { - return (size_t)len; + return (int)len; } static int th_mock_settime_default(void) diff --git a/src/th_poll_service.c b/src/th_poll_service.c index ec1b7be..ac311a3 100644 --- a/src/th_poll_service.c +++ b/src/th_poll_service.c @@ -209,7 +209,7 @@ TH_LOCAL(void) th_poll_service_run(void* self, int timeout_ms) { th_poll_service* service = (th_poll_service*)self; - nfds_t nfds = th_pollfd_vec_size(&service->fds); + nfds_t nfds = (nfds_t)th_pollfd_vec_size(&service->fds); int ret = poll(th_pollfd_vec_begin(&service->fds), nfds, timeout_ms); if (ret <= 0) { if (ret == -1) diff --git a/src/th_request_parser.c b/src/th_request_parser.c index dbc26c4..fd6d4fb 100644 --- a/src/th_request_parser.c +++ b/src/th_request_parser.c @@ -242,7 +242,7 @@ th_request_parser_do_path(th_request_parser* parser, th_request* request, th_str return TH_ERR_OK; } -TH_PRIVATE(th_err) +TH_LOCAL(th_err) th_request_parser_do_version(th_request_parser* parser, th_request* request, th_string buffer, size_t* parsed) { size_t n = th_string_find_first(buffer, 0, '\r'); @@ -275,7 +275,7 @@ th_request_parser_do_version(th_request_parser* parser, th_request* request, th_ return TH_ERR_OK; } -TH_PRIVATE(th_err) +TH_LOCAL(th_err) th_request_parse_handle_header(th_request_parser* parser, th_request* request, th_string name, th_string value) { char arena[1024] = {0}; @@ -330,7 +330,7 @@ th_request_parser_parse_header_line(th_string line, th_string* out_name, th_stri return TH_ERR_OK; } -TH_PRIVATE(th_err) +TH_LOCAL(th_err) th_request_parser_do_header(th_request_parser* parser, th_request* request, th_string buffer, size_t* parsed) { size_t n = th_string_find_first(buffer, 0, '\r'); @@ -525,8 +525,8 @@ th_request_parser_multipart_do_next(th_request* request, th_string buffer, th_st // check the boundary if (buffer.ptr[0] != '\r' || buffer.ptr[1] != '\n') return TH_ERR_HTTP(TH_CODE_BAD_REQUEST); - th_string boundary = th_string_substr(buffer, 2, th_request_parser_multipart_find_eol(buffer, 0)); - if (!th_request_parser_multipart_is_boundary_line(boundary, boundary, &last)) + th_string line = th_string_substr(buffer, 2, th_request_parser_multipart_find_eol(buffer, 0)); + if (!th_request_parser_multipart_is_boundary_line(line, boundary, &last)) return TH_ERR_HTTP(TH_CODE_BAD_REQUEST); buffer = th_string_substr(buffer, content_len + boundary.len + 2, th_string_npos); } else { @@ -597,8 +597,7 @@ th_request_parser_do_multipart_form_data(th_request* request, th_string body) body = th_string_substr(body, pos + 2, th_string_npos); do { size_t parsed = 0; - th_err err = th_request_parser_multipart_do_next(request, body, boundary, &parsed); - if (err != TH_ERR_OK) { + if ((err = th_request_parser_multipart_do_next(request, body, boundary, &parsed)) != TH_ERR_OK) { return err; } body = th_string_substr(body, parsed, th_string_npos); @@ -606,7 +605,7 @@ th_request_parser_do_multipart_form_data(th_request* request, th_string body) return TH_ERR_OK; } -TH_PRIVATE(th_err) +TH_LOCAL(th_err) th_request_parser_do_body(th_request_parser* parser, th_request* request, th_string buffer, size_t* parsed) { if (buffer.len < parser->content_len) { diff --git a/src/th_response.c b/src/th_response.c index e4f388f..8ac2ebe 100644 --- a/src/th_response.c +++ b/src/th_response.c @@ -171,7 +171,7 @@ th_response_set_body_va(th_response* response, const char* fmt, va_list args) } } else { th_heap_string_resize(&response->body, (size_t)len, ' '); - vsnprintf(th_heap_string_at(&response->body, 0), len, fmt, args); + vsnprintf(th_heap_string_at(&response->body, 0), (size_t)len, fmt, args); } response->is_file = 0; return TH_ERR_OK; @@ -193,7 +193,7 @@ th_response_finalize_headers(th_response* response) return err; if ((err = th_heap_string_append(&response->headers, TH_STRING(" "))) != TH_ERR_OK) return err; - if ((err = th_heap_string_append_cstr(&response->headers, th_http_strerror(response->code))) != TH_ERR_OK) + if ((err = th_heap_string_append_cstr(&response->headers, th_http_strerror((int)response->code))) != TH_ERR_OK) return err; if ((err = th_heap_string_append(&response->headers, TH_STRING("\r\n"))) != TH_ERR_OK) return err; @@ -211,12 +211,12 @@ th_response_set_default_headers(th_response* response) char buffer[256]; if (response->is_file) { size_t len = 0; - const char* content_len = th_fmt_uint_to_str_ex(buffer, sizeof(buffer), response->file_len, &len); + const char* content_len = th_fmt_uint_to_str_ex(buffer, sizeof(buffer), (unsigned int)response->file_len, &len); if ((err = th_response_add_header(response, TH_STRING("Content-Length"), th_string_make(content_len, len))) != TH_ERR_OK) return err; } else { size_t len = 0; - const char* body_len = th_fmt_uint_to_str_ex(buffer, sizeof(buffer), th_heap_string_len(&response->body), &len); + const char* body_len = th_fmt_uint_to_str_ex(buffer, sizeof(buffer), (unsigned int)th_heap_string_len(&response->body), &len); if ((err = th_response_add_header(response, TH_STRING("Content-Length"), th_string_make(body_len, len))) != TH_ERR_OK) return err; } diff --git a/src/th_router.c b/src/th_router.c index 4aeea02..d8c4f8f 100644 --- a/src/th_router.c +++ b/src/th_router.c @@ -247,16 +247,15 @@ th_router_add_route(th_router* router, th_method method, th_string path, th_hand while (1) { th_string name; th_capture_type type = TH_CAPTURE_TYPE_NONE; - th_err err = th_route_parse_trail(&trail, &name, &type); - if (err != TH_ERR_OK) + th_err err = TH_ERR_OK; + if ((err = th_route_parse_trail(&trail, &name, &type)) != TH_ERR_OK) return err; bool last = th_string_empty(trail); if (type == TH_CAPTURE_TYPE_PATH && !last) return TH_ERR_INVALID_ARG; if (route == NULL) { - th_err err = th_route_create(&route, type, name, router->allocator); - if (err != TH_ERR_OK) + if ((err = th_route_create(&route, type, name, router->allocator)) != TH_ERR_OK) return err; th_route_insert_sorted(list, route); route = *list; // restart diff --git a/src/th_server.c b/src/th_server.c index 94ca79f..745c8ae 100644 --- a/src/th_server.c +++ b/src/th_server.c @@ -54,7 +54,7 @@ th_main_allocator_alloc(void* self, size_t size) } if (!ptr) return NULL; - ((uint32_t*)ptr)[0] = size; + ((uint32_t*)ptr)[0] = (uint32_t)size; return (char*)ptr + ptr_offset; } diff --git a/src/th_string.c b/src/th_string.c index bdb3aa6..de1d774 100644 --- a/src/th_string.c +++ b/src/th_string.c @@ -26,7 +26,7 @@ th_string_to_uint(th_string str, unsigned int* out) for (size_t i = 0; i < str.len; i++) { if (str.ptr[i] < '0' || str.ptr[i] > '9') return TH_ERR_INVALID_ARG; - *out = *out * 10 + (str.ptr[i] - '0'); + *out = *out * 10 + (unsigned int)(str.ptr[i] - '0'); } return TH_ERR_OK; } @@ -117,7 +117,7 @@ th_string_trim(th_string str) return th_string_substr(str, start, end - start); } -TH_PRIVATE(uint32_t) +TH_PRIVATE(size_t) th_string_hash(th_string str) { return th_hash_bytes(str.ptr, str.len); diff --git a/src/th_string.h b/src/th_string.h index eb0d7f1..5dc83c4 100644 --- a/src/th_string.h +++ b/src/th_string.h @@ -109,7 +109,7 @@ th_string_substr(th_string str, size_t start, size_t len); TH_PRIVATE(th_string) th_string_trim(th_string str); -TH_PRIVATE(uint32_t) +TH_PRIVATE(size_t) th_string_hash(th_string str); #endif diff --git a/th.c b/th.c index 5b2381a..9391808 100644 --- a/th.c +++ b/th.c @@ -307,17 +307,15 @@ th_http_error(th_err err) switch (TH_ERR_CATEGORY(err)) { case TH_ERR_CATEGORY_SYSTEM: switch (TH_ERR_CODE(err)) { - { - case TH_ENOENT: - return TH_ERR_HTTP(TH_CODE_NOT_FOUND); - break; - case TH_ETIMEDOUT: - return TH_ERR_HTTP(TH_CODE_REQUEST_TIMEOUT); - break; - default: - return TH_ERR_HTTP(TH_CODE_INTERNAL_SERVER_ERROR); - break; - } + case TH_ENOENT: + return TH_ERR_HTTP(TH_CODE_NOT_FOUND); + break; + case TH_ETIMEDOUT: + return TH_ERR_HTTP(TH_CODE_REQUEST_TIMEOUT); + break; + default: + return TH_ERR_HTTP(TH_CODE_INTERNAL_SERVER_ERROR); + break; } break; case TH_ERR_CATEGORY_HTTP: @@ -736,6 +734,7 @@ th_next_pow2(size_t n) /* Start of th_allocator.h */ #include +#include TH_INLINE(void*) @@ -768,7 +767,7 @@ typedef struct th_arena_allocator { size_t size; size_t pos; size_t prev_pos; - unsigned int alignment; + uint16_t alignment; } th_arena_allocator; /** th_arena_allocator_init @@ -914,10 +913,10 @@ th_pool_allocator_deinit(th_pool_allocator* pool); * @brief Fowler-Noll-Vo hash function (FNV-1a). * See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function */ -TH_INLINE(uint32_t) +TH_INLINE(size_t) th_hash_bytes(const void* data, size_t len) { - uint32_t hash = 2166136261u; + size_t hash = 2166136261u; const uint8_t* bytes = (const uint8_t*)data; for (size_t i = 0; i < len; ++i) { hash ^= bytes[i]; @@ -926,7 +925,7 @@ th_hash_bytes(const void* data, size_t len) return hash; } -TH_INLINE(uint32_t) +TH_INLINE(size_t) th_hash_cstr(const char* str) { return th_hash_bytes(str, strlen(str)); @@ -939,7 +938,7 @@ th_hash_cstr(const char* str) #include -#define TH_DEFINE_HASHMAP2(NAME, K, V, HASH, K_EQ, K_NULL, K_DEINIT, V_DEINIT) \ +#define TH_DEFINE_HASHMAP(NAME, K, V, HASH, K_EQ, K_NULL) \ typedef struct NAME##_entry { \ K key; \ V value; \ @@ -1006,7 +1005,14 @@ th_hash_cstr(const char* str) TH_INLINE(void) \ NAME##_deinit(NAME* map) \ { \ - NAME##_reset(map); \ + if (map->entries) { \ + th_allocator_free(map->allocator, map->entries); \ + map->entries = NULL; \ + } \ + map->size = 0; \ + map->capacity = 0; \ + map->begin = 0; \ + map->end = 0; \ } \ \ TH_INLINE(void) \ @@ -1016,15 +1022,10 @@ th_hash_cstr(const char* str) if (map->size > 0) { \ for (size_t i = map->begin; i < map->end; i++) { \ NAME##_entry* entry = &map->entries[i]; \ - if (!K_EQ(entry->key, K_NULL)) { \ - K_DEINIT(entry->key); \ - V_DEINIT(entry->value); \ - } \ + entry->key = K_NULL; \ } \ } \ - th_allocator_free(map->allocator, map->entries); \ } \ - map->entries = NULL; \ map->size = 0; \ map->capacity = 0; \ map->begin = 0; \ @@ -1067,7 +1068,7 @@ th_hash_cstr(const char* str) } \ \ TH_LOCAL(th_err) \ - NAME##_do_set(NAME* map, uint32_t hash, K key, V value) \ + NAME##_do_set(NAME* map, size_t hash, K key, V value) \ { \ for (size_t i = hash; i < map->capacity; i++) { \ NAME##_entry* entry = &map->entries[i]; \ @@ -1079,9 +1080,6 @@ th_hash_cstr(const char* str) return TH_ERR_OK; \ } \ if (K_EQ(entry->key, key)) { \ - K_DEINIT(entry->key); \ - V_DEINIT(entry->value); \ - entry->key = key; \ entry->value = value; \ return TH_ERR_OK; \ } \ @@ -1096,9 +1094,6 @@ th_hash_cstr(const char* str) return TH_ERR_OK; \ } \ if (K_EQ(entry->key, key)) { \ - K_DEINIT(entry->key); \ - V_DEINIT(entry->value); \ - entry->key = key; \ entry->value = value; \ return TH_ERR_OK; \ } \ @@ -1112,9 +1107,10 @@ th_hash_cstr(const char* str) TH_INLINE(void) \ NAME##_fix_hole(NAME* map, NAME##_entry* entry) \ { \ - size_t last_zeroed = entry - map->entries; \ - for (size_t i = entry - map->entries + 1; i < map->end; i++) { \ - uint32_t hash = 0; \ + TH_ASSERT(entry >= map->entries && entry < map->entries + map->capacity && "Entry is out of bounds"); \ + size_t last_zeroed = (size_t)(entry - map->entries); \ + for (size_t i = (size_t)(entry - map->entries + 1); i < map->end; i++) { \ + size_t hash = 0; \ if (K_EQ(map->entries[i].key, K_NULL)) { \ break; \ } else if ((hash = (HASH(map->entries[i].key) & (map->capacity - 1))) <= last_zeroed) { \ @@ -1127,9 +1123,9 @@ th_hash_cstr(const char* str) map->begin = 0; \ map->end = 0; \ } else if (last_zeroed == map->end - 1) { \ - map->end = NAME##_prev(map, &map->entries[last_zeroed]) - map->entries + 1; \ + map->end = (size_t)(NAME##_prev(map, &map->entries[last_zeroed]) - map->entries + 1); \ } else if (last_zeroed == map->begin) { \ - map->begin = NAME##_next(map, &map->entries[last_zeroed]) - map->entries; \ + map->begin = (size_t)(NAME##_next(map, &map->entries[last_zeroed]) - map->entries); \ } \ } \ \ @@ -1152,7 +1148,7 @@ th_hash_cstr(const char* str) /* rearranged == 0; */ \ continue; \ } \ - uint32_t hash = HASH(entry->key); \ + size_t hash = HASH(entry->key); \ /* Don't need to rehash every entry */ \ hash &= (new_capacity - 1); \ NAME##_entry e = *entry; \ @@ -1175,14 +1171,14 @@ th_hash_cstr(const char* str) return err; \ } \ } \ - uint32_t hash = HASH(key) & (map->capacity - 1); \ + size_t hash = HASH(key) & (map->capacity - 1); \ return NAME##_do_set(map, hash, key, value); \ } \ \ TH_INLINE(NAME##_entry*) \ NAME##_find(const NAME* map, K key) \ { \ - uint32_t hash = HASH(key) & (map->capacity - 1); \ + size_t hash = HASH(key) & (map->capacity - 1); \ if (map->size == 0) { \ return NULL; \ } \ @@ -1236,7 +1232,8 @@ th_hash_cstr(const char* str) TH_INLINE(NAME##_entry*) \ NAME##_next(NAME* map, NAME##_entry* entry) \ { \ - size_t i = entry - map->entries; \ + TH_ASSERT(entry >= map->entries && entry < map->entries + map->capacity && "Entry is out of bounds"); \ + size_t i = (size_t)(entry - map->entries); \ for (size_t j = i + 1; j < map->end; j++) { \ NAME##_entry* e = &map->entries[j]; \ if (!K_EQ(e->key, K_NULL)) { \ @@ -1249,7 +1246,8 @@ th_hash_cstr(const char* str) TH_INLINE(NAME##_entry*) \ NAME##_prev(NAME* map, NAME##_entry* entry) \ { \ - size_t i = entry - map->entries; \ + TH_ASSERT(entry >= map->entries && entry < map->entries + map->capacity && "Entry is out of bounds"); \ + size_t i = (size_t)(entry - map->entries); \ for (size_t j = i - 1; j >= map->begin; j--) { \ NAME##_entry* e = &map->entries[j]; \ if (!K_EQ(e->key, K_NULL)) { \ @@ -1259,45 +1257,9 @@ th_hash_cstr(const char* str) return NAME##_begin(map); \ } -/** TH_DEFINE_HASHMAP_FIND - * Define find functions for alternative key types. - * !!! Only makes sense if the HASH function for the alternative key type - * is the same as the HASH function for the primary key type. - */ -#define TH_DEFINE_HASHMAP_FIND(NAME, METHOD, K, K_HASH, K_EQ, K_NULL) \ - TH_INLINE(NAME##_entry*) \ - NAME##_##METHOD(const NAME* map, K key) \ - { \ - uint32_t hash = K_HASH(key) & (map->capacity - 1); \ - if (map->size == 0) { \ - return NULL; \ - } \ - for (size_t i = hash; i < map->end; i++) { \ - NAME##_entry* entry = &map->entries[i]; \ - if (K_EQ(entry->key, K_NULL)) { \ - return NULL; \ - } \ - if (K_EQ(entry->key, key)) { \ - return entry; \ - } \ - } \ - for (size_t i = map->begin; i < hash; i++) { \ - NAME##_entry* entry = &map->entries[i]; \ - if (K_EQ(entry->key, K_NULL)) { \ - return NULL; \ - } \ - if (K_EQ(entry->key, key)) { \ - return entry; \ - } \ - } \ - return NULL; \ - } - -#define TH_DEFINE_HASHMAP(NAME, K, V, HASH, K_EQ, K_NULL) TH_DEFINE_HASHMAP2(NAME, K, V, HASH, K_EQ, K_NULL, (void), (void)) -/* default hash maps begin */ /* th_cstr_map begin */ -TH_INLINE(uint32_t) +TH_INLINE(size_t) th_cstr_hash(const char* str) { return th_hash_cstr(str); @@ -1424,7 +1386,7 @@ th_string_substr(th_string str, size_t start, size_t len); TH_PRIVATE(th_string) th_string_trim(th_string str); -TH_PRIVATE(uint32_t) +TH_PRIVATE(size_t) th_string_hash(th_string str); /* End of th_string.h */ @@ -2361,6 +2323,9 @@ th_context_drain(th_context* context); TH_PRIVATE(void) th_context_deinit(th_context* context); +TH_PRIVATE(th_io_service*) +th_context_get_io_service(th_context* context); + TH_PRIVATE(void) th_context_dispatch_handler(th_context* context, th_io_handler* handler, size_t result, th_err err); @@ -2619,10 +2584,10 @@ th_fcache_id_eq(th_fcache_id a, th_fcache_id b) return a.dir == b.dir && th_string_eq(a.path, b.path); } -TH_INLINE(uint32_t) +TH_INLINE(size_t) th_fcache_id_hash(th_fcache_id id) { - return th_string_hash(id.path) + id.dir->fd; + return th_string_hash(id.path) + (size_t)id.dir->fd; } TH_DEFINE_HASHMAP(th_fcache_map, th_fcache_id, th_fcache_entry*, th_fcache_id_hash, th_fcache_id_eq, (th_fcache_id){0}) @@ -3665,9 +3630,9 @@ th_url_decode_string(th_string input, th_heap_string* output, th_url_decode_type #include -#define TH_ALIGNOF(type) offsetof(struct { char c; type member; }, member) +#define TH_ALIGNOF(type) ((size_t)&(((struct { char c; type member; }*)0)->member)) #define TH_ALIGNAS(align, ptr) ((void*)(((uintptr_t)(ptr) + ((align) - 1)) & ~((align) - 1))) -#define TH_ALIGNUP(n, align) (((n) + (align) - 1) & ~((align) - 1)) +#define TH_ALIGNUP(n, align) (((n) + (size_t)(align) - 1) & ~((size_t)(align) - 1)) #define TH_ALIGNDOWN(n, align) ((n) & ~((align) - 1)) typedef long double th_max_align; @@ -3720,7 +3685,7 @@ th_main_allocator_alloc(void* self, size_t size) } if (!ptr) return NULL; - ((uint32_t*)ptr)[0] = size; + ((uint32_t*)ptr)[0] = (uint32_t)size; return (char*)ptr + ptr_offset; } @@ -4346,16 +4311,15 @@ th_router_add_route(th_router* router, th_method method, th_string path, th_hand while (1) { th_string name; th_capture_type type = TH_CAPTURE_TYPE_NONE; - th_err err = th_route_parse_trail(&trail, &name, &type); - if (err != TH_ERR_OK) + th_err err = TH_ERR_OK; + if ((err = th_route_parse_trail(&trail, &name, &type)) != TH_ERR_OK) return err; bool last = th_string_empty(trail); if (type == TH_CAPTURE_TYPE_PATH && !last) return TH_ERR_INVALID_ARG; if (route == NULL) { - th_err err = th_route_create(&route, type, name, router->allocator); - if (err != TH_ERR_OK) + if ((err = th_route_create(&route, type, name, router->allocator)) != TH_ERR_OK) return err; th_route_insert_sorted(list, route); route = *list; // restart @@ -4416,6 +4380,10 @@ th_router_add_route(th_router* router, th_method method, th_string path, th_hand #include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#pragma GCC diagnostic ignored "-Wconversion" +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#endif struct th_mime_mapping; #define TH_MIME_TOTAL_KEYWORDS 33 @@ -4579,6 +4547,10 @@ th_mime_mapping_find (register const char *str, register size_t len) #include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#pragma GCC diagnostic ignored "-Wconversion" +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#endif struct th_method_mapping; #define TH_METHOD_TOTAL_KEYWORDS 9 @@ -5191,7 +5163,7 @@ th_io_op_posix_readv(void* self, size_t* result) th_err err = TH_ERR_OK; th_io_task* iot = self; th_iov* iov = iot->addr; - ssize_t ret = readv(iot->fd, (struct iovec*)iov, iot->len); + ssize_t ret = readv(iot->fd, (struct iovec*)iov, (int)iot->len); if (ret < 0) err = TH_ERR_SYSTEM(errno); else if (ret == 0) @@ -5218,7 +5190,7 @@ th_io_op_posix_writev(void* self, size_t* result) th_err err = TH_ERR_OK; th_io_task* iot = self; th_iov* iov = iot->addr; - ssize_t ret = writev(iot->fd, (struct iovec*)iov, iot->len); + ssize_t ret = writev(iot->fd, (struct iovec*)iov, (int)iot->len); if (ret < 0) err = TH_ERR_SYSTEM(errno); (*result) = (size_t)ret; @@ -5300,11 +5272,11 @@ th_io_op_posix_sendfile_mmap(void* self, size_t* result) #endif struct msghdr msg = {0}; msg.msg_iov = vec; - msg.msg_iovlen = veclen; + msg.msg_iovlen = (int)veclen; ssize_t ret = sendmsg(iot->fd, &msg, flags); if (ret < 0) err = TH_ERR_SYSTEM(errno); - *result = ret; + *result = (size_t)ret; return err; } @@ -5325,7 +5297,7 @@ th_io_op_posix_sendfile_buffered(void* self, size_t* result) } } size_t toread = TH_MIN(sizeof(buffer), iot->len2); - ssize_t readlen = pread(((th_file*)iot->addr2)->fd, buffer, toread, iot->offset); + ssize_t readlen = pread(((th_file*)iot->addr2)->fd, buffer, toread, (off_t)iot->offset); if (readlen < 0) return TH_ERR_SYSTEM(errno); int flags = 0; @@ -5337,7 +5309,7 @@ th_io_op_posix_sendfile_buffered(void* self, size_t* result) veclen++; struct msghdr msg = {0}; msg.msg_iov = vec; - msg.msg_iovlen = veclen; + msg.msg_iovlen = (int)veclen; ssize_t writelen = sendmsg(iot->fd, &msg, flags); if (writelen < 0) return TH_ERR_SYSTEM(errno); @@ -5365,10 +5337,10 @@ th_io_op_bsd_sendfile(void* self, size_t* result) off_t len = (off_t)iot->len2; int ret = 0; if (iot->len == 0) { - ret = sendfile(((th_file*)iot->addr2)->fd, iot->fd, iot->offset, &len, NULL, 0); + ret = sendfile(((th_file*)iot->addr2)->fd, iot->fd, (off_t)iot->offset, &len, NULL, 0); } else { - struct sf_hdtr hdtr = {.headers = (struct iovec*)iov, .hdr_cnt = iot->len, .trailers = NULL, .trl_cnt = 0}; - ret = sendfile(((th_file*)iot->addr2)->fd, iot->fd, iot->offset, &len, &hdtr, 0); + struct sf_hdtr hdtr = {.headers = (struct iovec*)iov, .hdr_cnt = (int)iot->len, .trailers = NULL, .trl_cnt = 0}; + ret = sendfile(((th_file*)iot->addr2)->fd, iot->fd, (off_t)iot->offset, &len, &hdtr, 0); } th_err err = TH_ERR_OK; if (ret < 0 && len == 0) { @@ -5455,7 +5427,7 @@ th_default_allocator_set(th_allocator* allocator) /* th_arena_allocator implementation begin */ -TH_PRIVATE(void*) +TH_LOCAL(void*) th_arena_allocator_alloc(void* self, size_t size) { th_arena_allocator* allocator = self; @@ -5470,7 +5442,7 @@ th_arena_allocator_alloc(void* self, size_t size) return ptr; } -TH_PRIVATE(void*) +TH_LOCAL(void*) th_arena_allocator_realloc(void* self, void* ptr, size_t size) { th_arena_allocator* allocator = self; @@ -5500,7 +5472,7 @@ th_arena_allocator_realloc(void* self, void* ptr, size_t size) return newp; } -static void +TH_LOCAL(void) th_arena_allocator_free(void* self, void* ptr) { th_arena_allocator* allocator = self; @@ -5521,7 +5493,7 @@ th_arena_allocator_init_with_alignment(th_arena_allocator* allocator, void* buf, allocator->base.realloc = th_arena_allocator_realloc; allocator->base.free = th_arena_allocator_free; allocator->allocator = fallback; - allocator->alignment = alignment; + allocator->alignment = (uint16_t)alignment; void* aligned = TH_ALIGNAS(alignment, buf); allocator->size = size - (size_t)((uint8_t*)aligned - (uint8_t*)buf); allocator->buf = aligned; @@ -5742,7 +5714,7 @@ th_kqueue_service_run(void* self, int timeout_ms) TH_ASSERT(0 && "Invalid filter"); break; } - int idx = op_type - 1; + int idx = (int)(op_type - 1); if (handle->iot[idx]) { if (evlist[i].flags & EV_ERROR) { th_runner_push_uncounted_task(service->runner, (th_task*)th_io_task_abort(TH_MOVE_PTR(handle->iot[idx]), TH_ERR_SYSTEM(errno))); @@ -6142,7 +6114,7 @@ TH_LOCAL(void) th_poll_service_run(void* self, int timeout_ms) { th_poll_service* service = (th_poll_service*)self; - nfds_t nfds = th_pollfd_vec_size(&service->fds); + nfds_t nfds = (nfds_t)th_pollfd_vec_size(&service->fds); int ret = poll(th_pollfd_vec_begin(&service->fds), nfds, timeout_ms); if (ret <= 0) { if (ret == -1) @@ -7076,7 +7048,7 @@ th_request_parser_do_path(th_request_parser* parser, th_request* request, th_str return TH_ERR_OK; } -TH_PRIVATE(th_err) +TH_LOCAL(th_err) th_request_parser_do_version(th_request_parser* parser, th_request* request, th_string buffer, size_t* parsed) { size_t n = th_string_find_first(buffer, 0, '\r'); @@ -7109,7 +7081,7 @@ th_request_parser_do_version(th_request_parser* parser, th_request* request, th_ return TH_ERR_OK; } -TH_PRIVATE(th_err) +TH_LOCAL(th_err) th_request_parse_handle_header(th_request_parser* parser, th_request* request, th_string name, th_string value) { char arena[1024] = {0}; @@ -7164,7 +7136,7 @@ th_request_parser_parse_header_line(th_string line, th_string* out_name, th_stri return TH_ERR_OK; } -TH_PRIVATE(th_err) +TH_LOCAL(th_err) th_request_parser_do_header(th_request_parser* parser, th_request* request, th_string buffer, size_t* parsed) { size_t n = th_string_find_first(buffer, 0, '\r'); @@ -7359,8 +7331,8 @@ th_request_parser_multipart_do_next(th_request* request, th_string buffer, th_st // check the boundary if (buffer.ptr[0] != '\r' || buffer.ptr[1] != '\n') return TH_ERR_HTTP(TH_CODE_BAD_REQUEST); - th_string boundary = th_string_substr(buffer, 2, th_request_parser_multipart_find_eol(buffer, 0)); - if (!th_request_parser_multipart_is_boundary_line(boundary, boundary, &last)) + th_string line = th_string_substr(buffer, 2, th_request_parser_multipart_find_eol(buffer, 0)); + if (!th_request_parser_multipart_is_boundary_line(line, boundary, &last)) return TH_ERR_HTTP(TH_CODE_BAD_REQUEST); buffer = th_string_substr(buffer, content_len + boundary.len + 2, th_string_npos); } else { @@ -7431,8 +7403,7 @@ th_request_parser_do_multipart_form_data(th_request* request, th_string body) body = th_string_substr(body, pos + 2, th_string_npos); do { size_t parsed = 0; - th_err err = th_request_parser_multipart_do_next(request, body, boundary, &parsed); - if (err != TH_ERR_OK) { + if ((err = th_request_parser_multipart_do_next(request, body, boundary, &parsed)) != TH_ERR_OK) { return err; } body = th_string_substr(body, parsed, th_string_npos); @@ -7440,7 +7411,7 @@ th_request_parser_do_multipart_form_data(th_request* request, th_string body) return TH_ERR_OK; } -TH_PRIVATE(th_err) +TH_LOCAL(th_err) th_request_parser_do_body(th_request_parser* parser, th_request* request, th_string buffer, size_t* parsed) { if (buffer.len < parser->content_len) { @@ -8166,7 +8137,7 @@ th_response_set_body_va(th_response* response, const char* fmt, va_list args) } } else { th_heap_string_resize(&response->body, (size_t)len, ' '); - vsnprintf(th_heap_string_at(&response->body, 0), len, fmt, args); + vsnprintf(th_heap_string_at(&response->body, 0), (size_t)len, fmt, args); } response->is_file = 0; return TH_ERR_OK; @@ -8188,7 +8159,7 @@ th_response_finalize_headers(th_response* response) return err; if ((err = th_heap_string_append(&response->headers, TH_STRING(" "))) != TH_ERR_OK) return err; - if ((err = th_heap_string_append_cstr(&response->headers, th_http_strerror(response->code))) != TH_ERR_OK) + if ((err = th_heap_string_append_cstr(&response->headers, th_http_strerror((int)response->code))) != TH_ERR_OK) return err; if ((err = th_heap_string_append(&response->headers, TH_STRING("\r\n"))) != TH_ERR_OK) return err; @@ -8206,12 +8177,12 @@ th_response_set_default_headers(th_response* response) char buffer[256]; if (response->is_file) { size_t len = 0; - const char* content_len = th_fmt_uint_to_str_ex(buffer, sizeof(buffer), response->file_len, &len); + const char* content_len = th_fmt_uint_to_str_ex(buffer, sizeof(buffer), (unsigned int)response->file_len, &len); if ((err = th_response_add_header(response, TH_STRING("Content-Length"), th_string_make(content_len, len))) != TH_ERR_OK) return err; } else { size_t len = 0; - const char* body_len = th_fmt_uint_to_str_ex(buffer, sizeof(buffer), th_heap_string_len(&response->body), &len); + const char* body_len = th_fmt_uint_to_str_ex(buffer, sizeof(buffer), (unsigned int)th_heap_string_len(&response->body), &len); if ((err = th_response_add_header(response, TH_STRING("Content-Length"), th_string_make(body_len, len))) != TH_ERR_OK) return err; } @@ -8430,6 +8401,12 @@ th_context_deinit(th_context* context) th_io_service_destroy(context->io_service); } +TH_PRIVATE(th_io_service*) +th_context_get_io_service(th_context* context) +{ + return context->io_service; +} + TH_PRIVATE(void) th_context_dispatch_handler(th_context* context, th_io_handler* handler, size_t result, th_err err) { @@ -8693,6 +8670,10 @@ th_ssl_conn_destroy(void* self) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wconversion" +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#endif struct th_header_id_mapping; #define TH_HEADER_ID_TOTAL_KEYWORDS 6 @@ -8775,7 +8756,7 @@ th_file_mmap_mmap_posix(th_file_mmap* view, th_file* file, size_t offset, size_t { size_t page_size = (size_t)sysconf(_SC_PAGESIZE); size_t moffset = TH_ALIGNDOWN(offset, page_size); - void* addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, file->fd, moffset); + void* addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, file->fd, (off_t)moffset); if (addr == MAP_FAILED) { return TH_ERR_SYSTEM(errno); } @@ -8938,7 +8919,7 @@ TH_PRIVATE(th_err) th_file_read(th_file* stream, void* addr, size_t len, size_t offset, size_t* read) { #if defined(TH_CONFIG_OS_POSIX) - off_t ret = pread(stream->fd, addr, len, offset); + off_t ret = pread(stream->fd, addr, len, (off_t)offset); if (ret == -1) { *read = 0; return TH_ERR_SYSTEM(errno); @@ -8960,7 +8941,7 @@ TH_PRIVATE(th_err) th_file_write(th_file* stream, const void* addr, size_t len, size_t offset, size_t* written) { #if defined(TH_CONFIG_OS_POSIX) - off_t ret = pwrite(stream->fd, addr, len, offset); + off_t ret = pwrite(stream->fd, addr, len, (off_t)offset); if (ret == -1) { *written = 0; return TH_ERR_SYSTEM(errno); @@ -9024,6 +9005,7 @@ th_file_stat_hash_posix(th_file* stream) hash = FSTAT_HASH_NEXT(hash, (uint32_t)st.st_ino); hash = FSTAT_HASH_NEXT(hash, (uint32_t)st.st_uid); hash = FSTAT_HASH_NEXT(hash, (uint32_t)st.st_gid); + hash = FSTAT_HASH_NEXT(hash, (uint32_t)(st.st_nlink != 0)); return hash; } #elif defined(TH_CONFIG_OS_WIN) @@ -9446,7 +9428,7 @@ th_string_to_uint(th_string str, unsigned int* out) for (size_t i = 0; i < str.len; i++) { if (str.ptr[i] < '0' || str.ptr[i] > '9') return TH_ERR_INVALID_ARG; - *out = *out * 10 + (str.ptr[i] - '0'); + *out = *out * 10 + (unsigned int)(str.ptr[i] - '0'); } return TH_ERR_OK; } @@ -9537,7 +9519,7 @@ th_string_trim(th_string str) return th_string_substr(str, start, end - start); } -TH_PRIVATE(uint32_t) +TH_PRIVATE(size_t) th_string_hash(th_string str) { return th_hash_bytes(str.ptr, str.len); @@ -9549,7 +9531,7 @@ th_string_hash(th_string str) #define TH_HEAP_STRING_SMALL (sizeof(char*) + sizeof(size_t) + sizeof(size_t) - 2) #define TH_HEAP_STRING_ALIGNUP(size) TH_ALIGNUP(size, 16) -TH_PRIVATE(void) +TH_LOCAL(void) th_detail_small_string_init(th_detail_small_string* self, th_allocator* allocator) { self->small = 1; @@ -9581,7 +9563,7 @@ th_detail_small_string_set(th_detail_small_string* self, th_string str) if (str.len > 0) memcpy(self->buf, str.ptr, str.len); self->buf[str.len] = '\0'; - self->len = str.len; + self->len = (unsigned char)str.len; } TH_LOCAL(th_err) @@ -9701,7 +9683,7 @@ th_detail_small_string_resize(th_detail_small_string* self, size_t new_len, char { TH_ASSERT(new_len <= TH_HEAP_STRING_SMALL_MAX_LEN && "Invalid length"); memset(self->buf + self->len, fill, new_len - self->len); - self->len = new_len; + self->len = (unsigned char)new_len; self->buf[new_len] = '\0'; } @@ -9969,7 +9951,7 @@ th_http_write_error_response(th_http* http, th_err err) th_response_set_code(&http->response, TH_ERR_CODE(err)); if (th_heap_string_len(&http->request.uri_path) == 0) { // Set default error message - th_printf_body(&http->response, "%d %s", TH_ERR_CODE(err), th_http_strerror(err)); + th_printf_body(&http->response, "%d %s", TH_ERR_CODE(err), th_http_strerror((int)err)); } if (http->close) { th_response_add_header(&http->response, TH_STRING("Connection"), TH_STRING("close")); @@ -10204,7 +10186,7 @@ th_http_start(void* self) th_socket_async_read(th_conn_get_socket(http->conn), th_buf_vec_at(&http->buf, 0), th_buf_vec_size(&http->buf), &http->io_handler.base); } -TH_PRIVATE(void) +TH_LOCAL(void) th_http_init(th_http* http, const th_conn_tracker* tracker, th_conn* conn, th_router* router, th_fcache* fcache, th_allocator* allocator) { @@ -10225,7 +10207,7 @@ th_http_init(th_http* http, const th_conn_tracker* tracker, th_conn* conn, http->close = TH_HTTP_KEEP_ALIVE; } -TH_PRIVATE(th_err) +TH_LOCAL(th_err) th_http_create(th_http** out, const th_conn_tracker* tracker, th_conn* conn, th_router* router, th_fcache* fcache, th_allocator* allocator) { @@ -10237,7 +10219,7 @@ th_http_create(th_http** out, const th_conn_tracker* tracker, th_conn* conn, return TH_ERR_OK; } -TH_PRIVATE(void) +TH_LOCAL(void) th_http_upgrader_upgrade(void* self, th_conn* conn) { th_http_upgrader* upgrader = self; @@ -10338,7 +10320,7 @@ th_fmt_uint_to_str(char* buf, size_t len, unsigned int value) size_t i = len - 2; unsigned v = value; while (v > 0 && i > 0) { - buf[i--] = '0' + (v % 10); + buf[i--] = '0' + (char)(v % 10); v /= 10; } return &buf[i + 1]; @@ -10483,13 +10465,13 @@ th_date_now(void) struct tm tm = {0}; gmtime_r(&t, &tm); th_date date = {0}; - date.year = tm.tm_year; - date.month = tm.tm_mon; - date.day = tm.tm_mday; - date.weekday = tm.tm_wday; - date.hour = tm.tm_hour; - date.minute = tm.tm_min; - date.second = tm.tm_sec; + date.year = (unsigned int)tm.tm_year; + date.month = (unsigned int)tm.tm_mon; + date.day = (unsigned int)tm.tm_mday; + date.weekday = (unsigned int)tm.tm_wday; + date.hour = (unsigned int)tm.tm_hour; + date.minute = (unsigned int)tm.tm_min; + date.second = (unsigned int)tm.tm_sec; return date; } diff --git a/th.h b/th.h index eef4192..b61c7f0 100644 --- a/th.h +++ b/th.h @@ -172,13 +172,13 @@ typedef struct th_bind_opt { * @brief Date struct corresponding to the Date header in HTTP. Always in GMT. */ typedef struct th_date { - unsigned year : 16; - unsigned month : 8; - unsigned day : 8; - unsigned weekday : 8; - unsigned hour : 8; - unsigned minute : 8; - unsigned second : 8; + unsigned int year : 16; + unsigned int month : 8; + unsigned int day : 8; + unsigned int weekday : 8; + unsigned int hour : 8; + unsigned int minute : 8; + unsigned int second : 8; } th_date; typedef struct th_duration {