// ================================================================================
// Strings & Arrays
-typedef struct CB_StringView CB_StringView;
-struct CB_StringView {
+typedef struct CB_String8 CB_String8;
+struct CB_String8 {
u8 *data;
int64_t length;
};
+typedef struct CB_String16 CB_String16;
+struct CB_String16 {
+ u16 *data;
+ int64_t length;
+};
+
+typedef struct CB_UTFCodepoint CB_UTFCodepoint;
+struct CB_UTFCodepoint {
+ u32 codepoint;
+ u8 size;
+};
+
typedef struct CB_StringBuilder_Node CB_StringBuilder_Node;
struct CB_StringBuilder_Node {
struct CB_StringBuilder_Node *prev;
struct CB_StringBuilder_Node *next;
- CB_StringView value;
+ CB_String8 value;
};
typedef struct CB_StringBuilder CB_StringBuilder;
CB_LogLevel_COUNT,
};
-#define cb_strlit(cstr) (CB_StringView) { .data = (cstr), .length = cb_arrlength(cstr) - 1 }
+#define cb_strlit(cstr) (CB_String8) { .data = (u8*)(cstr), .length = cb_arrlength(cstr) - 1 }
#define cb_strinit(cstr) { .data = (cstr), .length = cb_arrlength(cstr) - 1 }
-#define cb_view_expand(view) (s32)(view).length, (view).data
+#define cb_str8_expand(str8) (s32)(str8).length, (str8).data
#define cb_array(CArrayLitteral) (CB_Array) { .data = (CArrayLitteral), .length = cb_arrlength((CArrayLitteral)) }
static void cb_print(CB_LogLevel level, const char *fmt, ...);
static char* cb_format(const char *format, ...);
-static char* cb_cstr_from_view(CB_StringView view);
+static char* cb_cstr_from_str8(CB_String8 str8);
+static wchar_t* cb_wstr_from_str8(CB_String8 str8);
-static CB_StringView cb_view_from_cstr(const char *cstr);
-static b8 cb_view_starts_with(const char *string, CB_StringView sv);
-static void cb_view_trim(CB_StringView *sv);
-static CB_StringBuilder cb_view_split(CB_StringView sv, char delim);
+static CB_String16 cb_str16_from_str8(CB_String8 in);
+static CB_String8 cb_str8_from_str16(CB_String16 in);
-static void cb_sb_append(CB_StringBuilder *sb, CB_StringView sv);
+static CB_String8 cb_str8_from_cstr(const char *cstr);
+static CB_String8 cb_str8_from_cstr_copy(const char *cstr);
+static b8 cb_str8_starts_with(const char *string, CB_String8 sv);
+static void cb_str8_trim(CB_String8 *sv);
+static CB_StringBuilder cb_str8_split(CB_String8 sv, char delim);
+
+static void cb_sb_append(CB_StringBuilder *sb, CB_String8 sv);
static void cb_sb_concat(CB_StringBuilder *sb, const CB_StringBuilder *other);
-static CB_StringView cb_sb_join_with_ch(CB_StringBuilder sb, char ch);
+static CB_String8 cb_sb_join_with_ch(CB_StringBuilder sb, char ch);
-static b8 cb_cli_contains(int32_t argc, char **argv, const char *target);
+static s32 cb_cli_find(int32_t argc, char **argv, const char *target);
internal char* cb_format_va(const char *format, va_list args);
#endif
static CB_FileProperties cb_file_properties(CB_FileHandle hfile);
-static CB_StringView cb_file_read(CB_FileHandle hfile, s64 size, s64 offset);
+static CB_String8 cb_file_read(CB_FileHandle hfile, s64 size, s64 offset);
static u8* cb_file_memory_map(CB_FileHandle hfile, s64 size, s64 offset);
-static void cb_file_write_at_pointer(CB_FileHandle hfile, CB_StringView content);
-static void cb_file_write_at_offset(CB_FileHandle hfile, CB_StringView content, s64 offset);
+static void cb_file_write_at_pointer(CB_FileHandle hfile, CB_String8 content);
+static void cb_file_write_at_offset(CB_FileHandle hfile, CB_String8 content, s64 offset);
static b8 cb_file_pointer_set_position_absolute(CB_FileHandle hfile, s64 position);
static b8 cb_file_pointer_set_position_relative(CB_FileHandle hfile, s64 offset);
static b8 cb_file_flush(CB_FileHandle hfile);
static void cb_file_memory_unmap(u8 *file_map, s64 size);
static void cb_file_close(CB_FileHandle hfile);
-static CB_FileHandle cb_filesystem_open(CB_StringView path, CB_AccessFlag flags);
-static CB_FileHandle cb_filesystem_open_temp(CB_StringView *path);
-static CB_FileProperties cb_filesystem_properties(CB_StringView path);
-static void cb_filesystem_delete(CB_StringView path);
-static b8 cb_filesystem_exists(CB_StringView path);
-static b8 cb_filesystem_rename(CB_StringView old, CB_StringView new);
-static b8 cb_filesystem_copy(CB_StringView path_source, CB_StringView path_dest, s64 bytes_to_copy, s64 offset_source, s64 offset_dest);
-static b8 cb_filesystem_link_create_symbolic(CB_StringView realpath, CB_StringView linkpath);
-static b8 cb_filesystem_link_create_physical(CB_StringView realpath, CB_StringView linkpath);
-static CB_StringView cb_filesystem_link_read(CB_StringView linkpath);
-static b8 cb_filesystem_directory_create(CB_StringView path);
-static b8 cb_filesystem_directory_copy(CB_StringView path, CB_StringView new);
-static b8 cb_filesystem_directory_delete(CB_StringView path, b8 recursive);
-static CB_StringView cb_filesystem_filename_from_path(CB_StringView path);
-static CB_StringView cb_filesystem_path_canonicalize(CB_StringView path);
+static CB_FileHandle cb_filesystem_open(CB_String8 path, CB_AccessFlag flags);
+static CB_FileHandle cb_filesystem_open_temp(CB_String8 *path);
+static CB_FileProperties cb_filesystem_properties(CB_String8 path);
+static void cb_filesystem_delete(CB_String8 path);
+static b8 cb_filesystem_exists(CB_String8 path);
+static b8 cb_filesystem_rename(CB_String8 old, CB_String8 new);
+static b8 cb_filesystem_copy(CB_String8 path_source, CB_String8 path_dest, s64 bytes_to_copy, s64 offset_source, s64 offset_dest);
+static b8 cb_filesystem_link_create_symbolic(CB_String8 realpath, CB_String8 linkpath);
+static b8 cb_filesystem_link_create_physical(CB_String8 realpath, CB_String8 linkpath);
+static CB_String8 cb_filesystem_link_read(CB_String8 linkpath);
+static b8 cb_filesystem_directory_create(CB_String8 path);
+static b8 cb_filesystem_directory_copy(CB_String8 path, CB_String8 new);
+static b8 cb_filesystem_directory_delete(CB_String8 path, b8 recursive);
+static CB_String8 cb_filesystem_filename_from_path(CB_String8 path);
+static CB_String8 cb_filesystem_path_canonicalize(CB_String8 path);
static void cb_filesystem_iter_begin(CB_FileIterator *it, const char *rootpath);
static b8 cb_filesystem_iter_next(CB_FileIterator *it, CB_FileInfo *output);
# define MAX_ENVVAR 32767
#endif
-static char* cb_getenv(const char *varname);
-static b8 cb_setenv(const char *varname, const char *value);
-
-// ==============================================================================
-// Implementation
+static CB_String8 cb_getenv(CB_String8 varname);
+static b8 cb_setenv(CB_String8 varname, CB_String8 value);
+static b8 cb_unsetenv(CB_String8 varname);
+#ifndef CBUILD_NOIMPL
// ================================================================================
// Static arena impl
static inline u64 cb_align_forward(u64 x, u64 align)
return res;
}
-static char* cb_cstr_from_view(CB_StringView view)
+static char* cb_cstr_from_str8(CB_String8 str8)
+{
+ assert(str8.length > 0);
+ assert(str8.data != NULL);
+ char *res = cb_arena_push_many(char, str8.length + 1);
+ cb_memcopy(res, str8.data, str8.length);
+ res[str8.length] = '\0';
+ return res;
+}
+
+static wchar_t* cb_wstr_from_str8(CB_String8 str8)
{
- assert(view.length > 0);
- assert(view.data != NULL);
- char *res = cb_arena_push_many(char, view.length + 1);
- cb_memcopy(res, view.data, view.length);
- res[view.length] = '\0';
+ CB_String16 str16 = cb_str16_from_str8(str8);
+ assert(str16.length > 0);
+ assert(str16.data != NULL);
+ wchar_t *res = cb_arena_push_many(wchar_t, str16.length + 1);
+ cb_memcopy(res, str16.data, str16.length * (s64)sizeof(u16));
+ res[str16.length] = (u16)0;
+ return res;
+}
+
+
+static CB_String8 cb_str8_from_str16(CB_String16 in)
+{
+ assert(in.length > 0);
+ assert(in.data != NULL);
+ CB_String8 res = {0};
+
+ // Worst case: every UTF-16 code unit becomes 3 UTF-8 bytes
+ s64 approx_size = in.length * 3;
+ u8 *bytes = cb_arena_push_many(u8, approx_size);
+ if (!bytes) { return res; }
+
+ u8 *dst = bytes;
+
+ for (u16 *src = in.data, *end = src + in.length; src < end; ) {
+ u32 codepoint;
+
+ // Handle surrogate pairs
+ if (*src >= 0xD800 && *src <= 0xDBFF && src + 1 < end &&
+ src[1] >= 0xDC00 && src[1] <= 0xDFFF) {
+ codepoint = (((src[0] - 0xD800U) << 10U) |
+ (src[1] - 0xDC00U)) + 0x10000U;
+ src += 2;
+ } else {
+ codepoint = *src++;
+ }
+
+ // Encode UTF-8
+ if (codepoint < 0x80) {
+ *dst++ = (u8)codepoint;
+ } else if (codepoint < 0x800) {
+ *dst++ = (u8)(0xC0 | (codepoint >> 6));
+ *dst++ = (u8)(0x80 | (codepoint & 0x3F));
+ } else if (codepoint < 0x10000) {
+ *dst++ = (u8)(0xE0 | (codepoint >> 12));
+ *dst++ = (u8)(0x80 | ((codepoint >> 6) & 0x3F));
+ *dst++ = (u8)(0x80 | (codepoint & 0x3F));
+ } else {
+ *dst++ = (u8)(0xF0 | (codepoint >> 18));
+ *dst++ = (u8)(0x80 | ((codepoint >> 12) & 0x3F));
+ *dst++ = (u8)(0x80 | ((codepoint >> 6) & 0x3F));
+ *dst++ = (u8)(0x80 | (codepoint & 0x3F));
+ }
+ }
+
+ s64 res_size = dst - bytes;
+ cb_arena_pop(approx_size - res_size);
+
+ res.data = bytes;
+ res.length = res_size;
return res;
}
-static CB_StringView cb_view_from_cstr(const char *cstr)
+static CB_String16 cb_str16_from_str8(CB_String8 in)
{
- CB_StringView res = {0};
+ assert(in.length > 0);
+ assert(in.data != NULL);
+
+ CB_String16 res = {0};
+ s64 res_size = 0, approx_size = in.length * 2;
+ u16 *words = cb_arena_push_many(u16, approx_size), *res_offset = words;
+ if (!words) { return res; }
+
+ CB_UTFCodepoint codepoint = {0};
+ for (const u8 *start = in.data, *end = in.data + in.length;
+ start < end;
+ start += codepoint.size) {
+ if ((*start & 0x80) == 0) {
+ codepoint.codepoint = *start;
+ codepoint.size = 1;
+ } else if ((*start & 0xE0) == 0xC0) {
+ codepoint.codepoint = start[1] & 0x3F;
+ codepoint.codepoint |= (u32)(start[0] & 0x1F) << 6;
+ codepoint.size = 2;
+ } else if ((*start & 0xF0) == 0xE0) {
+ codepoint.codepoint = start[2] & 0x3F;
+ codepoint.codepoint |= (u32)(start[1] & 0x3F) << 6;
+ codepoint.codepoint |= (u32)(start[0] & 0xf) << 12;
+ codepoint.size = 3;
+ } else if ((*start & 0xF8) == 0xF0) {
+ codepoint.codepoint = start[3] & 0x3F;
+ codepoint.codepoint |= (u32)(start[2] & 0x3F) << 6;
+ codepoint.codepoint |= (u32)(start[1] & 0x3F) << 12;
+ codepoint.codepoint |= (u32)(start[0] & 0x7) << 18;
+ codepoint.size = 4;
+ } else {
+ assert(false && "unreachable reached");
+ }
+
+ s64 utf16_codepoint_size;
+ if (codepoint.codepoint <= 0xD7FF || (codepoint.codepoint >= 0xE000 && codepoint.codepoint <= 0xFFFF)) {
+ res_offset[0] = (u16)codepoint.codepoint;
+ utf16_codepoint_size = 1;
+ } else if (codepoint.codepoint >= 0x10000 && codepoint.codepoint <= 0x10FFFF) {
+ res_offset[0] = (u16)(((codepoint.codepoint - 0x10000) >> 10) + 0xD800);
+ res_offset[1] = ((codepoint.codepoint - 0x10000) & 0x3FF) + 0xDC00;
+ utf16_codepoint_size = 2;
+ } else {
+ assert(false && "unreachable reached");
+ }
+
+ res_size += utf16_codepoint_size;
+ res_offset += utf16_codepoint_size;
+ }
+
+ assert(res_size >= 0);
+ cb_arena_pop(approx_size - res_size);
+ res.data = words;
+ res.length = res_size;
+ return res;
+}
+
+static CB_String8 cb_str8_from_cstr(const char *cstr)
+{
+ CB_String8 res = {0};
res.data = (u8*)cstr;
if (cstr != NULL) {
const char *start = cstr;
return res;
}
-static b8 cb_view_starts_with(const char *string, CB_StringView sv)
+static CB_String8 cb_str8_from_cstr_copy(const char *cstr)
+{
+ CB_String8 res = {0};
+ if (cstr == NULL || *cstr == '\0') { return res; }
+ const char *start = cstr;
+ for (; *cstr; ++cstr);
+ res.length = cstr - start;
+ res.data = cb_arena_push_many(u8, res.length);
+ cb_memcopy(res.data, start, res.length);
+ return res;
+}
+
+static b8 cb_str8_starts_with(const char *string, CB_String8 sv)
{
if (string == NULL || sv.length == 0 || sv.data == NULL) { return false; }
for (int32_t i = 0; i < sv.length; ++i) {
return true;
}
-static void cb_view_trim(CB_StringView *sv)
+static void cb_str8_trim(CB_String8 *sv)
{
cb_assert(sv != NULL);
if (sv->length <= 0) { return; }
sv->length -= 1) {}
}
-static CB_StringBuilder cb_view_split(CB_StringView sv, char delim)
+static CB_StringBuilder cb_str8_split(CB_String8 sv, char delim)
{
CB_StringBuilder res = {0};
if (sv.data == NULL || sv.length == 0) { return res; }
- ssize_t prev = 0;
- for (ssize_t i = 0; i < sv.length;) {
+ s64 prev = 0;
+ for (s64 i = 0; i < sv.length;) {
if (sv.data[i] == delim) {
if (prev != i) {
- cb_sb_append(&res, (CB_StringView) {
+ cb_sb_append(&res, (CB_String8) {
.data = sv.data + prev,
- .length = (int64_t)(i - prev),
+ .length = (s64)(i - prev),
});
}
do {
}
}
if (prev != sv.length) {
- cb_sb_append(&res, (CB_StringView) {
+ cb_sb_append(&res, (CB_String8) {
.data = sv.data + prev,
- .length = (int64_t)(sv.length - prev),
+ .length = (s64)(sv.length - prev),
});
}
cb_assert(res.node_count > 0);
return res;
}
-static void cb_sb_append(CB_StringBuilder *sb, CB_StringView sv)
+static void cb_sb_append(CB_StringBuilder *sb, CB_String8 sv)
{
cb_assert(sb != NULL);
if (sv.length == 0 || sv.data == NULL) { return; }
sb->last = other->last;
}
-static CB_StringView cb_sb_join_with_ch(CB_StringBuilder sb, char ch)
+static CB_String8 cb_sb_join_with_ch(CB_StringBuilder sb, char ch)
{
- CB_StringView sv = {0};
+ CB_String8 sv = {0};
sv.data = malloc((uint32_t)(sb.total_length + sb.node_count));
sv.length = sb.total_length + sb.node_count - 1;
int32_t offset = 0;
return sv;
}
-static b8 cb_cli_contains(int32_t argc, char **argv, const char *target)
+static s32 cb_cli_find(int32_t argc, char **argv, const char *target)
{
for (int32_t i = 0; i < argc; ++i) {
if (!strcmp(argv[i], target)) {
- return true;
+ return i;
}
}
- return false;
+ return -1;
}
internal char* cb_format_va(const char *format, va_list args)
assert(properties.size >= 0);
if (file_info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL || file_info.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
- properties.type = OS_FileType_Regular;
+ properties.type = CB_FileType_Regular;
} else if (file_info.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) {
- properties.type = OS_FileType_Device_Block;
+ properties.type = CB_FileType_Device_Disk;
} else if (file_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- properties.type = OS_FileType_Link;
+ properties.type = CB_FileType_Link;
} else if (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- properties.type = OS_FileType_Directory;
+ properties.type = CB_FileType_Directory;
} else {
unreachable();
}
assert((((u64)file_info.ftLastAccessTime.dwHighDateTime << 32) | file_info.ftLastAccessTime.dwLowDateTime) <= 0x8000000000000000);
assert((((u64)file_info.ftLastWriteTime.dwHighDateTime << 32) | file_info.ftLastWriteTime.dwLowDateTime) <= 0x8000000000000000);
SYSTEMTIME last_access_time = {0}, last_write_time = {0};
- res = FileTimeToSystemTime(&file_info.ftLastAccessTime, &last_access_time);
+ BOOL res = FileTimeToSystemTime(&file_info.ftLastAccessTime, &last_access_time);
assert(res == TRUE);
res = FileTimeToSystemTime(&file_info.ftLastWriteTime, &last_write_time);
assert(res == TRUE);
#endif
}
-static CB_StringView cb_file_read(CB_FileHandle hfile, s64 size, s64 offset)
+static CB_String8 cb_file_read(CB_FileHandle hfile, s64 size, s64 offset)
{
assert(hfile != CB_FILEHANDLE_INVALID);
assert(size > 0);
assert(offset >= 0);
assert(offset < size);
- CB_StringView result = {0};
+ CB_String8 result = {0};
u8 *buffer = cb_arena_push_many(u8, size);
#if OS_WINDOWS
- // TODO(lb): win32
+ LONG pointer_position_high = 0;
+ DWORD pointer_position_low = SetFilePointer(hfile, 0, &pointer_position_high, FILE_CURRENT);
+
+ DWORD bytes_read = 0;
+ SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
+ BOOL res_read = ReadFile(hfile, buffer, (DWORD)size, &bytes_read, NULL);
+ SetFilePointer(hfile, (LONG)pointer_position_low, &pointer_position_high, FILE_BEGIN);
+ assert(bytes_read > 0);
+ assert(bytes_read <= size);
+ result.data = buffer;
+ result.length = bytes_read;
+ return result;
#else
s64 bytes_read = pread(hfile, buffer, (u64)size, offset);
assert(bytes_read != -1);
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
u8 *res = mmap(NULL, (u64)size, O_RDWR, MAP_SHARED, hfile, offset);
assert(res != MAP_FAILED);
#endif
}
-static void cb_file_write_at_pointer(CB_FileHandle hfile, CB_StringView content)
+static void cb_file_write_at_pointer(CB_FileHandle hfile, CB_String8 content)
{
assert(hfile != CB_FILEHANDLE_INVALID);
assert(content.length > 0);
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
CB_Scratch scratch = cb_scratch_begin();
- s64 bytes_wrote = write(hfile, cb_cstr_from_view(content), (u64)content.length);
+ s64 bytes_wrote = write(hfile, cb_cstr_from_str8(content), (u64)content.length);
cb_scratch_end(scratch);
assert(bytes_wrote == content.length);
#endif
}
-static void cb_file_write_at_offset(CB_FileHandle hfile, CB_StringView content, s64 offset)
+static void cb_file_write_at_offset(CB_FileHandle hfile, CB_String8 content, s64 offset)
{
assert(hfile != CB_FILEHANDLE_INVALID);
assert(content.length > 0);
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
CB_Scratch scratch = cb_scratch_begin();
- s64 bytes_wrote = pwrite(hfile, cb_cstr_from_view(content), (u64)content.length, offset);
+ s64 bytes_wrote = pwrite(hfile, cb_cstr_from_str8(content), (u64)content.length, offset);
cb_scratch_end(scratch);
assert(bytes_wrote <= content.length);
#endif
assert(position > 0);
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
off_t res = lseek(hfile, position, SEEK_SET);
return res == 0;
assert(hfile != CB_FILEHANDLE_INVALID);
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
off_t res = lseek(hfile, offset, SEEK_CUR);
return res == 0;
assert(hfile != CB_FILEHANDLE_INVALID);
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
s32 res = fsync(hfile);
return res == 0;
assert(new_size >= 0);
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
s32 res = ftruncate(hfile, new_size);
return res == 0;
assert(size > 0);
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
s32 res = munmap(file_map, (u64)size);
assert(res == 0);
{
assert(hfile != CB_FILEHANDLE_INVALID);
#if OS_WINDOWS
- // TODO(lb): win32
+ BOOL res = CloseHandle(hfile);
+ assert(res == TRUE);
#else
s32 res = close(hfile);
assert(res == 0);
#endif
}
-static CB_FileHandle cb_filesystem_open(CB_StringView path, CB_AccessFlag flags)
+static CB_FileHandle cb_filesystem_open(CB_String8 path, CB_AccessFlag flags)
{
assert(path.length > 0);
assert(path.data != NULL);
#if OS_WINDOWS
- // TODO(lb): win32
+ DWORD access_flags = 0;
+ DWORD share_mode = FILE_SHARE_DELETE;
+ if (flags & CB_AccessFlag_Read) {
+ access_flags |= GENERIC_READ;
+ share_mode |= FILE_SHARE_READ;
+ }
+ if (flags & CB_AccessFlag_Write) {
+ access_flags |= GENERIC_WRITE;
+ share_mode |= FILE_SHARE_WRITE;
+ }
+ if (flags & CB_AccessFlag_Append) {
+ access_flags |= FILE_APPEND_DATA;
+ }
+
+ CB_Scratch scratch = cb_scratch_begin();
+ CB_FileHandle res = CreateFileW(cb_wstr_from_str8(path), access_flags, share_mode, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ cb_scratch_end(scratch);
+ return res;
#else
s32 mode = O_CREAT;
if ((flags & CB_AccessFlag_Read) && ((flags & CB_AccessFlag_Write) || (flags & CB_AccessFlag_Append))) {
}
if (flags & CB_AccessFlag_Append) { mode |= O_APPEND; }
CB_Scratch scratch = cb_scratch_begin();
- int32_t res = open(cb_cstr_from_view(path), mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ int32_t res = open(cb_cstr_from_str8(path), mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
cb_scratch_end(scratch);
if (res == -1) { return CB_FILEHANDLE_INVALID; }
return (CB_FileHandle)res;
#endif
}
-static CB_FileHandle cb_filesystem_open_temp(CB_StringView *path)
+static CB_FileHandle cb_filesystem_open_temp(CB_String8 *path)
{
assert(path != NULL);
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
path->length = cb_arrlength("/tmp/XXXXXX");
char *bytes = cb_arena_push_many(char, path->length);
#endif
}
-static CB_FileProperties cb_filesystem_properties(CB_StringView path)
+static CB_FileProperties cb_filesystem_properties(CB_String8 path)
{
assert(path.length > 0);
assert(path.data != NULL);
#if OS_WINDOWS
- // TODO(lb): get file properties from path on win32
- CB_FileProperties res = {0};
- return res;
+ CB_FileProperties properties = {0};
+
+ BY_HANDLE_FILE_INFORMATION file_info = {0};
+ CB_FileHandle fd = cb_filesystem_open(path, CB_AccessFlag_Read);
+ BOOL res = GetFileInformationByHandle(fd, &file_info);
+ cb_file_close(fd);
+ assert(res == TRUE);
+
+ properties.size = (((s64)file_info.nFileSizeHigh << 32) | file_info.nFileSizeLow);
+ assert(properties.size >= 0);
+
+ if (file_info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL ||
+ file_info.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
+ properties.type = CB_FileType_Regular;
+ } else if (file_info.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) {
+ properties.type = CB_FileType_Device_Disk;
+ } else if (file_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+ properties.type = CB_FileType_Link;
+ } else if (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ properties.type = CB_FileType_Directory;
+ } else {
+ assert(false && "unreachable reached");
+ }
+
+ assert((((u64)file_info.ftLastAccessTime.dwHighDateTime << 32) | file_info.ftLastAccessTime.dwLowDateTime) <= 0x8000000000000000);
+ assert((((u64)file_info.ftLastWriteTime.dwHighDateTime << 32) | file_info.ftLastWriteTime.dwLowDateTime) <= 0x8000000000000000);
+ SYSTEMTIME last_access_time = {0}, last_write_time = {0};
+ res = FileTimeToSystemTime(&file_info.ftLastAccessTime, &last_access_time);
+ assert(res == TRUE);
+ res = FileTimeToSystemTime(&file_info.ftLastWriteTime, &last_write_time);
+ assert(res == TRUE);
+
+ properties.time_last_access = time64_from_systemtime(&last_access_time);
+ properties.time_last_status_change = time64_from_systemtime(&last_write_time);
+ properties.time_last_modification = properties.time_last_status_change;
+
+ return properties;
#else
struct stat file_stat = {0};
CB_Scratch scratch = cb_scratch_begin();
- s32 stat_res = stat(cb_cstr_from_view(path), &file_stat);
+ s32 stat_res = stat(cb_cstr_from_str8(path), &file_stat);
cb_scratch_end(scratch);
assert(stat_res == 0);
return cb_fileproperties_from_stat(&file_stat);
#endif
}
-static void cb_filesystem_delete(CB_StringView path)
+static void cb_filesystem_delete(CB_String8 path)
{
assert(path.length > 0);
assert(path.data != NULL);
#if OS_WINDOWS
// TODO(lb): implement file delete on win32
+ assert(false);
#else
CB_Scratch scratch = cb_scratch_begin();
- unlink(cb_cstr_from_view(path));
+ unlink(cb_cstr_from_str8(path));
cb_scratch_end(scratch);
#endif
}
-static b8 cb_filesystem_exists(CB_StringView path)
+static b8 cb_filesystem_exists(CB_String8 path)
{
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
# define F_OK 0
# define access _access
#endif
CB_Scratch scratch = cb_scratch_begin();
- b8 res = (access(cb_cstr_from_view(path), F_OK) == 0);
+ b8 res = (access(cb_cstr_from_str8(path), F_OK) == 0);
cb_scratch_end(scratch);
return res;
}
-static b8 cb_filesystem_rename(CB_StringView old, CB_StringView new)
+static b8 cb_filesystem_rename(CB_String8 old, CB_String8 new)
{
#if OS_WINDOWS
- // TODO(lb): implement file rename on win32
+ CB_Scratch scratch = cb_scratch_begin();
+ BOOL res = MoveFileExW(cb_wstr_from_str8(old), cb_wstr_from_str8(new), MOVEFILE_REPLACE_EXISTING);
+ cb_scratch_end(scratch);
+ return res;
#else
CB_Scratch scratch = cb_scratch_begin();
- char *old_cstr = cb_cstr_from_view(old);
- char *new_cstr = cb_cstr_from_view(new);
+ char *old_cstr = cb_cstr_from_str8(old);
+ char *new_cstr = cb_cstr_from_str8(new);
b8 res = (rename(old_cstr, new_cstr) == 0);
cb_scratch_end(scratch);
return res;
#endif
}
-static b8 cb_filesystem_copy(CB_StringView path_source, CB_StringView path_dest, s64 bytes_to_copy, s64 offset_source, s64 offset_dest)
+static b8 cb_filesystem_copy(CB_String8 path_source, CB_String8 path_dest, s64 bytes_to_copy, s64 offset_source, s64 offset_dest)
{
assert(bytes_to_copy > 0);
assert(offset_source >= 0);
if (!cb_filesystem_exists(path_dest)) { assert(offset_dest == 0); }
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
CB_Scratch scratch = cb_scratch_begin();
- s32 src = open(cb_cstr_from_view(path_source), O_RDONLY, 0);
- s32 dest = open(cb_cstr_from_view(path_dest), O_WRONLY | O_CREAT, 0644);
+ s32 src = open(cb_cstr_from_str8(path_source), O_RDONLY, 0);
+ s32 dest = open(cb_cstr_from_str8(path_dest), O_WRONLY | O_CREAT, 0644);
cb_scratch_end(scratch);
assert(src != -1);
assert(dest != -1);
#endif
}
-static b8 cb_filesystem_link_create_symbolic(CB_StringView realpath, CB_StringView linkpath)
+static b8 cb_filesystem_link_create_symbolic(CB_String8 realpath, CB_String8 linkpath)
{
assert(cb_filesystem_exists(realpath));
assert(!cb_filesystem_exists(linkpath));
#if OS_WINDOWS
// TODO(lb): create symlink on win32
+ assert(false);
return false;
#else
CB_Scratch scratch = cb_scratch_begin();
- s32 res = symlink(cb_cstr_from_view(realpath), cb_cstr_from_view(linkpath));
+ s32 res = symlink(cb_cstr_from_str8(cb_filesystem_path_canonicalize(realpath)), cb_cstr_from_str8(linkpath));
cb_scratch_end(scratch);
return res == 0;
#endif
}
-static b8 cb_filesystem_link_create_physical(CB_StringView realpath, CB_StringView linkpath)
+static b8 cb_filesystem_link_create_physical(CB_String8 realpath, CB_String8 linkpath)
{
assert(cb_filesystem_properties(realpath).type != CB_FileType_Directory);
assert(!cb_filesystem_exists(linkpath));
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
CB_Scratch scratch = cb_scratch_begin();
- s32 res = link(cb_cstr_from_view(realpath), cb_cstr_from_view(linkpath));
+ s32 res = link(cb_cstr_from_str8(realpath), cb_cstr_from_str8(linkpath));
cb_scratch_end(scratch);
return res == 0;
#endif
}
-static CB_StringView cb_filesystem_link_read(CB_StringView linkpath)
+static CB_String8 cb_filesystem_link_read(CB_String8 linkpath)
{
assert(cb_filesystem_exists(linkpath));
assert(cb_filesystem_properties(linkpath).type == CB_FileType_Link);
- CB_StringView res = {0};
+ CB_String8 res = {0};
#if OS_WINDOWS
// TODO(lb): win32
+ assert(false);
#else
s64 approx_length = 1024;
char *buffer = cb_arena_push_many(char, approx_length);
CB_Scratch scratch = cb_scratch_begin();
- s64 length = readlink(cb_cstr_from_view(linkpath), buffer, (u64)approx_length);
+ s64 length = readlink(cb_cstr_from_str8(linkpath), buffer, (u64)approx_length);
assert(length > 0);
cb_scratch_end(scratch);
cb_arena_pop(approx_length - length);
return res;
}
-static b8 cb_filesystem_directory_create(CB_StringView path)
+static b8 cb_filesystem_directory_create(CB_String8 path)
{
- assert(!cb_filesystem_exists(path));
+ assert(path.length > 0);
+ assert(path.data != NULL);
+ if (cb_filesystem_exists(path)) { return false; }
#if OS_WINDOWS
- // TODO(lb): win32
+ CB_Scratch scratch = cb_scratch_begin();
+ BOOL res = CreateDirectoryW(cb_wstr_from_str8(path), NULL);
+ cb_scratch_end(scratch);
+ return res;
#else
CB_Scratch scratch = cb_scratch_begin();
- s32 res = mkdir(cb_cstr_from_view(path), (S_IRWXU) | (S_IRWXG) | (S_IROTH | S_IXOTH));
+ s32 res = mkdir(cb_cstr_from_str8(path), (S_IRWXU) | (S_IRWXG) | (S_IROTH | S_IXOTH));
cb_scratch_end(scratch);
return res == 0;
#endif
}
-static b8 cb_filesystem_directory_copy(CB_StringView dirpath, CB_StringView new)
+static b8 cb_filesystem_directory_copy(CB_String8 dirpath, CB_String8 new)
{
assert(cb_filesystem_exists(dirpath));
assert(cb_filesystem_properties(dirpath).type == CB_FileType_Directory);
return false;
}
-static b8 cb_filesystem_directory_delete(CB_StringView path, b8 recursive)
+static b8 cb_filesystem_directory_delete(CB_String8 path, b8 recursive)
{
assert(cb_filesystem_exists(path));
assert(cb_filesystem_properties(path).type == CB_FileType_Directory);
- // TODO(lb): directory delete
+
+#if OS_WINDOWS
+ // TODO(lb): win32
+#else
+ if (!recursive) {
+ CB_Scratch scratch = cb_scratch_begin();
+ s32 res = rmdir(cb_cstr_from_str8(path));
+ cb_scratch_end(scratch);
+ return res == 0;
+ }
+
+ CB_Scratch scratch = cb_scratch_begin();
+ const char *dirpath = cb_cstr_from_str8(path);
+ DIR *dir = opendir(dirpath);
+ if (dir == NULL) {
+ cb_scratch_end(scratch);
+ return false;
+ }
+
+ struct dirent *entry = NULL;
+ while ((entry = readdir(dir)) != NULL) {
+ if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; }
+ CB_String8 child = cb_str8_from_cstr(cb_format("%.*s/%s", cb_str8_expand(path), entry->d_name));
+ CB_FileProperties props = cb_filesystem_properties(child);
+ if (props.type == CB_FileType_Directory) {
+ if (!cb_filesystem_directory_delete(child, true)) { goto fail; }
+ } else {
+ if (unlink(cb_cstr_from_str8(child)) != 0) { goto fail; }
+ }
+ }
+ closedir(dir);
+ b8 result = rmdir(dirpath) == 0;
+ cb_scratch_end(scratch);
+ return result;
+ fail:
+ closedir(dir);
+ cb_scratch_end(scratch);
return false;
+#endif
}
-static CB_StringView cb_filesystem_filename_from_path(CB_StringView path)
+static CB_String8 cb_filesystem_filename_from_path(CB_String8 path)
{
assert(cb_filesystem_exists(path));
#if OS_WINDOWS
- // TODO(lb): win32
+ // TODO(lb): win32
+ assert(false);
#else
- const char *fullname = basename(cb_cstr_from_view(path));
+ const char *fullname = basename(cb_cstr_from_str8(path));
assert(fullname != NULL);
- CB_StringView res = cb_view_from_cstr(fullname);
+ CB_String8 res = cb_str8_from_cstr(fullname);
return res;
#endif
}
-static CB_StringView cb_filesystem_path_canonicalize(CB_StringView path)
+static CB_String8 cb_filesystem_path_canonicalize(CB_String8 path)
{
assert(cb_filesystem_exists(path));
#if OS_WINDOWS
- // TODO(lb): win32
+ // TODO(lb): win32
+ assert(false);
#else
CB_Scratch scratch = cb_scratch_begin();
- char *cstr_fullpath = realpath(cb_cstr_from_view(path), NULL);
+ char *cstr_fullpath = realpath(cb_cstr_from_str8(path), NULL);
assert(cstr_fullpath != NULL);
cb_scratch_end(scratch);
- CB_StringView res = cb_view_from_cstr(cstr_fullpath);
+ CB_String8 res = cb_str8_from_cstr_copy(cstr_fullpath);
+ free(cstr_fullpath);
return res;
#endif
}
memset(&it->handle, 0, sizeof it->handle);
#if OS_WINDOWS
// TODO(lb): file iteration on win32
+ assert(false);
#else
it->handle.path = rootpath;
it->handle.dir = opendir(rootpath);
#if OS_WINDOWS
// TODO(lb): file iteration on win32
+ assert(false);
return false;
#else
struct dirent *entry = NULL;
{
#if OS_WINDOWS
// TODO(lb): file iteration on win32
+ assert(false);
#else
closedir(it->handle.dir);
#endif
assert(build_options.length >= 0);
if (build_options.length > 0) { assert(build_options.data != NULL); }
+ CB_String8 executable = cb_str8_from_cstr(argv[0]);
+ cb_str8_trim(&executable);
+ assert(executable.length > 0);
+ assert(executable.data != NULL);
+
b8 should_rebuild = false;
- CB_StringView executable = cb_view_from_cstr(argv[0]);
- cb_view_trim(&executable);
time64 last_edit_executable = cb_filesystem_properties(executable).time_last_modification;
- CB_StringView *str_sources = sources.data;
+ CB_String8 *str_sources = sources.data;
for (s64 i = 0; i < sources.length; ++i) {
time64 last_edit_source = cb_filesystem_properties(str_sources[i]).time_last_modification;
if (last_edit_executable < last_edit_source) {
if (!should_rebuild) { return; }
#if OS_WINDOWS
+ CB_String8 executable_old = cb_str8_from_cstr(cb_format("%.*s.old", cb_str8_expand(executable)));
{
CB_Scratch scratch = cb_scratch_begin();
- CB_StringView executable_old = cb_view_from_cstr(cb_format("%.*s.old", executable));
- if (!cb_file_rename(executable, executable_old)) {
- cb_print(CB_LogLevel_Info, "File rename failed: %.*s -> %.*s\n", cb_view_expand(executable), cb_view_expand(executable_old));
+ if (!cb_filesystem_rename(executable, executable_old)) {
+ cb_print(CB_LogLevel_Info, "File rename failed: %.*s -> %.*s\n", cb_str8_expand(executable), cb_str8_expand(executable_old));
exit(-1);
}
cb_scratch_end(scratch);
cb_cmd_push(&cmd, CC);
#if COMPILER_CL
cb_cmd_append(&cmd, "/std:c11", "/nologo");
- cb_cmd_push(&cmd, cb_format("/Fe:%.*s", cb_view_expand(executable)));
- cb_cmd_push(&cmd, cb_format("%.*s", cb_view_expand(str_sources[0])));
+ cb_cmd_push(&cmd, cb_format("/Fe:%.*s", cb_str8_expand(executable)));
+ cb_cmd_push(&cmd, cb_format("%.*s", cb_str8_expand(str_sources[0])));
#else
cb_cmd_push(&cmd, "-o");
- cb_cmd_push(&cmd, cb_format("%.*s", cb_view_expand(executable)));
- cb_cmd_push(&cmd, cb_format("%.*s", cb_view_expand(str_sources[0])));
+ cb_cmd_push(&cmd, cb_format("%.*s", cb_str8_expand(executable)));
+ cb_cmd_push(&cmd, cb_format("%.*s", cb_str8_expand(str_sources[0])));
#endif
- CB_StringView *str_build_options = build_options.data;
+ CB_String8 *str_build_options = build_options.data;
for (s64 i = 0; i < build_options.length; ++i) {
- cb_cmd_push(&cmd, cb_format("%.*s", cb_view_expand(str_build_options[i])));
+ cb_cmd_push(&cmd, cb_format("%.*s", cb_str8_expand(str_build_options[i])));
}
cb_cmd_print(&cmd);
CB_Process compilation_proc = cb_cmd_exec(&cmd);
if (compilation_proc.status_code != 0) {
#if OS_WINDOWS
- cb_file_rename(executable_old, executable);
+ cb_filesystem_rename(executable_old, executable);
#endif
exit(-1);
}
- cb_cmd_push(&cmd, cb_format("%.*s", cb_view_expand(executable)));
+ cb_cmd_push(&cmd, cb_format("%.*s", cb_str8_expand(executable)));
cb_cmd_append_dyn(&cmd, argv, (size_t)argc);
(void)cb_cmd_exec(&cmd);
exit(0);
// ==============================================================================
// Environment variables
-static char* cb_getenv(const char *varname)
+static CB_String8 cb_getenv(CB_String8 varname)
{
- cb_assert(varname != NULL);
+ assert(varname.length > 0);
+ assert(varname.data != NULL);
#if OS_WINDOWS
- char *res = cb_arena_push_many(char, MAX_ENVVAR);
- if (!GetEnvironmentVariableA(varname, res, MAX_ENVVAR)) {
- cb_arena_pop(sizeof(char) * MAX_ENVVAR);
- res = 0;
- }
- return res;
+ wchar_t *res = cb_arena_push_many(wchar_t, MAX_ENVVAR);
+ CB_Scratch scratch = cb_scratch_begin();
+ DWORD length = GetEnvironmentVariableW(cb_wstr_from_str8(varname), res, MAX_ENVVAR);
+ cb_scratch_end(scratch);
+ assert(length > 0);
+ return cb_str8_from_str16((CB_String16) {
+ .data = res,
+ .length = length,
+ });
#else
- return getenv(varname);
+ CB_Scratch scratch = cb_scratch_begin();
+ char *cstr = getenv(cb_cstr_from_str8(varname));
+ cb_scratch_end(scratch);
+ return cb_str8_from_cstr(cstr);
#endif
}
-static b8 cb_setenv(const char *varname, const char *value)
+static b8 cb_setenv(CB_String8 varname, CB_String8 value)
{
- cb_assert(varname != NULL);
- cb_assert(value != NULL);
+ cb_assert(varname.length > 0);
+ cb_assert(varname.data != NULL);
+ cb_assert(value.length > 0);
+ cb_assert(value.data != NULL);
#if OS_WINDOWS
- return SetEnvironmentVariableA(varname, value);
+ CB_Scratch scratch = cb_scratch_begin();
+ BOOL res = SetEnvironmentVariableW(cb_wstr_from_str8(varname), cb_wstr_from_str8(value));
+ cb_scratch_end(scratch);
+ return res;
#else
- return !setenv(varname, value, true);
+ CB_Scratch scratch = cb_scratch_begin();
+ s32 res = setenv(cb_cstr_from_str8(varname), cb_cstr_from_str8(value), true);
+ cb_scratch_end(scratch);
+ return res == 0;
#endif
}
+static b8 cb_unsetenv(CB_String8 varname)
+{
+ assert(varname.length > 0);
+ assert(varname.data != NULL);
+#if OS_WINDOWS
+ // TODO(lb): win32
+ assert(false);
+#else
+ CB_Scratch scratch = cb_scratch_begin();
+ s32 res = unsetenv(cb_cstr_from_str8(varname));
+ cb_scratch_end(scratch);
+ return res == 0;
#endif
+}
+
+#endif // CBUILD_NOIMPL
+#endif // Header guard
#endif
typedef struct CB_BibloElement {
- CB_StringView name;
- CB_StringView brief;
- CB_StringView description;
- CB_StringView ref_block;
+ CB_String8 name;
+ CB_String8 brief;
+ CB_String8 description;
+ CB_String8 ref_block;
CB_StringBuilder aliases;
} CB_BibloElement;
struct CB_BibloParser {
- CB_StringView prefix;
- CB_StringView content;
- ssize_t offset;
- CB_Handle hfile;
+ CB_String8 prefix;
+ CB_String8 content;
+ int64_t offset;
+ CB_FileHandle hfile;
};
static void cb_biblo_build_man(const char *rootpath, const char *output_path);
-internal void cb_biblo_generate_troff(const CB_BibloElement *element, CB_StringView path_dirdoc, const char *source_path);
-internal CB_BibloElement cb_biblo_parse(CB_Handle file, struct CB_BibloParser *parser);
+internal void cb_biblo_generate_troff(const CB_BibloElement *element, CB_String8 path_dirdoc, const char *source_path);
+internal CB_BibloElement cb_biblo_parse(CB_FileHandle file, struct CB_BibloParser *parser);
internal void cb_biblo_parser_advance(struct CB_BibloParser *parser, size_t by);
-internal char cb_biblo_parser_peek(struct CB_BibloParser *parser, ssize_t offset);
-internal void cb_biblo_parser_until_newline(struct CB_BibloParser *parser, CB_StringView *sv);
+internal char cb_biblo_parser_peek(struct CB_BibloParser *parser, int64_t offset);
+internal void cb_biblo_parser_until_newline(struct CB_BibloParser *parser, CB_String8 *sv);
internal void cb_biblo_find_prefix(struct CB_BibloParser *parser);
// ===============================================================
CB_BibloAnnotationID_ReferenceEnd,
};
-static CB_StringView cb_biblo_annotation[] = {
+static CB_String8 cb_biblo_annotation[] = {
[CB_BibloAnnotationID_Name] = cb_strinit("@name"),
[CB_BibloAnnotationID_Brief] = cb_strinit("@brief"),
[CB_BibloAnnotationID_Long] = cb_strinit("@long"),
static void cb_biblo_build_man(const char *rootpath, const char *output_path)
{
CB_FileIterator it = { .filter_allowed = CB_FileType_Regular | CB_FileType_Directory };
- cb_file_iter_begin(&it, rootpath);
+ cb_filesystem_iter_begin(&it, rootpath);
- for (CB_FileInfo file = {0}; cb_file_iter_next(&it, &file); free(file.path)) {
+ for (CB_FileInfo file = {0}; cb_filesystem_iter_next(&it, &file); free(file.path)) {
if (file.type == CB_FileType_Directory) {
cb_biblo_build_man(file.path, output_path);
} else {
int32_t line = 1;
- CB_Handle fd = cb_file_open(file.path, CB_AccessFlag_Read);
- assert(fd != CB_HANDLE_INVALID);
+ CB_FileHandle fd = cb_filesystem_open(cb_str8_from_cstr(file.path), CB_AccessFlag_Read);
+ assert(fd != CB_FILEHANDLE_INVALID);
struct CB_BibloParser parser = {0};
for (;;) {
CB_BibloElement doc = cb_biblo_parse(fd, &parser);
if (doc.name.length == 0) { break; }
CB_StringBuilder sb = {0};
- cb_sb_append(&sb, cb_view_from_cstr(output_path));
+ cb_sb_append(&sb, cb_str8_from_cstr(output_path));
cb_sb_append(&sb, cb_strlit("man3"));
- CB_StringView doc_fullpath = cb_sb_join_with_ch(sb, '/');
- cb_dir_create(doc_fullpath.data);
+ CB_String8 doc_fullpath = cb_sb_join_with_ch(sb, '/');
+ cb_filesystem_directory_create(doc_fullpath);
cb_biblo_generate_troff(&doc, doc_fullpath, file.path);
}
cb_file_close(fd);
}
}
+
+ cb_filesystem_iter_end(&it);
}
-internal void cb_biblo_generate_troff(const CB_BibloElement *element, CB_StringView path_dirdoc, const char *source_path)
+internal void cb_biblo_generate_troff(const CB_BibloElement *element, CB_String8 path_dirdoc, const char *source_path)
{
assert(element != NULL);
CB_StringBuilder sb_target = {0};
cb_sb_append(&sb_target, element->name);
cb_sb_append(&sb_target, cb_strlit("3"));
- CB_StringView troff_filename = cb_sb_join_with_ch(sb_target, '.');
+ CB_String8 troff_filename = cb_sb_join_with_ch(sb_target, '.');
CB_StringBuilder sb = {0};
cb_sb_append(&sb, path_dirdoc);
cb_sb_append(&sb, troff_filename);
- CB_StringView troff_filepath = cb_sb_join_with_ch(sb, '/');
+ CB_String8 troff_filepath = cb_sb_join_with_ch(sb, '/');
- cb_file_delete(troff_filepath.data);
- CB_Handle troff_fd = cb_file_open(troff_filepath.data, CB_AccessFlag_Write);
- assert(troff_fd != CB_HANDLE_INVALID);
+ cb_filesystem_delete(cb_str8_from_cstr(troff_filepath.data));
+ CB_FileHandle troff_fd = cb_filesystem_open(cb_str8_from_cstr(troff_filepath.data), CB_AccessFlag_Write);
+ assert(troff_fd != CB_FILEHANDLE_INVALID);
char *date = NULL;
#if OS_WINDOWS
#endif
assert(date != NULL);
- cb_file_write(troff_fd, ".TH ");
- cb_file_write(troff_fd, element->name);
- cb_file_write(troff_fd, " 3 ");
- cb_file_write(troff_fd, date);
- cb_file_write(troff_fd, " GNU\n.SH NAME\n");
+ cb_file_write_at_pointer(troff_fd, cb_strlit(".TH "));
+ cb_file_write_at_pointer(troff_fd, element->name);
+ cb_file_write_at_pointer(troff_fd, cb_strlit(" 3 "));
+ cb_file_write_at_pointer(troff_fd, cb_str8_from_cstr(date));
+ cb_file_write_at_pointer(troff_fd, cb_strlit(" GNU\n.SH NAME\n"));
if (element->aliases.node_count == 0) {
- cb_file_write(troff_fd, element->name);
+ cb_file_write_at_pointer(troff_fd, element->name);
} else {
for (struct CB_StringBuilder_Node *curr = element->aliases.first; curr; curr = curr->next) {
- cb_file_write(troff_fd, curr->value);
- if (curr->next) { cb_file_write(troff_fd, ",\\ "); }
+ cb_file_write_at_pointer(troff_fd, curr->value);
+ if (curr->next) { cb_file_write_at_pointer(troff_fd, cb_strlit(",\\ ")); }
}
}
if (element->brief.length > 0) {
- cb_file_write(troff_fd, " \\- ");
- cb_file_write(troff_fd, element->brief);
+ cb_file_write_at_pointer(troff_fd, cb_strlit(" \\- "));
+ cb_file_write_at_pointer(troff_fd, element->brief);
}
- cb_file_write(troff_fd, "\n.SH SYNOPSIS\n.RS\n.nf\n");
- cb_file_write(troff_fd, element->ref_block);
- cb_file_write(troff_fd, "\n.fi\n.RE");
+ cb_file_write_at_pointer(troff_fd, cb_strlit("\n.SH SYNOPSIS\n.RS\n.nf\n"));
+ cb_file_write_at_pointer(troff_fd, element->ref_block);
+ cb_file_write_at_pointer(troff_fd, cb_strlit("\n.fi\n.RE"));
if (element->description.length > 0) {
- cb_file_write(troff_fd, "\n.SH DESCRIPTION\n");
- cb_file_write(troff_fd, element->description);
+ cb_file_write_at_pointer(troff_fd, cb_strlit("\n.SH DESCRIPTION\n"));
+ cb_file_write_at_pointer(troff_fd, element->description);
}
- cb_file_write(troff_fd, "\n.SH FILES\n.TP\n.I ");
- cb_file_write(troff_fd, source_path);
+ cb_file_write_at_pointer(troff_fd, cb_strlit("\n.SH FILES\n.TP\n.I "));
+ cb_file_write_at_pointer(troff_fd, cb_str8_from_cstr(source_path));
if (element->aliases.node_count > 0) {
for (struct CB_StringBuilder_Node *curr = element->aliases.first; curr; curr = curr->next) {
CB_StringBuilder sb_link = {0};
cb_sb_append(&sb_link, path_dirdoc);
cb_sb_append(&sb_link, curr->value);
- CB_StringView link_filepath = cb_sb_join_with_ch(sb_link, '/');
+ CB_String8 link_filepath = cb_sb_join_with_ch(sb_link, '/');
memset(&sb_link, 0, sizeof sb_link);
cb_sb_append(&sb_link, link_filepath);
cb_sb_append(&sb_link, cb_strlit("3"));
link_filepath = cb_sb_join_with_ch(sb_link, '.');
- cb_symlink_create(troff_filename.data, link_filepath.data);
+ cb_filesystem_link_create_symbolic(troff_filename, link_filepath);
}
}
cb_file_close(troff_fd);
}
-internal CB_BibloElement cb_biblo_parse(CB_Handle file, struct CB_BibloParser *parser)
+internal CB_BibloElement cb_biblo_parse(CB_FileHandle file, struct CB_BibloParser *parser)
{
CB_BibloElement res = {0};
if (parser->hfile == 0) {
assert(file != 0);
parser->hfile = file;
- parser->content = cb_file_read(file);
+ parser->content = cb_file_read(file, -1, 0);
parser->offset = 0;
if (parser->content.length == 0) { return res; }
cb_biblo_find_prefix(parser);
assert(parser->content.data != NULL);
assert(parser->content.length > 0);
- bool has_explicit_ref_block = false, started_ref_block = false;
+ b8 has_explicit_ref_block = false, started_ref_block = false;
if (parser->prefix.data == NULL || parser->prefix.length <= 0) { return res; }
// NOTE(lb): skip lines until one that starts with `PREFIX@`
for (;;) {
- for (; !(cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix));) {
+ for (; !(cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix));) {
cb_biblo_parser_until_newline(parser, NULL);
if (parser->offset >= parser->content.length) { return res; }
}
}
}
- for (CB_StringView line = {0}; cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix);) {
+ for (CB_String8 line = {0}; cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix);) {
cb_biblo_parser_advance(parser, parser->prefix.length);
CB_StringBuilder sb = {0};
- if (cb_view_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_Brief])) {
+ if (cb_str8_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_Brief])) {
cb_biblo_parser_advance(parser, cb_biblo_annotation[CB_BibloAnnotationID_Brief].length);
if (parser->offset >= parser->content.length) {
cb_print(CB_LogLevel_Error, "Missing brief description.\n");
cb_biblo_parser_advance(parser, 1);
} else {
cb_biblo_parser_until_newline(parser, &line);
- cb_view_trim(&line);
+ cb_str8_trim(&line);
cb_sb_append(&sb, line);
}
- for (; cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix) &&
+ for (; cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix) &&
cb_biblo_parser_peek(parser, parser->prefix.length) != '@';) {
cb_biblo_parser_advance(parser, parser->prefix.length);
cb_biblo_parser_until_newline(parser, &line);
- cb_view_trim(&line);
+ cb_str8_trim(&line);
cb_sb_append(&sb, line);
}
- if (cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix)) {
+ if (cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix)) {
assert(cb_biblo_parser_peek(parser, parser->prefix.length) == '@');
}
res.brief = cb_sb_join_with_ch(sb, ' ');
- cb_view_trim(&res.brief);
+ cb_str8_trim(&res.brief);
}
- else if (cb_view_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_Name])) {
+ else if (cb_str8_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_Name])) {
cb_biblo_parser_advance(parser, cb_biblo_annotation[CB_BibloAnnotationID_Name].length);
if (parser->offset >= parser->content.length) {
cb_print(CB_LogLevel_Error, "Missing name.\n");
assert(false);
}
cb_biblo_parser_until_newline(parser, &line);
- cb_view_trim(&line);
+ cb_str8_trim(&line);
cb_sb_append(&sb, line);
- if (cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix)) {
+ if (cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix)) {
assert(cb_biblo_parser_peek(parser, parser->prefix.length) == '@');
}
res.name = cb_sb_join_with_ch(sb, ' ');
- cb_view_trim(&res.name);
+ cb_str8_trim(&res.name);
}
- else if (cb_view_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_Long])) {
+ else if (cb_str8_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_Long])) {
cb_biblo_parser_advance(parser, cb_biblo_annotation[CB_BibloAnnotationID_Long].length);
if (parser->offset >= parser->content.length) {
cb_print(CB_LogLevel_Error, "Missing description.\n");
cb_biblo_parser_advance(parser, 1);
} else {
cb_biblo_parser_until_newline(parser, &line);
- cb_view_trim(&line);
+ cb_str8_trim(&line);
cb_sb_append(&sb, line);
}
- for (; cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix) &&
+ for (; cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix) &&
cb_biblo_parser_peek(parser, parser->prefix.length) != '@';) {
cb_biblo_parser_advance(parser, parser->prefix.length);
cb_biblo_parser_until_newline(parser, &line);
- cb_view_trim(&line);
+ cb_str8_trim(&line);
cb_sb_append(&sb, line);
}
- if (cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix)) {
+ if (cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix)) {
assert(cb_biblo_parser_peek(parser, parser->prefix.length) == '@');
}
res.description = cb_sb_join_with_ch(sb, ' ');
- cb_view_trim(&res.description);
+ cb_str8_trim(&res.description);
}
- else if (cb_view_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_Alias])) {
+ else if (cb_str8_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_Alias])) {
cb_biblo_parser_advance(parser, cb_biblo_annotation[CB_BibloAnnotationID_Alias].length);
if (parser->offset >= parser->content.length) {
cb_print(CB_LogLevel_Error, "Missing alias list.\n");
}
if (cb_biblo_parser_peek(parser, 0) == '\n') {
cb_biblo_parser_advance(parser, 1);
- assert(cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix));
+ assert(cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix));
cb_biblo_parser_advance(parser, parser->prefix.length);
assert(cb_biblo_parser_peek(parser, 0) != '@');
}
for (; parser->offset < parser->content.length;) {
cb_biblo_parser_until_newline(parser, &line);
- CB_StringBuilder split_line = cb_view_split(line, ',');
+ CB_StringBuilder split_line = cb_str8_split(line, ',');
for (struct CB_StringBuilder_Node *curr = split_line.first; curr; curr = curr->next) {
- cb_view_trim(&curr->value);
+ cb_str8_trim(&curr->value);
}
cb_sb_concat(&res.aliases, &split_line);
- if (cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix) &&
+ if (cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix) &&
cb_biblo_parser_peek(parser, parser->prefix.length) != '@') {
cb_biblo_parser_advance(parser, parser->prefix.length);
} else {
break;
}
}
- if (cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix)) {
+ if (cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix)) {
assert(cb_biblo_parser_peek(parser, parser->prefix.length) == '@');
}
}
- else if (cb_view_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_ReferenceBegin])) {
+ else if (cb_str8_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_ReferenceBegin])) {
has_explicit_ref_block = true;
started_ref_block = true;
cb_biblo_parser_advance(parser, cb_biblo_annotation[CB_BibloAnnotationID_ReferenceBegin].length);
assert(false);
}
for (; parser->offset < parser->content.length &&
- !(cb_view_starts_with(&parser->content.data[parser->offset], parser->prefix) &&
- cb_view_starts_with(&parser->content.data[parser->offset] + parser->prefix.length,
+ !(cb_str8_starts_with(&parser->content.data[parser->offset], parser->prefix) &&
+ cb_str8_starts_with(&parser->content.data[parser->offset] + parser->prefix.length,
cb_biblo_annotation[CB_BibloAnnotationID_ReferenceEnd]));) {
cb_biblo_parser_until_newline(parser, &line);
cb_sb_append(&sb, line);
}
res.ref_block = cb_sb_join_with_ch(sb, '\n');
- cb_view_trim(&res.ref_block);
+ cb_str8_trim(&res.ref_block);
}
- else if (cb_view_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_ReferenceEnd])) {
+ else if (cb_str8_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[CB_BibloAnnotationID_ReferenceEnd])) {
assert(started_ref_block == true);
cb_biblo_parser_until_newline(parser, NULL);
}
}
if (!has_explicit_ref_block) {
CB_StringBuilder sb = {0};
- for (CB_StringView line = {0};
+ for (CB_String8 line = {0};
parser->offset < parser->content.length && cb_biblo_parser_peek(parser, 0) != '\n';) {
cb_biblo_parser_until_newline(parser, &line);
cb_sb_append(&sb, line);
}
res.ref_block = cb_sb_join_with_ch(sb, '\n');
- cb_view_trim(&res.ref_block);
+ cb_str8_trim(&res.ref_block);
}
if (res.name.length <= 0) {
cb_print(CB_LogLevel_Error, "Missing mandatory biblo name annotation.\n");
assert(parser->offset <= parser->content.length);
}
-internal char cb_biblo_parser_peek(struct CB_BibloParser *parser, ssize_t offset)
+internal char cb_biblo_parser_peek(struct CB_BibloParser *parser, int64_t offset)
{
assert(parser != NULL);
assert(parser->content.data != NULL);
return parser->content.data[parser->offset + offset];
}
-internal void cb_biblo_parser_until_newline(struct CB_BibloParser *parser, CB_StringView *sv)
+internal void cb_biblo_parser_until_newline(struct CB_BibloParser *parser, CB_String8 *sv)
{
assert(parser != NULL);
assert(parser->content.data != NULL);
switch (cb_biblo_parser_peek(parser, 0)) {
case '@': {
for (int32_t i = 0; i < cb_arrlength(cb_biblo_annotation); ++i) {
- if (cb_view_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[i])) {
+ if (cb_str8_starts_with(&parser->content.data[parser->offset], cb_biblo_annotation[i])) {
parser->prefix.data = &parser->content.data[line_start];
parser->prefix.length = parser->offset - line_start;
parser->offset = line_start;
#include <assert.h>
internal void
-cb_linagen_defun_vecn_element_wise(CB_Generator *gen, char *type,
+cb_linagen_defun_vecn_element_wise(CB_Generator *gen, const char *type,
int32_t n, b8 implementation,
- char *func_name, char op);
+ const char *func_name, char op);
internal void
-cb_linagen_defun_matnn_element_wise(CB_Generator *gen, char *type,
+cb_linagen_defun_matnn_element_wise(CB_Generator *gen, const char *type,
int32_t n, b8 implementation,
- char *func_name, char op);
+ const char *func_name, char op);
internal char char_toupper(char ch);
static void
-cb_linagen_typedef_vecn(CB_Generator *gen, char *type, int32_t n, ...);
+cb_linagen_typedef_vecn(CB_Generator *gen, const char *type, int32_t n, ...);
static void
-cb_linagen_typedef_vecn_unnamed(CB_Generator *gen, char *type, int32_t n);
+cb_linagen_typedef_vecn_unnamed(CB_Generator *gen, const char *type, int32_t n);
static void
-cb_linagen_typedef_matnn(CB_Generator *gen, char *type, int32_t n);
+cb_linagen_typedef_matnn(CB_Generator *gen, const char *type, int32_t n);
static inline void
-cb_linagen_defun_vecn(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_vecn_add(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_add(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_vecn_sub(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_sub(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_equal(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_vecn_near(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_near(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_lerp(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_scale(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_normalize(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_dot(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_mulm(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_magnitude(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_distance(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_vecn_distance2(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type, b8 implementation);
+cb_linagen_defun_vec3_cross(CB_Generator *gen, const char *type, b8 implementation);
static void
-cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_matnn_scale(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_matnn_add(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_matnn_add(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_matnn_sub(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_matnn_sub(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static inline void
-cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_matnn_dot(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_matnn_mulv(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type, int32_t n, b8 implementation);
+cb_linagen_defun_matnn_identity(CB_Generator *gen, const char *type, int32_t n, b8 implementation);
static void
-cb_linagen_defun_mat4_transform_translate_by(CB_Generator *gen, char *type, b8 implementation);
+cb_linagen_defun_mat4_transform_translate_by(CB_Generator *gen, const char *type, b8 implementation);
static void
-cb_linagen_defun_mat4_transform_translate_to(CB_Generator *gen, char *type, b8 implementation);
+cb_linagen_defun_mat4_transform_translate_to(CB_Generator *gen, const char *type, b8 implementation);
static void
-cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, char *type, b8 implementation);
+cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, const char *type, b8 implementation);
static void
-cb_linagen_defun_mat4_transform_rotate_rad(CB_Generator *gen, char *type, b8 implementation);
+cb_linagen_defun_mat4_transform_rotate_rad(CB_Generator *gen, const char *type, b8 implementation);
static void
-cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, char *type, b8 implementation);
+cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, const char *type, b8 implementation);
static void
-cb_linagen_defun_mat4_projection_orthographic(CB_Generator *gen, char *type, b8 implementation);
+cb_linagen_defun_mat4_projection_orthographic(CB_Generator *gen, const char *type, b8 implementation);
static void
-cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, char *type, b8 implementation);
+cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, const char *type, b8 implementation);
static void
-cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, char *type, b8 implementation);
+cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, const char *type, b8 implementation);
// ======================================================================
// Implementations
static void
-cb_linagen_typedef_vecn(CB_Generator *gen, char *type, int32_t n, ...) {
+cb_linagen_typedef_vecn(CB_Generator *gen, const char *type, int32_t n, ...) {
va_list args = {0};
va_start(args, n);
char *suffix = strdup(type);
"\n struct {", type, n));
b8 found_last_named_field = false;
for (int32_t i = 0; i < n; ++i) {
- char *prefix = " ";
+ const char *prefix = " ";
if (i % 4 == 0) {
prefix = "\n ";
}
}
static void
-cb_linagen_typedef_vecn_unnamed(CB_Generator *gen, char *type, int32_t n) {
+cb_linagen_typedef_vecn_unnamed(CB_Generator *gen, const char *type, int32_t n) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push(gen, cb_format("typedef struct Vec%d%s {"
}
static void
-cb_linagen_typedef_matnn(CB_Generator *gen, char *type, int32_t n) {
+cb_linagen_typedef_matnn(CB_Generator *gen, const char *type, int32_t n) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push(gen, cb_format("typedef union Mat%d%s {"
}
static inline void
-cb_linagen_defun_vecn(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec%d%s vec%d%s",
}
static inline void
-cb_linagen_defun_vecn_add(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_add(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
cb_linagen_defun_vecn_element_wise(gen, type, n, implementation, "add", '+');
}
static inline void
-cb_linagen_defun_vecn_sub(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_sub(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
cb_linagen_defun_vecn_element_wise(gen, type, n, implementation, "sub", '-');
}
static inline void
-cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
cb_linagen_defun_vecn_element_wise(gen, type, n, implementation,
"hadamard_prod", '*');
}
static inline void
-cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
cb_linagen_defun_vecn_element_wise(gen, type, n, implementation,
"hadamard_div", '/');
}
static inline void
-cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_equal(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static inline void
-cb_linagen_defun_vecn_near(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_near(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static inline void
-cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_lerp(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static void
-cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_scale(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static void
-cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_normalize(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static void
-cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_dot(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static void
-cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_mulm(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
if (!implementation) { return; }
cb_gen_push_line(gen, cb_format("{" "\n Vec%d%s res = {0};", n, suffix));
for (int32_t i = 0; i < n; ++i) {
- char *prefix = "";
+ const char *prefix = "";
cb_gen_push(gen, cb_format(" res.values[%d] = ", i));
for (int32_t j = 0; j < n; ++j) {
cb_gen_push(gen, cb_format("%s(v.values[%d] * m.values[%d][%d])",
cb_gen_push(gen, "{\n");
for (int32_t i = 0; i < n; ++i) {
- char *prefix = "";
+ const char *prefix = "";
cb_gen_push(gen, cb_format(" res->values[%d] = ", i));
for (int32_t j = 0; j < n; ++j) {
cb_gen_push(gen, cb_format("%s(v->values[%d] * m->values[%d][%d])",
}
static void
-cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_magnitude(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static void
-cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static void
-cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_distance(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static void
-cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_vecn_distance2(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn float vec%d%s_distance2",
}
static inline void
-cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type, b8 implementation) {
+cb_linagen_defun_vec3_cross(CB_Generator *gen, const char *type, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec3%s vec3%s_cross", suffix, type));
}
static void
-cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_matnn_scale(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static inline void
-cb_linagen_defun_matnn_add(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_matnn_add(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
cb_linagen_defun_matnn_element_wise(gen, type, n, implementation, "add", '+');
}
static inline void
-cb_linagen_defun_matnn_sub(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_matnn_sub(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
cb_linagen_defun_matnn_element_wise(gen, type, n, implementation, "sub", '-');
}
static inline void
-cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
cb_linagen_defun_matnn_element_wise(gen, type, n, implementation,
"hadamard_prod", '*');
}
static inline void
-cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
cb_linagen_defun_matnn_element_wise(gen, type, n, implementation,
"hadamard_div", '/');
}
static void
-cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_matnn_dot(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
for (int32_t col = 0; col < n; ++col) {
for (int32_t row = 0; row < n; ++row) {
cb_gen_push(gen, cb_format(" res.values[%d][%d] = ", col, row));
- char *prefix = "";
+ const char *prefix = "";
for (int32_t k = 0; k < n; ++k) {
cb_gen_push(gen, cb_format("%s(m1.values[%d][%d] * m2.values[%d][%d])",
prefix, k, row, col, k));
for (int32_t col = 0; col < n; ++col) {
for (int32_t row = 0; row < n; ++row) {
cb_gen_push(gen, cb_format(" res->values[%d][%d] = ", col, row));
- char *prefix = "";
+ const char *prefix = "";
for (int32_t k = 0; k < n; ++k) {
cb_gen_push(gen, cb_format("%s(m1->values[%d][%d] * m2->values[%d][%d])",
prefix, k, row, col, k));
}
static void
-cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_matnn_mulv(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_line(gen, cb_format("{" "\n Vec%d%s res = {0};", n, suffix));
for (int32_t i = 0; i < n; ++i) {
- char *prefix = "";
+ const char *prefix = "";
cb_gen_push(gen, cb_format(" res.values[%d] = ", i));
for (int32_t j = 0; j < n; ++j) {
cb_gen_push(gen, cb_format("%s(m.values[%d][%d] * v.values[%d])",
cb_gen_push(gen, "{\n");
for (int32_t i = 0; i < n; ++i) {
- char *prefix = "";
+ const char *prefix = "";
cb_gen_push(gen, cb_format(" res->values[%d] = ", i));
for (int32_t j = 0; j < n; ++j) {
cb_gen_push(gen, cb_format("%s(m->values[%d][%d] * v->values[%d])",
}
static void
-cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type, int32_t n, b8 implementation) {
+cb_linagen_defun_matnn_identity(CB_Generator *gen, const char *type, int32_t n, b8 implementation) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
static void
-cb_linagen_defun_mat4_transform_translate_by(CB_Generator *gen, char *type, b8 implementation) {
+cb_linagen_defun_mat4_transform_translate_by(CB_Generator *gen, const char *type, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_transform_translate_by", suffix, type));
}
static void
-cb_linagen_defun_mat4_transform_translate_to(CB_Generator *gen, char *type, b8 implementation) {
+cb_linagen_defun_mat4_transform_translate_to(CB_Generator *gen, const char *type, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_transform_translate_to", suffix, type));
}
static void
-cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, char *type, b8 implementation) {
+cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, const char *type, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_transform_rotate", suffix, type));
for (int32_t i = 0; i < 4; ++i) {
for (int32_t j = 0; j < 4; ++j) {
cb_gen_push(gen, cb_format(" res.values[%d][%d] = ", i, j));
- char *prefix = "";
+ const char *prefix = "";
for (int32_t k = 0; k < 4; ++k) {
cb_gen_push(gen, cb_format("%s(rot.values[%d][%d]) * m.values[%d][%d]",
prefix, k, j, i, k));
}
static void
-cb_linagen_defun_mat4_transform_rotate_rad(CB_Generator *gen, char *type, b8 implementation) {
+cb_linagen_defun_mat4_transform_rotate_rad(CB_Generator *gen, const char *type, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_transform_rotate_rad", suffix, type));
for (int32_t i = 0; i < 4; ++i) {
for (int32_t j = 0; j < 4; ++j) {
cb_gen_push(gen, cb_format(" res.values[%d][%d] = ", i, j));
- char *prefix = "";
+ const char *prefix = "";
for (int32_t k = 0; k < 4; ++k) {
cb_gen_push(gen, cb_format("%s(rot.values[%d][%d]) * m.values[%d][%d]",
prefix, k, j, i, k));
}
static void
-cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, char *type, b8 implementation) {
+cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, const char *type, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_transform_scale", suffix, type));
for (int32_t i = 0; i < 4; ++i) {
for (int32_t j = 0; j < 4; ++j) {
cb_gen_push(gen, cb_format(" res.values[%d][%d] = ", i, j));
- char *prefix = "";
+ const char *prefix = "";
for (int32_t k = 0; k < 4; ++k) {
cb_gen_push(gen, cb_format("%s(scale.values[%d][%d]) * m.values[%d][%d]",
prefix, k, j, i, k));
}
static void
-cb_linagen_defun_mat4_projection_orthographic(CB_Generator *gen, char *type, b8 implementation) {
+cb_linagen_defun_mat4_projection_orthographic(CB_Generator *gen, const char *type, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_projection_orthographic", suffix, type));
}
static void
-cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, char *type, b8 implementation) {
+cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, const char *type, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_projection_perspective", suffix, type));
}
static void
-cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, char *type, b8 implementation) {
+cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, const char *type, b8 implementation) {
char *suffix = strdup(type);
*suffix = char_toupper(*type);
cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_projection_perspective_rad", suffix, type));
internal void
-cb_linagen_defun_vecn_element_wise(CB_Generator *gen, char *type,
+cb_linagen_defun_vecn_element_wise(CB_Generator *gen, const char *type,
int32_t n, b8 implementation,
- char *func_name, char op) {
+ const char *func_name, char op) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
internal void
-cb_linagen_defun_matnn_element_wise(CB_Generator *gen, char *type,
+cb_linagen_defun_matnn_element_wise(CB_Generator *gen, const char *type,
int32_t n, b8 implementation,
- char *func_name, char op) {
+ const char *func_name, char op) {
assert(n > 1);
char *suffix = strdup(type);
*suffix = char_toupper(*type);
}
}
cb_assertion_handler = cb_assertion_break;
- cb_print(CB_LogLevel_Info, "Summary: %d/%d tests passed\n",
- test_passed_count, cb_tests.count);
+ cb_print(CB_LogLevel_Info, "Summary: %d/%d tests passed\n", test_passed_count, cb_tests.count);
}
internal void cb_test_register(struct CB_Test test) {
- cb_dyn_push_custom(&cb_tests, test,
- tests, count, capacity);
+ cb_dyn_push_custom(&cb_tests, test, tests, count, capacity);
}
-internal void cb_assertion_test(char *condition,
- char *file, int32_t line) {
- printf(ANSI_COLOR_RED "FAILED" ANSI_COLOR_RESET
- ": `%s` (%s:%d)\n", condition, file, line);
+internal void cb_assertion_test(char *condition, char *file, int32_t line) {
+ printf(ANSI_COLOR_RED "FAILED" ANSI_COLOR_RESET ": `%s` (%s:%d)\n", condition, file, line);
longjmp(test_runner_jmpbuf, 1);
}
+#ifdef CBUILD_TEST_INCLUDE_SELFTEST
+// TODO(lb): test `cbuild.h` stuff.
+// the other extras can be tested by having `cbuild_test.h` included last
+// and by placing the tests behind include guards.
+#endif // CBUILD_TEST_INCLUDE_SELFTEST
+
#endif