diff --git a/src/core/file/file.c b/src/core/file/file.c new file mode 100644 index 0000000..cd69fba --- /dev/null +++ b/src/core/file/file.c @@ -0,0 +1,103 @@ +// 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); +} diff --git a/src/core/file/file.h b/src/core/file/file.h new file mode 100644 index 0000000..3ed21bf --- /dev/null +++ b/src/core/file/file.h @@ -0,0 +1,57 @@ +// vim:fileencoding=utf-8:foldmethod=marker + +#ifndef FILE_H +#define FILE_H + +#include "../../common/aliases/aliases.h" +#include "../../primitives/array/array.h" +#include "../../primitives/strings/str8/str8.h" +#include + +#ifdef WAPP_PLATFORM_CPP +BEGIN_C_LINKAGE +#endif // !WAPP_PLATFORM_CPP + +typedef FILE File; + +typedef enum { + WAPP_FA_MODE_R, // Equivalent to r + WAPP_FA_MODE_W, // Equivalent to w + WAPP_FA_MODE_A, // Equivalent to a + WAPP_FA_MODE_R_EX, // Equivalent to r+ + WAPP_FA_MODE_W_EX, // Equivalent to w+ + WAPP_FA_MODE_A_EX, // Equivalent to a+ + WAPP_FA_MODE_RB, // Equivalent to rb + WAPP_FA_MODE_WB, // Equivalent to wb + WAPP_FA_MODE_AB, // Equivalent to ab + WAPP_FA_MODE_RB_EX, // Equivalent to rb+ + WAPP_FA_MODE_WB_EX, // Equivalent to wb+ + WAPP_FA_MODE_AB_EX, // Equivalent to ab+ + WAPP_FA_MODE_WX, // Equivalent to wx + WAPP_FA_MODE_WX_EX, // Equivalent to wx+ + WAPP_FA_MODE_WBX, // Equivalent to wbx + WAPP_FA_MODE_WBX_EX, // Equivalent to wbx+ + + FILE_ACCESS_MODE_COUNT, +} FileAccessMode; + +typedef enum { + WAPP_SEEK_START = SEEK_SET, + WAPP_SEEK_CURRENT = SEEK_CUR, + WAPP_SEEK_END = SEEK_END, +} FileSeekOrigin; + +File *wapp_file_open(Str8RO *filename, FileAccessMode mode); +u64 wapp_file_get_current_position(File *file); +i32 wapp_file_seek(File *file, u64 offset, FileSeekOrigin origin); +u64 wapp_file_get_length(File *file); +u64 wapp_file_read(GenericArray *dst, File *file, u64 item_count); +u64 wapp_file_write(const GenericArray *src, File *file, u64 item_count); +i32 wapp_file_flush(File *file); +i32 wapp_file_close(File *file); + +#ifdef WAPP_PLATFORM_CPP +END_C_LINKAGE +#endif // !WAPP_PLATFORM_CPP + +#endif // !FILE_H diff --git a/src/core/wapp_core.c b/src/core/wapp_core.c index 34d8bcb..eb11156 100644 --- a/src/core/wapp_core.c +++ b/src/core/wapp_core.c @@ -4,6 +4,7 @@ #define WAPP_CORE_C #include "wapp_core.h" +#include "file/file.c" #include "os/shell/termcolour/posix/termcolour_posix.c" #include "os/shell/termcolour/win/termcolour_win.c" #include "os/shell/termcolour/termcolour.c" diff --git a/src/core/wapp_core.h b/src/core/wapp_core.h index 54320cd..964508a 100644 --- a/src/core/wapp_core.h +++ b/src/core/wapp_core.h @@ -3,6 +3,7 @@ #ifndef WAPP_CORE_H #define WAPP_CORE_H +#include "file/file.h" #include "os/shell/termcolour/termcolour.h" #include "os/shell/termcolour/terminal_colours.h" #include "os/shell/commander/commander.h"