Implement Windows file IO
This commit is contained in:
159
src/os/file/win/file_win.c
Normal file
159
src/os/file/win/file_win.c
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#include "file_win.h"
|
||||||
|
#include "../../../common/platform/platform.h"
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
#include "../file.h"
|
||||||
|
#include "../../cpath/cpath.h"
|
||||||
|
#include "../../../common/aliases/aliases.h"
|
||||||
|
#include "../../../base/array/array.h"
|
||||||
|
#include "../../../base/strings/str8/str8.h"
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <fileapi.h>
|
||||||
|
#include <intsafe.h>
|
||||||
|
|
||||||
|
wapp_intern DWORD file_accesses[FILE_ACCESS_MODE_COUNT] = {
|
||||||
|
[WAPP_ACCESS_READ] = FILE_READ_DATA,
|
||||||
|
[WAPP_ACCESS_WRITE] = FILE_WRITE_DATA,
|
||||||
|
[WAPP_ACCESS_APPEND] = FILE_APPEND_DATA,
|
||||||
|
[WAPP_ACCESS_READ_EX] = FILE_READ_DATA | FILE_WRITE_DATA,
|
||||||
|
[WAPP_ACCESS_WRITE_EX] = FILE_READ_DATA | FILE_WRITE_DATA,
|
||||||
|
[WAPP_ACCESS_APPEND_EX] = FILE_READ_DATA | FILE_APPEND_DATA,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = FILE_WRITE_DATA,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = FILE_READ_DATA | FILE_WRITE_DATA,
|
||||||
|
};
|
||||||
|
|
||||||
|
wapp_intern DWORD creation_dispositions[FILE_ACCESS_MODE_COUNT] = {
|
||||||
|
[WAPP_ACCESS_READ] = OPEN_EXISTING,
|
||||||
|
[WAPP_ACCESS_WRITE] = CREATE_ALWAYS,
|
||||||
|
[WAPP_ACCESS_APPEND] = OPEN_ALWAYS,
|
||||||
|
[WAPP_ACCESS_READ_EX] = OPEN_EXISTING,
|
||||||
|
[WAPP_ACCESS_WRITE_EX] = CREATE_ALWAYS,
|
||||||
|
[WAPP_ACCESS_APPEND_EX] = OPEN_ALWAYS,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = CREATE_NEW,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = CREATE_NEW,
|
||||||
|
};
|
||||||
|
|
||||||
|
wapp_intern DWORD sharing_modes[FILE_ACCESS_MODE_COUNT] = {
|
||||||
|
[WAPP_ACCESS_READ] = FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
[WAPP_ACCESS_WRITE] = FILE_SHARE_READ,
|
||||||
|
[WAPP_ACCESS_APPEND] = FILE_SHARE_READ,
|
||||||
|
[WAPP_ACCESS_READ_EX] = FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
[WAPP_ACCESS_WRITE_EX] = FILE_SHARE_READ,
|
||||||
|
[WAPP_ACCESS_APPEND_EX] = FILE_SHARE_READ,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = FILE_SHARE_READ,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = FILE_SHARE_READ,
|
||||||
|
};
|
||||||
|
|
||||||
|
wapp_intern DWORD file_seek_origins[FILE_SEEK_ORIGIN_COUNT] = {
|
||||||
|
[WAPP_SEEK_START] = FILE_BEGIN,
|
||||||
|
[WAPP_SEEK_CURRENT] = FILE_CURRENT,
|
||||||
|
[WAPP_SEEK_END] = FILE_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
WFile *_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode) {
|
||||||
|
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
memset(tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(tmp, filepath->buf, filepath->size);
|
||||||
|
|
||||||
|
HANDLE fh = CreateFileA((LPCSTR)tmp,
|
||||||
|
file_accesses[mode],
|
||||||
|
sharing_modes[mode],
|
||||||
|
NULL,
|
||||||
|
creation_dispositions[mode],
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
if (fh == INVALID_HANDLE_VALUE) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
WFile *output = wapp_mem_allocator_alloc(allocator, sizeof(WFile));
|
||||||
|
if (output) {
|
||||||
|
output->fh = fh;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
i64 _file_seek(WFile *file, i64 offset, FileSeekOrigin origin) {
|
||||||
|
LARGE_INTEGER distance = {0};
|
||||||
|
LARGE_INTEGER output = {0};
|
||||||
|
|
||||||
|
distance.QuadPart = offset;
|
||||||
|
|
||||||
|
if (!SetFilePointerEx(file->fh, distance, &output, file_seek_origins[origin])) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 _file_read(void* dst_buf, u64 byte_count, WFile* file, u64 file_length) {
|
||||||
|
u64 copy_byte_count = file_length <= byte_count ? file_length : byte_count;
|
||||||
|
wapp_debug_assert(copy_byte_count <= DWORD_MAX, "Attempting to read large number of bytes at once");
|
||||||
|
|
||||||
|
DWORD read_count = 0;
|
||||||
|
if (!ReadFile(file->fh, dst_buf, (DWORD)copy_byte_count, &read_count, NULL)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (u64)read_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
i64 _file_write(const void *src_buf, WFile *file, u64 byte_count) {
|
||||||
|
wapp_debug_assert(byte_count <= DWORD_MAX, "Attempting to write large number of bytes at once");
|
||||||
|
|
||||||
|
DWORD write_count = 0;
|
||||||
|
if (!WriteFile(file->fh, src_buf, (DWORD)byte_count, &write_count, NULL)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (i64)write_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_flush(WFile *file) {
|
||||||
|
if (!FlushFileBuffers(file->fh)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_close(WFile *file) {
|
||||||
|
if (!CloseHandle(file->fh)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_rename(Str8RO *old_filepath, Str8RO *new_filepath) {
|
||||||
|
wapp_persist c8 old_tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
wapp_persist c8 new_tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
memset(old_tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(old_tmp, old_filepath->buf, old_filepath->size);
|
||||||
|
memset(new_tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(new_tmp, new_filepath->buf, new_filepath->size);
|
||||||
|
|
||||||
|
if (!MoveFile((LPCSTR)old_tmp, (LPCSTR)new_tmp)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_remove(Str8RO *filepath) {
|
||||||
|
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
memset(tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(tmp, filepath->buf, filepath->size);
|
||||||
|
|
||||||
|
if (!DeleteFile((LPCSTR)tmp)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
31
src/os/file/win/file_win.h
Normal file
31
src/os/file/win/file_win.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#ifndef FILE_WIN_H
|
||||||
|
#define FILE_WIN_H
|
||||||
|
|
||||||
|
#include "../../../common/aliases/aliases.h"
|
||||||
|
#include "../../../common/platform/platform.h"
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
#define END_OF_LINE "\r\n"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <fileapi.h>
|
||||||
|
|
||||||
|
struct WFile {
|
||||||
|
HANDLE fh;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
|
#endif // !FILE_WIN_H
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "wapp_os.h"
|
#include "wapp_os.h"
|
||||||
#include "file/file.c"
|
#include "file/file.c"
|
||||||
#include "file/posix/file_posix.c"
|
#include "file/posix/file_posix.c"
|
||||||
|
#include "file/win/file_win.c"
|
||||||
#include "shell/termcolour/posix/termcolour_posix.c"
|
#include "shell/termcolour/posix/termcolour_posix.c"
|
||||||
#include "shell/termcolour/win/termcolour_win.c"
|
#include "shell/termcolour/win/termcolour_win.c"
|
||||||
#include "shell/termcolour/termcolour.c"
|
#include "shell/termcolour/termcolour.c"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "file/file.h"
|
#include "file/file.h"
|
||||||
#include "file/posix/file_posix.h"
|
#include "file/posix/file_posix.h"
|
||||||
|
#include "file/win/file_win.h"
|
||||||
#include "shell/termcolour/termcolour.h"
|
#include "shell/termcolour/termcolour.h"
|
||||||
#include "shell/termcolour/terminal_colours.h"
|
#include "shell/termcolour/terminal_colours.h"
|
||||||
#include "shell/commander/commander.h"
|
#include "shell/commander/commander.h"
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ wapp_intern i32 dst_buf[DST_CAPACITY] = {0};
|
|||||||
|
|
||||||
TestFuncResult test_wapp_file_open(void) {
|
TestFuncResult test_wapp_file_open(void) {
|
||||||
arena = wapp_mem_arena_allocator_init(KiB(16));
|
arena = wapp_mem_arena_allocator_init(KiB(16));
|
||||||
test_fp = wapp_file_open(&arena, &test_filename, WAPP_ACCESS_WRITE_BIN_EX);
|
test_fp = wapp_file_open(&arena, &test_filename, WAPP_ACCESS_WRITE_EX);
|
||||||
return wapp_tester_result(test_fp != NULL);
|
return wapp_tester_result(test_fp != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_wapp_file_get_current_position(void) {
|
TestFuncResult test_wapp_file_get_current_position(void) {
|
||||||
u64 pos = wapp_file_get_current_position(test_fp);
|
i64 pos = wapp_file_get_current_position(test_fp);
|
||||||
return wapp_tester_result(pos == 0);
|
return wapp_tester_result(pos == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,8 +47,14 @@ TestFuncResult test_wapp_file_read(void) {
|
|||||||
u64 count = wapp_file_read((void *)dst_buf, test_fp, byte_count);
|
u64 count = wapp_file_read((void *)dst_buf, test_fp, byte_count);
|
||||||
b8 result = count == byte_count;
|
b8 result = count == byte_count;
|
||||||
|
|
||||||
for (u64 i = 0; i < DST_CAPACITY; ++i) {
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
result = result && (dst_buf[i] == *wapp_array_get(i32, src_array1, i));
|
// MSVC Spectre mitigation warnings
|
||||||
|
u64 index = 0;
|
||||||
|
b8 running = true;
|
||||||
|
while (running) {
|
||||||
|
result = result && (dst_buf[index] == *wapp_array_get(i32, src_array1, index));
|
||||||
|
++index;
|
||||||
|
running = index < DST_CAPACITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
@@ -58,9 +64,9 @@ TestFuncResult test_wapp_file_write(void) {
|
|||||||
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
||||||
|
|
||||||
u64 expected_count = wapp_array_count(src_array2) * wapp_array_item_size(src_array2);
|
u64 expected_count = wapp_array_count(src_array2) * wapp_array_item_size(src_array2);
|
||||||
u64 count = wapp_file_write((void *)src_array2, test_fp, expected_count);
|
i64 count = wapp_file_write((void *)src_array2, test_fp, expected_count);
|
||||||
|
|
||||||
return wapp_tester_result(count == expected_count);
|
return wapp_tester_result(count >= 0 && (u64)count == expected_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_wapp_file_read_array(void) {
|
TestFuncResult test_wapp_file_read_array(void) {
|
||||||
@@ -70,8 +76,14 @@ TestFuncResult test_wapp_file_read_array(void) {
|
|||||||
b8 result = count == wapp_array_count(src_array1) &&
|
b8 result = count == wapp_array_count(src_array1) &&
|
||||||
wapp_array_count(dst_array) == wapp_array_count(src_array1);
|
wapp_array_count(dst_array) == wapp_array_count(src_array1);
|
||||||
|
|
||||||
for (u64 i = 0; i < wapp_array_count(dst_array); ++i) {
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
result = result && (*wapp_array_get(i32, dst_array, i) == *wapp_array_get(i32, src_array1, i));
|
// MSVC Spectre mitigation warnings
|
||||||
|
u64 index = 0;
|
||||||
|
b8 running = true;
|
||||||
|
while (running) {
|
||||||
|
result = result && (*wapp_array_get(i32, dst_array, index) == *wapp_array_get(i32, src_array1, index));
|
||||||
|
++index;
|
||||||
|
running = index < wapp_array_count(dst_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
@@ -80,9 +92,9 @@ TestFuncResult test_wapp_file_read_array(void) {
|
|||||||
TestFuncResult test_wapp_file_write_array(void) {
|
TestFuncResult test_wapp_file_write_array(void) {
|
||||||
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
||||||
|
|
||||||
u64 count = wapp_file_write_array((GenericArray)src_array3, test_fp, wapp_array_count(src_array3));
|
i64 count = wapp_file_write_array((GenericArray)src_array3, test_fp, wapp_array_count(src_array3));
|
||||||
|
|
||||||
return wapp_tester_result(count == wapp_array_count(src_array3));
|
return wapp_tester_result(count >= 0 && (u64)count == wapp_array_count(src_array3));
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_wapp_file_flush(void) {
|
TestFuncResult test_wapp_file_flush(void) {
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ TestFuncResult test_wapp_file_open(void) {
|
|||||||
src_array2 = wapp_array(i32, 5, 6, 7, 8, 9);
|
src_array2 = wapp_array(i32, 5, 6, 7, 8, 9);
|
||||||
src_array3 = wapp_array(i32, 10, 11, 12, 13, 14);
|
src_array3 = wapp_array(i32, 10, 11, 12, 13, 14);
|
||||||
dst_array = wapp_array_with_capacity(i32, DST_CAPACITY, false);
|
dst_array = wapp_array_with_capacity(i32, DST_CAPACITY, false);
|
||||||
test_fp = wapp_file_open(&arena, &test_filename, WAPP_ACCESS_WRITE_BIN_EX);
|
test_fp = wapp_file_open(&arena, &test_filename, WAPP_ACCESS_WRITE_EX);
|
||||||
return wapp_tester_result(test_fp != NULL);
|
return wapp_tester_result(test_fp != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_wapp_file_get_current_position(void) {
|
TestFuncResult test_wapp_file_get_current_position(void) {
|
||||||
u64 pos = wapp_file_get_current_position(test_fp);
|
i64 pos = wapp_file_get_current_position(test_fp);
|
||||||
return wapp_tester_result(pos == 0);
|
return wapp_tester_result(pos == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,8 +51,14 @@ TestFuncResult test_wapp_file_read(void) {
|
|||||||
u64 count = wapp_file_read((void *)dst_buf, test_fp, byte_count);
|
u64 count = wapp_file_read((void *)dst_buf, test_fp, byte_count);
|
||||||
b8 result = count == byte_count;
|
b8 result = count == byte_count;
|
||||||
|
|
||||||
for (u64 i = 0; i < DST_CAPACITY; ++i) {
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
result = result && (dst_buf[i] == *wapp_array_get(i32, src_array1, i));
|
// MSVC Spectre mitigation warnings
|
||||||
|
u64 index = 0;
|
||||||
|
b8 running = true;
|
||||||
|
while (running) {
|
||||||
|
result = result && (dst_buf[index] == *wapp_array_get(i32, src_array1, index));
|
||||||
|
++index;
|
||||||
|
running = index < DST_CAPACITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
@@ -62,9 +68,9 @@ TestFuncResult test_wapp_file_write(void) {
|
|||||||
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
||||||
|
|
||||||
u64 expected_count = wapp_array_count(src_array2) * wapp_array_item_size(src_array2);
|
u64 expected_count = wapp_array_count(src_array2) * wapp_array_item_size(src_array2);
|
||||||
u64 count = wapp_file_write((void *)src_array2, test_fp, expected_count);
|
i64 count = wapp_file_write((void *)src_array2, test_fp, expected_count);
|
||||||
|
|
||||||
return wapp_tester_result(count == expected_count);
|
return wapp_tester_result(count >= 0 && (u64)count == expected_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_wapp_file_read_array(void) {
|
TestFuncResult test_wapp_file_read_array(void) {
|
||||||
@@ -74,8 +80,14 @@ TestFuncResult test_wapp_file_read_array(void) {
|
|||||||
b8 result = count == wapp_array_count(src_array1) &&
|
b8 result = count == wapp_array_count(src_array1) &&
|
||||||
wapp_array_count(dst_array) == wapp_array_count(src_array1);
|
wapp_array_count(dst_array) == wapp_array_count(src_array1);
|
||||||
|
|
||||||
for (u64 i = 0; i < wapp_array_count(dst_array); ++i) {
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
result = result && (*wapp_array_get(i32, dst_array, i) == *wapp_array_get(i32, src_array1, i));
|
// MSVC Spectre mitigation warnings
|
||||||
|
u64 index = 0;
|
||||||
|
b8 running = true;
|
||||||
|
while (running) {
|
||||||
|
result = result && (*wapp_array_get(i32, dst_array, index) == *wapp_array_get(i32, src_array1, index));
|
||||||
|
++index;
|
||||||
|
running = index < wapp_array_count(dst_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
@@ -84,9 +96,9 @@ TestFuncResult test_wapp_file_read_array(void) {
|
|||||||
TestFuncResult test_wapp_file_write_array(void) {
|
TestFuncResult test_wapp_file_write_array(void) {
|
||||||
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
||||||
|
|
||||||
u64 count = wapp_file_write_array((GenericArray)src_array3, test_fp, wapp_array_count(src_array3));
|
i64 count = wapp_file_write_array((GenericArray)src_array3, test_fp, wapp_array_count(src_array3));
|
||||||
|
|
||||||
return wapp_tester_result(count == wapp_array_count(src_array3));
|
return wapp_tester_result(count >= 0 && (u64)count == wapp_array_count(src_array3));
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_wapp_file_flush(void) {
|
TestFuncResult test_wapp_file_flush(void) {
|
||||||
|
|||||||
Reference in New Issue
Block a user