From 1b1af5ff8541e5390b3504a4bce8714f5d0eacb7 Mon Sep 17 00:00:00 2001 From: Abdulmujeeb Raji Date: Tue, 18 Feb 2025 09:36:53 +0000 Subject: [PATCH] file system rewrite + more --- bastd/buffer.c | 97 ++++++++++++++----------------- bastd/examples/buffer.c | 2 +- bastd/os.c | 21 +++++-- bastd/os_windows.c | 126 +++++++++++++++++++++++----------------- bastd/rand.c | 4 +- bastd/slice.c | 51 +++++++++++++++- bastd/string.c | 9 ++- build.bat | 2 +- 8 files changed, 192 insertions(+), 120 deletions(-) diff --git a/bastd/buffer.c b/bastd/buffer.c index 07333b3..6706c4a 100644 --- a/bastd/buffer.c +++ b/bastd/buffer.c @@ -11,68 +11,34 @@ struct Buffer { #define BUFFER(raw, cap) ((Buffer){raw, cap, 0, FALSE}) -typedef enum BufferOutputType BufferOutputType; -enum BufferOutputType { - BufferOutputType_string = 0, - BufferOutputType_file, -}; - -typedef struct BufferOutput BufferOutput; -struct BufferOutput { - BufferOutputType type; - union { - S8 str; - int fd; - } data; -}; - -FUNCTION void -Buffer_flush(Buffer *b, BufferOutput out) -{ - switch (out.type) { - case BufferOutputType_string: { - b->error |= out.data.str.len < b->len; - m_memoryCopy(out.data.str.raw, b->raw, out.data.str.len); - } break; - case BufferOutputType_file: { - b->error |= out.data.fd < 0; - b->error |= !os_write(out.data.fd, b->raw, b->len); - } break; - } - b->len = 0; -} - // Utility FUNCTION S8 Buffer_buildS8(Buffer *b, m_Allocator *perm) { S8 res = S8_alloc(b->len, perm); - BufferOutput out = {0}; - out.type = BufferOutputType_string; - out.data.str = res; + b->error |= res.len < b->len; + m_memoryCopy(res.raw, b->raw, res.len); - Buffer_flush(b, out); + b->len = 0; return res; } FUNCTION void Buffer_standardOutput(Buffer *b) { - BufferOutput output = {0}; - output.type = BufferOutputType_file; - output.data.fd = 1; - Buffer_flush(b, output); + os_File stdout = os_getStdout(); + b->error |= !os_writeFile(stdout, b->raw, b->len); + b->len = 0; } FUNCTION void Buffer_fileOutput(Buffer *b, S8 filename) { - BufferOutput output = {0}; - output.type = BufferOutputType_file; - output.data.fd = os_openFile(filename.raw, TRUE); - Buffer_flush(b, output); - os_closeFile(output.data.fd); + os_File file = os_openFile(filename.raw); + b->error |= !os_writeFile(file, b->raw, b->len); + os_closeFile(file); + b->len = 0; } FUNCTION void @@ -115,6 +81,26 @@ Buffer_appendI64(Buffer *b, I64 x) Buffer_append(b, beg, end-beg); } +FUNCTION void +Buffer_appendU64Hex(Buffer *b, U64 x) +{ + U8 tmp[64]; + U8 *end = tmp + sizeof(tmp); + U8 *beg = end; + do { + char remainder = x % 16; + char c = 0; + if (remainder > 9) { + c = remainder +55; + } else { + c = remainder + '0'; + } + *--beg = c; + } while (x /= 16); + Buffer_appendS8(b, S8("0x")); + Buffer_append(b, beg, end-beg); +} + FUNCTION void Buffer_appendPtr(Buffer *b, void *p) { @@ -155,25 +141,26 @@ Buffer_appendF64(Buffer *b, F64 x, U64 num_decimals) FUNCTION void Buffer_appendFile(Buffer *b, S8 filename, m_Allocator *perm) { - int fd = os_openFile(filename.raw, FALSE); - U32 file_size = (U32)os_getFileSize(fd); + os_File file = os_openFile(filename.raw); - U8 *data = m_MAKE(U8, file_size, perm); - b->error |= os_read(fd, data, (int)file_size, &file_size); - Buffer_append(b, data, file_size); + U8 *data = m_MAKE(U8, file.size, perm); + b->error |= os_readFile(file, data, (int)file.size, &file.size); + Buffer_append(b, data, file.size); - os_closeFile(fd); - m_RELEASE(data, file_size, perm); + os_closeFile(file); + if (!file.already_exists) { + os_deleteFile(file); + } + m_RELEASE(data, file.size, perm); } FUNCTION void Buffer_appendStandardInput(Buffer *b, U64 max_read_size, m_Allocator *perm) { - int stdin_fd = 0; - U32 len = 0; - + int len = 0; U8 *data = m_MAKE(U8, max_read_size, perm); - b->error |= os_read(stdin_fd, data, (int)max_read_size, &len); + os_File stdin = os_getStdin(); + b->error |= os_readFile(stdin, data, (int)max_read_size, &len); Buffer_append(b, data, len); // NOTE maybe we should switch to sl_U8 so theres no max length for stdin diff --git a/bastd/examples/buffer.c b/bastd/examples/buffer.c index b962108..effadce 100644 --- a/bastd/examples/buffer.c +++ b/bastd/examples/buffer.c @@ -8,7 +8,7 @@ os_entry(void) m_Allocator perm = m_BUDDY_ALLOCATOR(buddy); Buffer buf = BUFFER(os_alloc(KILO(2)), KILO(2)); - Buffer_appendS8(&buf, S8("Hello, Buffered output!")); + Buffer_appendS8(&buf, S8("Hello, Buffered output! ")); Buffer_appendI64(&buf, 10245); S8 buf_built = Buffer_buildS8(&buf, &perm); diff --git a/bastd/os.c b/bastd/os.c index 1191bd8..777ddf0 100644 --- a/bastd/os.c +++ b/bastd/os.c @@ -3,11 +3,19 @@ FUNCTION void os_abort(char *msg); FUNCTION void *os_alloc(U64 cap); -FUNCTION B8 os_write(int fd, U8 *buf, int len); -FUNCTION B8 os_read(int fd, U8 *buf, int len, U32 *bytes_read); -FUNCTION U64 os_getFileSize(int fd); -FUNCTION int os_openFile(U8 *filename, B8 always_create); -FUNCTION B8 os_closeFile(int fd); + +typedef struct os_File os_File; +struct os_File; // Depends on the OS. Always tells you if the file existed before being opened + +FUNCTION os_File os_openFile(U8 *filename); +FUNCTION os_File os_getStdout(void); +FUNCTION os_File os_getStdin(void); + +FUNCTION B8 os_deleteFile(os_File file); +FUNCTION B8 os_closeFile(os_File file); + +FUNCTION B8 os_readFile(os_File file, U8 *buf, int len, U32 *bytes_read); +FUNCTION B8 os_writeFile(os_File file, U8 *buf, int len); typedef struct os_Thread os_Thread; struct os_Thread; // Depends on the OS @@ -36,7 +44,8 @@ enum { }; CALLBACK_EXPORT os_ErrorCode os_entry(void); -FUNCTION U64 os_rdtsc(void); +// Handle microseconds using U64 +FUNCTION U64 os_wallclock(void); #if defined(OS_WINDOWS) diff --git a/bastd/os_windows.c b/bastd/os_windows.c index bcf0868..5212dcd 100644 --- a/bastd/os_windows.c +++ b/bastd/os_windows.c @@ -25,66 +25,83 @@ os_alloc(U64 cap) return VirtualAlloc(NIL, cap, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); } -FUNCTION B8 -os_write(int fd, U8 *buf, int len) +struct os_File { + U8 *name; + HANDLE raw; + U64 size; + B8 already_exists; +}; + +FUNCTION os_File +os_openFile(U8 *filename) { - HANDLE h = GetStdHandle(-10 - fd); - if (h == INVALID_HANDLE_VALUE) { - h = (HANDLE)_get_osfhandle(fd); + os_File res = {0}; + + res.name = filename; + + U32 attribs = GetFileAttributes(res.name); + res.already_exists = (attribs != INVALID_FILE_ATTRIBUTES && + !(attribs & FILE_ATTRIBUTE_DIRECTORY)); + + DWORD open_style = CREATE_NEW; + if (res.already_exists) { + open_style = OPEN_EXISTING; } - if (h == INVALID_HANDLE_VALUE) { - return FALSE; - } - U32 dummy; - return WriteFile(h, buf, len, &dummy, 0); -} - -FUNCTION B8 -os_read(int fd, U8 *buf, int len, U32 *bytes_read) -{ - HANDLE h = GetStdHandle(-10 - fd); - if (h != INVALID_HANDLE_VALUE) { - // This *should be* stdin - ASSERT(fd == 0, "fd is 0 for stdin"); - - B8 res = ReadConsole(h, buf, len, bytes_read, NIL); - return res; - } else { - h = (HANDLE)_get_osfhandle(fd); - return ReadFile(h, buf, len, bytes_read, 0); - } -} - -FUNCTION U64 -os_getFileSize(int fd) -{ - HANDLE h = GetStdHandle(-10 - fd); - if (h == INVALID_HANDLE_VALUE) { - // This is a real file - h = (HANDLE)_get_osfhandle(fd); - } - + res.raw = CreateFileA(res.name, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, 0, open_style, FILE_ATTRIBUTE_NORMAL, 0); + LARGE_INTEGER file_size; - GetFileSizeEx(h, &file_size); - return (U64)file_size.QuadPart; + GetFileSizeEx(res.raw, &file_size); + res.size = (U64)file_size.QuadPart; + + return res; } -FUNCTION int -os_openFile(U8 *filename, B8 always_create) +FUNCTION os_File +os_getStdout(void) { - U32 open_style = OPEN_EXISTING; - if (always_create) { - open_style = CREATE_ALWAYS; - } - HANDLE file = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ, 0, open_style, 0, 0); - return _open_osfhandle((intptr_t)file, 0); + os_File res = {0}; + res.already_exists = TRUE; + res.name = "stdout"; + res.size = KILO(1); + res.raw = GetStdHandle((U32)(-11)); + return res; +} + +FUNCTION os_File +os_getStdin(void) +{ + os_File res = {0}; + res.already_exists = TRUE; + res.name = "stdin"; + res.size = KILO(1); + res.raw = GetStdHandle((U32)(-10)); + return res; +} + +FUNCTION B8 +os_deleteFile(os_File file) +{ + return DeleteFileA(file.name); } FUNCTION B8 -os_closeFile(int fd) +os_closeFile(os_File file) { - return _close(fd); + return CloseHandle(file.raw); +} + +FUNCTION B8 +os_writeFile(os_File file, U8 *buf, int len) +{ + U32 dummy; + return WriteFile(file.raw, buf, len, &dummy, 0); +} + +FUNCTION B8 +os_readFile(os_File file, U8 *buf, int len, U32 *bytes_read) +{ + return ReadFile(file.raw, buf, len, bytes_read, 0); } FUNCTION char ** @@ -181,9 +198,14 @@ os_Semaphore_wait(os_Semaphore semaphore) } FUNCTION U64 -os_rdtsc(void) +os_wallclock(void) { - return __rdtsc(); + LARGE_INTEGER count, freq; + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&count); + + U64 res = (count.QuadPart * 1000000) / freq.QuadPart; + return res; } #if defined(BASTD_CLI) diff --git a/bastd/rand.c b/bastd/rand.c index 612f207..06aceee 100644 --- a/bastd/rand.c +++ b/bastd/rand.c @@ -24,10 +24,10 @@ rand_generateSeed(U64 x) FUNCTION U64 rand_next(void) { - U64 rdtscp_val = os_rdtsc(); + U64 wallclock = os_wallclock(); for (int i = 0; i < COUNT_OF(rand_seed); i++) { if (rand_seed[i] == 0) { - rand_seed[i] = rand_generateSeed(rdtscp_val); + rand_seed[i] = rand_generateSeed(wallclock); } } diff --git a/bastd/slice.c b/bastd/slice.c index 4e346d8..9571d1a 100644 --- a/bastd/slice.c +++ b/bastd/slice.c @@ -1,10 +1,25 @@ -// GENERIC FILE, REDEFINED ON EVERY INCLUDE +// Shared by all generic types +#ifndef BASTD_SLICE_C +#defien BASTD_SLICE_C + +typedef enum slice_CompareResult slice_CompareResult; +enum slice_CompareResult { + slice_CompareResult_first_elem_less = -1, + slice_CompareResult_equal = 0, + slice_CompareResult_first_elem_greater = 1, +}; + +#endif//BASTD_SLICE_C + +// GENERIC SECTION, REDEFINED ON EVERY INCLUDE #ifndef sl_TYPE #error "No sl_TYPE given" #endif #define sl_NAME CONCAT(sl_, sl_TYPE) +#include "rand.c" + typedef struct sl_NAME sl_NAME; struct sl_NAME { sl_TYPE *elems; @@ -45,5 +60,39 @@ CONCAT(sl_NAME, _pop) (sl_NAME *slice) return *(slice->elems + --slice->len); } +FUNCTION sl_TYPE* +CONCAT(sl_NAME, _get) (sl_NAME slice, U64 idx) +{ + if (idx >= slice.len) { + // TODO not sure what the appropriate error handling is here + return NIL; + } + return slice.elems + idx; +} + +typedef slice_CompareResult (* CONCAT(sl_NAME, _CompareProc))(sl_TYPE, sl_TYPE); + +FUNCTION void +CONCAT(sl_NAME, _sort) (sl_NAME *slice, CONCAT(sl_NAME, _CompareProc) compare_proc) +{ + // QuickSort + if (slice->len < 2) { + return; + } + + U64 pivot_idx = rand_next() % slice->len; + sl_NAME + + for (int i = 0; i < slice->len; i++) { + sl_TYPE val = slice->elems[i]; + slice_CompareResult cmp = compare_proc(val, slice->elems[pivot_idx]); + if (cmp == slice_CompareResult_first_elem_less) { + + } else { + + } + } +} + #undef sl_NAME #undef sl_TYPE \ No newline at end of file diff --git a/bastd/string.c b/bastd/string.c index 3eee39d..f308cde 100644 --- a/bastd/string.c +++ b/bastd/string.c @@ -6,12 +6,11 @@ struct S8 { U64 len; U8 *raw; }; +#define S8(s) (S8){.len = LENGTH_OF(s), .raw = (U8 *)s} #define sl_TYPE S8 #include "slice.c" -#define S8(s) (S8){.len = LENGTH_OF(s), .raw = (U8 *)s} - FUNCTION S8 S8_alloc(U64 len, m_Allocator *perm) { @@ -107,6 +106,12 @@ S8_equal(S8 a, S8 b) return m_memoryDifference(a.raw, b.raw, a.len) == 0; } +FUNCTION B8 +S8_empty(S8 s) +{ + return S8_equal(s, (S8){.len = 0, .raw = NIL}); +} + FUNCTION S8 S8_view(S8 s, U64 start, U64 end) { diff --git a/build.bat b/build.bat index a695c9d..b01ed88 100644 --- a/build.bat +++ b/build.bat @@ -13,6 +13,6 @@ REM cl ..\bastd\examples\buffer.c %debugflags% REM cl ..\bastd\examples\job_random.c %debugflags% REM This builds your application with debug symbols. -cl ..\main.c %debugflags% +REM cl ..\main.c %debugflags% popd \ No newline at end of file