file system rewrite + more
This commit is contained in:
parent
19c45cca31
commit
1b1af5ff85
8 changed files with 192 additions and 120 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
21
bastd/os.c
21
bastd/os.c
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
Loading…
Add table
Reference in a new issue