file system rewrite + more

This commit is contained in:
Abdulmujeeb Raji 2025-02-18 09:36:53 +00:00
parent 19c45cca31
commit 1b1af5ff85
Signed by: midnadimple
GPG key ID: EB02C582F8C3962B
8 changed files with 192 additions and 120 deletions

View file

@ -11,68 +11,34 @@ struct Buffer {
#define BUFFER(raw, cap) ((Buffer){raw, cap, 0, FALSE}) #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 // Utility
FUNCTION S8 FUNCTION S8
Buffer_buildS8(Buffer *b, m_Allocator *perm) Buffer_buildS8(Buffer *b, m_Allocator *perm)
{ {
S8 res = S8_alloc(b->len, perm); S8 res = S8_alloc(b->len, perm);
BufferOutput out = {0}; b->error |= res.len < b->len;
out.type = BufferOutputType_string; m_memoryCopy(res.raw, b->raw, res.len);
out.data.str = res;
Buffer_flush(b, out); b->len = 0;
return res; return res;
} }
FUNCTION void FUNCTION void
Buffer_standardOutput(Buffer *b) Buffer_standardOutput(Buffer *b)
{ {
BufferOutput output = {0}; os_File stdout = os_getStdout();
output.type = BufferOutputType_file; b->error |= !os_writeFile(stdout, b->raw, b->len);
output.data.fd = 1; b->len = 0;
Buffer_flush(b, output);
} }
FUNCTION void FUNCTION void
Buffer_fileOutput(Buffer *b, S8 filename) Buffer_fileOutput(Buffer *b, S8 filename)
{ {
BufferOutput output = {0}; os_File file = os_openFile(filename.raw);
output.type = BufferOutputType_file; b->error |= !os_writeFile(file, b->raw, b->len);
output.data.fd = os_openFile(filename.raw, TRUE); os_closeFile(file);
Buffer_flush(b, output); b->len = 0;
os_closeFile(output.data.fd);
} }
FUNCTION void FUNCTION void
@ -115,6 +81,26 @@ Buffer_appendI64(Buffer *b, I64 x)
Buffer_append(b, beg, end-beg); 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 FUNCTION void
Buffer_appendPtr(Buffer *b, void *p) Buffer_appendPtr(Buffer *b, void *p)
{ {
@ -155,25 +141,26 @@ Buffer_appendF64(Buffer *b, F64 x, U64 num_decimals)
FUNCTION void FUNCTION void
Buffer_appendFile(Buffer *b, S8 filename, m_Allocator *perm) Buffer_appendFile(Buffer *b, S8 filename, m_Allocator *perm)
{ {
int fd = os_openFile(filename.raw, FALSE); os_File file = os_openFile(filename.raw);
U32 file_size = (U32)os_getFileSize(fd);
U8 *data = m_MAKE(U8, file_size, perm); U8 *data = m_MAKE(U8, file.size, perm);
b->error |= os_read(fd, data, (int)file_size, &file_size); b->error |= os_readFile(file, data, (int)file.size, &file.size);
Buffer_append(b, data, file_size); Buffer_append(b, data, file.size);
os_closeFile(fd); os_closeFile(file);
m_RELEASE(data, file_size, perm); if (!file.already_exists) {
os_deleteFile(file);
}
m_RELEASE(data, file.size, perm);
} }
FUNCTION void FUNCTION void
Buffer_appendStandardInput(Buffer *b, U64 max_read_size, m_Allocator *perm) Buffer_appendStandardInput(Buffer *b, U64 max_read_size, m_Allocator *perm)
{ {
int stdin_fd = 0; int len = 0;
U32 len = 0;
U8 *data = m_MAKE(U8, max_read_size, perm); 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); Buffer_append(b, data, len);
// NOTE maybe we should switch to sl_U8 so theres no max length for stdin // NOTE maybe we should switch to sl_U8 so theres no max length for stdin

View file

@ -8,7 +8,7 @@ os_entry(void)
m_Allocator perm = m_BUDDY_ALLOCATOR(buddy); m_Allocator perm = m_BUDDY_ALLOCATOR(buddy);
Buffer buf = BUFFER(os_alloc(KILO(2)), KILO(2)); 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); Buffer_appendI64(&buf, 10245);
S8 buf_built = Buffer_buildS8(&buf, &perm); S8 buf_built = Buffer_buildS8(&buf, &perm);

View file

@ -3,11 +3,19 @@
FUNCTION void os_abort(char *msg); FUNCTION void os_abort(char *msg);
FUNCTION void *os_alloc(U64 cap); 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); typedef struct os_File os_File;
FUNCTION U64 os_getFileSize(int fd); struct os_File; // Depends on the OS. Always tells you if the file existed before being opened
FUNCTION int os_openFile(U8 *filename, B8 always_create);
FUNCTION B8 os_closeFile(int fd); 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; typedef struct os_Thread os_Thread;
struct os_Thread; // Depends on the OS struct os_Thread; // Depends on the OS
@ -36,7 +44,8 @@ enum {
}; };
CALLBACK_EXPORT os_ErrorCode os_entry(void); 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) #if defined(OS_WINDOWS)

