// vim:fileencoding=utf-8:foldmethod=marker #include "file.h" #include "../os/cpath/cpath.h" #include "../../common/assert/assert.h" #include "../../common/aliases/aliases.h" #include "../../primitives/array/array.h" #include "../../primitives/strings/str8/str8.h" #include File *wapp_file_open(Str8RO *filepath, FileAccessMode mode) { persistent const char *modes[FILE_ACCESS_MODE_COUNT] = { [WAPP_FA_MODE_R] = "r", [WAPP_FA_MODE_W] = "w", [WAPP_FA_MODE_A] = "a", [WAPP_FA_MODE_R_EX] = "r+", [WAPP_FA_MODE_W_EX] = "w+", [WAPP_FA_MODE_A_EX] = "a+", [WAPP_FA_MODE_RB] = "rb", [WAPP_FA_MODE_WB] = "wb", [WAPP_FA_MODE_AB] = "ab", [WAPP_FA_MODE_RB_EX] = "rb+", [WAPP_FA_MODE_WB_EX] = "wb+", [WAPP_FA_MODE_AB_EX] = "ab+", [WAPP_FA_MODE_WX] = "wx", [WAPP_FA_MODE_WX_EX] = "wx+", [WAPP_FA_MODE_WBX] = "wbx", [WAPP_FA_MODE_WBX_EX] = "wbx+", }; persistent c8 tmp[WAPP_PATH_MAX] = {0}; wapp_debug_assert(filepath->size < WAPP_PATH_MAX, "`filepath` exceeds max path limit."); memset(tmp, 0, WAPP_PATH_MAX); memcpy(tmp, filepath->buf, filepath->size); return fopen((const char *)tmp, modes[mode]); } u64 wapp_file_get_current_position(File *file) { wapp_debug_assert(file != NULL, "`file` should not be NULL."); return (u64)ftell(file); } i32 wapp_file_seek(File *file, u64 offset, FileSeekOrigin origin) { wapp_debug_assert(file != NULL, "`file` should not be NULL."); return fseek(file, offset, origin); } u64 wapp_file_get_length(File *file) { wapp_debug_assert(file != NULL, "`file` should not be NULL."); u64 current = wapp_file_get_current_position(file); wapp_file_seek(file, 0, WAPP_SEEK_END); u64 output = ftell(file); // Restore position wapp_file_seek(file, current, WAPP_SEEK_START); return output; } u64 wapp_file_read(GenericArray *dst, File *file, u64 item_count) { wapp_debug_assert(dst != NULL && dst->items != NULL && file != NULL, "`dst`, `dst->items` and `file` should not be NULL."); u64 file_length = wapp_file_get_length(file); u64 dst_byte_capacity = dst->item_size * dst->capacity; u64 req_byte_count = item_count * dst->item_size; u64 copy_byte_count = 0; if (req_byte_count <= file_length && req_byte_count <= dst_byte_capacity) { copy_byte_count = req_byte_count; } else { copy_byte_count = file_length <= dst_byte_capacity ? file_length : dst_byte_capacity; } dst->count = fread(dst->items, sizeof(u8), copy_byte_count, file) / dst->item_size; return dst->count; } u64 wapp_file_write(const GenericArray *src, File *file, u64 item_count) { wapp_debug_assert(src != NULL && src->items != NULL && file != NULL, "`src`, `src->items` and `file` should not be NULL."); u64 src_byte_count = src->count * src->item_size; u64 req_byte_count = item_count * src->item_size; u64 to_copy = req_byte_count <= src_byte_count ? req_byte_count : src_byte_count; return fwrite(src->items, sizeof(u8), to_copy, file); } i32 wapp_file_flush(File *file) { wapp_debug_assert(file != NULL, "`file` should not be NULL."); return fflush(file); } i32 wapp_file_close(File *file) { wapp_debug_assert(file != NULL, "`file` should not be NULL."); return fclose(file); }