diff --git a/include/tlibc/errors.h b/include/tlibc/errors.h index 1928157..2b001a2 100755 --- a/include/tlibc/errors.h +++ b/include/tlibc/errors.h @@ -41,7 +41,8 @@ typedef struct Result_ { #define RESULT_ERROR(MSG, IS_MSG_ON_HEAP) (Result_){ .error = Error_create(MSG, IS_MSG_ON_HEAP, ErrorCallPos_here()) } -#define RESULT_ERROR_FMT(FORMAT, ARGS...) RESULT_ERROR(sprintf_malloc(4096, FORMAT, ARGS), true) +#define RESULT_ERROR_FMT(FORMAT, ARGS...) RESULT_ERROR(sprintf_malloc(4096, FORMAT ,##ARGS), true) +#define RESULT_ERROR_ERRNO() RESULT_ERROR(strerror(errno), false) #define RESULT_VOID (Result_){ .error = NULL } #define RESULT_VALUE(FIELD, V) (Result_){ .error = NULL, .FIELD = V } diff --git a/include/tlibc/filesystem.h b/include/tlibc/filesystem.h index 3996000..21eb88b 100644 --- a/include/tlibc/filesystem.h +++ b/include/tlibc/filesystem.h @@ -1,17 +1,24 @@ #pragma once +#include #include "std.h" #include "errors.h" #include "string/str.h" +#include "collections/Array.h" -#if !defined(KFS_USE_WINDOWS_H) +#if !defined(TLIBC_FS_USE_WINDOWS_H) #if defined(_WIN64) || defined(_WIN32) - #define KFS_USE_WINDOWS_H 1 + #define TLIBC_FS_USE_WINDOWS_H 1 #else - #define KFS_USE_WINDOWS_H 0 + #define TLIBC_FS_USE_WINDOWS_H 0 #endif #endif -#if KFS_USE_WINDOWS_H + +////////////////////////////////////////////////////////////////////////////// +// PATH // +////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN64) || defined(_WIN32) #define path_sep '\\' #define path_seps "\\" #define path_notsep '/' @@ -32,6 +39,10 @@ str path_dirname(str path); str path_basename(str path, bool remove_ext); +////////////////////////////////////////////////////////////////////////////// +// FILE // +////////////////////////////////////////////////////////////////////////////// + /// open a file for reading #define FO_Read "rb" /// (re)create a file for writing @@ -45,10 +56,11 @@ str path_basename(str path, bool remove_ext); Result(FILE*) file_open(cstr file_name, cstr fopen_mode); -bool file_exists(cstr path); +bool file_exists(cstr path); Result(i64) file_getSize(FILE* f); + typedef enum SeekOrigin { SeekOrigin_Start = SEEK_SET, SeekOrigin_Current = SEEK_CUR, @@ -58,6 +70,58 @@ typedef enum SeekOrigin { Result(void) file_seek(FILE* f, i64 offset, SeekOrigin origin); +Result(void) file_writeByte(FILE* f, u8 b); +Result(void) file_writeStructs(FILE* f, const void* src, u64 struct_size, u64 count); + +static inline Result(void) file_writeBytes(FILE* f, const void* src, u64 size){ + return file_writeStructs(f, src, size, 1); +} + +static inline Result(void) file_writeBytesArray(FILE* f, Array(u8) src){ + return file_writeStructs(f, src.data, src.size, 1); +} + + +/// @param out_byte is not set on error or end of file +/// @return true if byte was read, false if end of file was reached +Result(bool) file_readByte(FILE* f, u8* out_byte); + + +/// @param max_count maximum number of structs to read +/// @return number of structs that were read (<=max_count) +Result(u64) file_readStructs(FILE* f, void* dst, u64 struct_size, u64 max_count); + +/// @param max_count maximum number of bytes to read +/// @return number of bytes that were read (<=max_count) +static inline Result(u64) file_readBytes(FILE* f, void* dst, u64 max_count){ + return file_readStructs(f, dst, 1, max_count); +} + +/// @param dst array where .size is the maximum number of bytes to read +/// @return number of bytes that were read (<=max_count) +static inline Result(u64) file_readBytesArray(FILE* f, Array(u8) dst){ + return file_readStructs(f, dst.data, 1, dst.size); +} + + +/// @param max_count exact number of structs to read +Result(void) file_readStructsExactly(FILE* f, void* dst, u64 struct_size, u64 exact_count); + +/// @param exact_count exact number of bytes to read +static inline Result(void) file_readBytesExactly(FILE* f, void* dst, u64 exact_count){ + return file_readStructsExactly(f, dst, 1, exact_count); +} + +/// @param dst array where .size is the exact number of bytes to read +static inline Result(void) file_readBytesArrayExactly(FILE* f, Array(u8) dst){ + return file_readStructsExactly(f, dst.data, 1, dst.size); +} + +////////////////////////////////////////////////////////////////////////////// +// DIRECTORY // +////////////////////////////////////////////////////////////////////////////// + bool dir_exists(cstr path); +/// @brief creates directories specified in path recursively if they don't exist Result(void) dir_create(cstr path); diff --git a/src/filesystem/dir.c b/src/filesystem/dir.c index 73ad5e1..8eb0b10 100644 --- a/src/filesystem/dir.c +++ b/src/filesystem/dir.c @@ -1,5 +1,5 @@ #include "tlibc/filesystem.h" -#include "io_includes.h" +#include "internal.h" bool dir_exists(cstr path){ if(path[0]=='.'){ @@ -8,7 +8,7 @@ bool dir_exists(cstr path){ // else if(path[1]=='.' && path[2]==path_sep) //TODO path_resolve because windows doesnt recognize .\ pattern } -#if KFS_USE_WINDOWS_H +#if TLIBC_FS_USE_WINDOWS_H DWORD dwAttrib = GetFileAttributes(path); return (bool)( (dwAttrib != INVALID_FILE_ATTRIBUTES) && // file exists @@ -29,7 +29,7 @@ Result(void) dir_create(cstr path){ char* parentDir= str_copy(path_dirname(str_from_cstr((void*)path))).data; try_void(dir_create(parentDir), free(parentDir)); free(parentDir); -#if KFS_USE_WINDOWS_H +#if TLIBC_FS_USE_WINDOWS_H if(!CreateDirectory(path, NULL)) #else if(mkdir(path, 0777) == -1) diff --git a/src/filesystem/file.c b/src/filesystem/file.c index 7d7f5e4..313de5a 100644 --- a/src/filesystem/file.c +++ b/src/filesystem/file.c @@ -1,5 +1,5 @@ #include "tlibc/filesystem.h" -#include "io_includes.h" +#include "internal.h" bool file_exists(cstr path){ if(path[0]=='.'){ @@ -9,7 +9,7 @@ bool file_exists(cstr path){ //TODO path_resolve because windows doesnt recognize .\ pattern } -#if KFS_USE_WINDOWS_H +#if TLIBC_FS_USE_WINDOWS_H DWORD dwAttrib = GetFileAttributes(path); return (bool)( (dwAttrib != INVALID_FILE_ATTRIBUTES) && // file exists @@ -35,7 +35,7 @@ Result(FILE*) file_open(cstr file_name, cstr fopen_mode){ Result(i64) file_getSize(FILE* f){ i64 r = IFWIN(_ftelli64, ftello64)(f); if(r < 0){ - return RESULT_ERROR(strerror(errno), false); + return RESULT_ERROR_ERRNO(); } return RESULT_VALUE(i, r); } @@ -47,4 +47,53 @@ Result(void) file_seek(FILE* f, i64 offset, SeekOrigin origin){ offset, origin, strerror(errno)); } return RESULT_VOID; -} \ No newline at end of file +} + + +Result(void) file_writeStructs(FILE* f, const void* src, u64 struct_size, u64 count){ + u64 r = fwrite(src, struct_size, count, f); + if(r != count){ + return RESULT_ERROR_ERRNO(); + } + return RESULT_VOID; +} + +Result(void) file_writeByte(FILE* f, u8 b){ + if(fputc(b, f) != 0){ + return RESULT_ERROR_ERRNO(); + } + return RESULT_VOID; +} + +Result(bool) file_readByte(FILE* f, u8* out_byte){ + int r = fgetc(f); + if(ferror(f)){ + return RESULT_ERROR_ERRNO(); + } + if(feof(f)){ + return RESULT_VALUE(u, false); + } + *out_byte = r; + return RESULT_VALUE(u, true); +} + +Result(u64) file_readStructs(FILE* f, void* dst, u64 struct_size, u64 max_count){ + u64 r = fread(dst, struct_size, max_count, f); + if(ferror(f)){ + return RESULT_ERROR_ERRNO(); + } + return RESULT_VALUE(u, r); +} + +Result(void) file_readStructsExactly(FILE* f, void* dst, u64 struct_size, u64 exact_count){ + u64 r = fread(dst, struct_size, exact_count, f); + if(ferror(f)){ + return RESULT_ERROR_ERRNO(); + } + if(r != exact_count){ + return RESULT_ERROR_FMT( + "read " IFWIN("%llu", "%lu") " structures out of " IFWIN("%llu", "%lu"), + r, exact_count); + } + return RESULT_VOID; +} diff --git a/src/filesystem/io_includes.h b/src/filesystem/internal.h similarity index 66% rename from src/filesystem/io_includes.h rename to src/filesystem/internal.h index 2b75fc8..4addc95 100644 --- a/src/filesystem/io_includes.h +++ b/src/filesystem/internal.h @@ -1,6 +1,7 @@ #pragma once -#if KFS_USE_WINDOWS_H +#include "tlibc/filesystem.h" +#if TLIBC_FS_USE_WINDOWS_H #include #else #include