View file

@ -25,66 +25,83 @@ os_alloc(U64 cap)
return VirtualAlloc(NIL, cap, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); return VirtualAlloc(NIL, cap, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
} }
FUNCTION B8 struct os_File {
os_write(int fd, U8 *buf, int len) U8 *name;
HANDLE raw;
U64 size;
B8 already_exists;
};
FUNCTION os_File
os_openFile(U8 *filename)
{ {
HANDLE h = GetStdHandle(-10 - fd); os_File res = {0};
if (h == INVALID_HANDLE_VALUE) {
h = (HANDLE)_get_osfhandle(fd); 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) { res.raw = CreateFileA(res.name, GENERIC_READ | GENERIC_WRITE,
return FALSE; FILE_SHARE_READ, 0, open_style, FILE_ATTRIBUTE_NORMAL, 0);
}
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);
}
LARGE_INTEGER file_size; LARGE_INTEGER file_size;
GetFileSizeEx(h, &file_size); GetFileSizeEx(res.raw, &file_size);
return (U64)file_size.QuadPart; res.size = (U64)file_size.QuadPart;
return res;
} }
FUNCTION int FUNCTION os_File
os_openFile(U8 *filename, B8 always_create) os_getStdout(void)
{ {
U32 open_style = OPEN_EXISTING; os_File res = {0};
if (always_create) { res.already_exists = TRUE;
open_style = CREATE_ALWAYS; res.name = "stdout";
} res.size = KILO(1);
HANDLE file = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, res.raw = GetStdHandle((U32)(-11));
FILE_SHARE_READ, 0, open_style, 0, 0); return res;
return _open_osfhandle((intptr_t)file, 0); }
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 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 ** FUNCTION char **
@ -181,9 +198,14 @@ os_Semaphore_wait(os_Semaphore semaphore)
} }
FUNCTION U64 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) #if defined(BASTD_CLI)

View file

@ -24,10 +24,10 @@ rand_generateSeed(U64 x)
FUNCTION U64 FUNCTION U64
rand_next(void) rand_next(void)
{ {
U64 rdtscp_val = os_rdtsc(); U64 wallclock = os_wallclock();
for (int i = 0; i < COUNT_OF(rand_seed); i++) { for (int i = 0; i < COUNT_OF(rand_seed); i++) {
if (rand_seed[i] == 0) { if (rand_seed[i] == 0) {
rand_seed[i] = rand_generateSeed(rdtscp_val); rand_seed[i] = rand_generateSeed(wallclock);
} }
} }

View file

@ -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 #ifndef sl_TYPE
#error "No sl_TYPE given" #error "No sl_TYPE given"
#endif #endif
#define sl_NAME CONCAT(sl_, sl_TYPE) #define sl_NAME CONCAT(sl_, sl_TYPE)
#include "rand.c"
typedef struct sl_NAME sl_NAME; typedef struct sl_NAME sl_NAME;
struct sl_NAME { struct sl_NAME {
sl_TYPE *elems; sl_TYPE *elems;
@ -45,5 +60,39 @@ CONCAT(sl_NAME, _pop) (sl_NAME *slice)
return *(slice->elems + --slice->len); 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_NAME
#undef sl_TYPE #undef sl_TYPE

View file

@ -6,12 +6,11 @@ struct S8 {
U64 len; U64 len;
U8 *raw; U8 *raw;
}; };
#define S8(s) (S8){.len = LENGTH_OF(s), .raw = (U8 *)s}
#define sl_TYPE S8 #define sl_TYPE S8
#include "slice.c" #include "slice.c"
#define S8(s) (S8){.len = LENGTH_OF(s), .raw = (U8 *)s}
FUNCTION S8 FUNCTION S8
S8_alloc(U64 len, m_Allocator *perm) 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; 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 FUNCTION S8
S8_view(S8 s, U64 start, U64 end) S8_view(S8 s, U64 start, U64 end)
{ {

View file

@ -13,6 +13,6 @@ REM cl ..\bastd\examples\buffer.c %debugflags%
REM cl ..\bastd\examples\job_random.c %debugflags% REM cl ..\bastd\examples\job_random.c %debugflags%
REM This builds your application with debug symbols. REM This builds your application with debug symbols.
cl ..\main.c %debugflags% REM cl ..\main.c %debugflags%
popd popd