#include "internal.h" bool file_exists(cstr path){ if(path[0]=='.'){ if(path[1]==0 || (path[1]==path_sep && path[2]==0)) return false; // . or ./ is not a file // else if(path[1]=='.' && path[2]==path_sep) //TODO path_resolve because windows doesnt recognize .\ pattern } #if TLIBC_FS_USE_WINDOWS_H DWORD dwAttrib = GetFileAttributes(path); return (bool)( (dwAttrib != INVALID_FILE_ATTRIBUTES) && // file exists !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); // file is not directory #else struct stat stats; i32 rez=stat(path, &stats); return (bool)( (rez!=-1) && // file exists !(S_ISDIR(stats.st_mode))); // file is not directory #endif } Result(FILE*) file_open(cstr file_name, cstr fopen_mode){ FILE* f = fopen(file_name, fopen_mode); if(f == NULL){ char* errno_s = strerror_malloc(errno); ResultVar(void) err = RESULT_ERROR_FMT( "Can't open (%s) file '%s': %s", fopen_mode, file_name, errno_s); free(errno_s); return err; } return RESULT_VALUE(p, f); } Result(FILE*) file_openOrCreateReadWrite(cstr file_name){ cstr fopen_mode = "rb+"; FILE* f = fopen(file_name, fopen_mode); if(f == NULL){ fopen_mode = "wb+"; f = fopen(file_name, fopen_mode); if(f == NULL){ char* errno_s = strerror_malloc(errno); ResultVar(void) err = RESULT_ERROR_FMT( "Can't open (%s) file '%s': %s", fopen_mode, file_name, errno_s); free(errno_s); return err; } } return RESULT_VALUE(p, f); } Result(i64) file_tellPos(FILE* f){ i64 r = IFWIN(_ftelli64, ftello64)(f); if(r < 0){ return RESULT_ERROR_ERRNO(); } return RESULT_VALUE(i, r); } Result(void) file_seek(FILE* f, i64 offset, SeekOrigin origin){ if(IFWIN(_fseeki64, fseeko64)(f, offset, (int)origin) != 0){ char* errno_s = strerror_malloc(errno); ResultVar(void) err = RESULT_ERROR_FMT( "Can't seek (offset: "FMT_i64", origin: %i) in file: %s", offset, origin, errno_s); free(errno_s); return err; } return RESULT_VOID; } Result(i64) file_getSize(FILE* f){ Deferral(4); // get current position try(i64 original_pos, i, file_tellPos(f)); // seek to end try_void(file_seek(f, 0, SeekOrigin_End)); try(i64 size, i, file_tellPos(f)); // restore original position try_void(file_seek(f, original_pos, SeekOrigin_Start)); Return RESULT_VALUE(i, size); } 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 "FMT_u64" structures out of "FMT_u64, r, exact_count); } return RESULT_VOID; } Result(void) file_readWhole(FILE* f, Array(u8)* out_buf){ Deferral(1); bool success = false; try(i64 f_size, i, file_getSize(f)); Array(u8) buf = Array_u8_alloc(f_size); Defer(if(!success) Array_u8_destroy(&buf)); try_void(file_readBytesArrayExactly(f, buf)); *out_buf = buf; success = true; Return RESULT_VOID; } Result(void) file_readWholeText(FILE* f, str* out_str){ Deferral(1); bool success = false; try(i64 f_size, i, file_getSize(f)); Array(u8) buf = Array_u8_alloc(f_size + 1); Defer(if(!success) Array_u8_destroy(&buf)); buf.len--; try_void(file_readBytesArrayExactly(f, buf)); buf.data[buf.len] = '\0'; *out_str = Array_u8_castTo_str(buf, true); success = true; Return RESULT_VOID; }