This commit is contained in:
Krzosa Karol
2025-04-03 10:52:11 +02:00
parent c8e73ac245
commit 706bd89385
11 changed files with 759 additions and 78 deletions

View File

@@ -350,9 +350,9 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int n
ma_temp_t scratch = ma_begin_scratch(); ma_temp_t scratch = ma_begin_scratch();
s8_t dir = os_exe_dir(scratch.arena); s8_t dir = os_exe_dir(scratch.arena);
for (os_iter_t *it = os_iter(scratch.arena, dir); it->is_valid; os_advance(it)) { for (os_iter_t *it = os_iter(scratch.arena, dir); it->is_valid; os_advance(it)) {
b32 is_dll = s8_ends_with(it->name, s8_lit(".dll"), false); b32 is_dll = s8_ends_with(it->name, s8_lit(".dll"));
b32 is_pdb = s8_ends_with(it->name, s8_lit(".pdb"), false); b32 is_pdb = s8_ends_with(it->name, s8_lit(".pdb"));
b32 is_rdi = s8_ends_with(it->name, s8_lit(".rdi"), false); b32 is_rdi = s8_ends_with(it->name, s8_lit(".rdi"));
b32 is_temp = s8_find(it->name, s8_lit("_temp_"), s8_seek_none) != -1; b32 is_temp = s8_find(it->name, s8_lit("_temp_"), s8_seek_none) != -1;
if (is_temp && (is_dll || is_pdb || is_rdi)) { if (is_temp && (is_dll || is_pdb || is_rdi)) {
b32 ok = os_delete(it->abs); b32 ok = os_delete(it->abs);

View File

@@ -30,7 +30,7 @@ fn void os_error_box(char *str) {
fn void os_console_log(char *str) { fn void os_console_log(char *str) {
s8_t string = s8_from_char(str); s8_t string = s8_from_char(str);
if (s8_ends_with(string, s8_lit("\n"), false)) { if (s8_ends_with(string, s8_lit("\n"))) {
string = s8_chop(string, 1); string = s8_chop(string, 1);
} }
wasm_write_to_console((isize)string.str, (i32)string.len); wasm_write_to_console((isize)string.str, (i32)string.len);

View File

@@ -45,13 +45,6 @@ fn b32 char_is_alphanumeric(char a) {
return result; return result;
} }
fn i64 wstr_len(wchar_t *string) {
i64 len = 0;
while (*string++ != 0)
len++;
return len;
}
fn s8_t s8_from_range(char *begin, char *end) { fn s8_t s8_from_range(char *begin, char *end) {
assert(end >= begin); assert(end >= begin);
intptr_t size = (intptr_t)end - (intptr_t)begin; intptr_t size = (intptr_t)end - (intptr_t)begin;
@@ -66,21 +59,6 @@ fn s8_t s8_from_char(char *string) {
return result; return result;
} }
fn s16_t s16_from_s8(ma_arena_t *ma, s8_t string) {
u16 *buffer = ma_push_array(ma, u16, string.len + 1);
i64 len = wstr_from_str(buffer, string.len + 1, string.str, string.len);
assert(len <= string.len); // @todo: verify
return (s16_t){buffer, len};
}
fn s8_t s8_from_s16(ma_arena_t *ma, s16_t string) {
i64 buffer_size = (string.len + 1) * 2;
char *buffer = ma_push_array(ma, char, buffer_size);
i64 len = str_from_wstr(buffer, buffer_size, string.str, string.len);
assert(len < buffer_size);
return (s8_t){buffer, len};
}
fn s8_t s8_copy(ma_arena_t *ma, s8_t string) { fn s8_t s8_copy(ma_arena_t *ma, s8_t string) {
char *copy = (char *)ma_push_size(ma, sizeof(char) * (string.len + 1)); char *copy = (char *)ma_push_size(ma, sizeof(char) * (string.len + 1));
memory_copy(copy, string.str, string.len); memory_copy(copy, string.str, string.len);
@@ -89,7 +67,7 @@ fn s8_t s8_copy(ma_arena_t *ma, s8_t string) {
return result; return result;
} }
s8_t s8_copy_char(ma_arena_t *ma, char *s) { fn s8_t s8_copy_char(ma_arena_t *ma, char *s) {
int64_t len = str_len(s); int64_t len = str_len(s);
char *copy = (char *)ma_push_size(ma, sizeof(char) * (len + 1)); char *copy = (char *)ma_push_size(ma, sizeof(char) * (len + 1));
memory_copy(copy, s, len); memory_copy(copy, s, len);
@@ -143,18 +121,26 @@ fn s8_t s8_skip(s8_t string, int64_t len) {
return result; return result;
} }
fn b32 s8_ends_with(s8_t a, s8_t end, b32 ignore_case) { fn b32 s8_ends_with_ex(s8_t a, s8_t end, b32 ignore_case) {
s8_t a_end = s8_get_postfix(a, end.len); s8_t a_end = s8_get_postfix(a, end.len);
b32 result = s8_are_equal_ex(end, a_end, ignore_case); b32 result = s8_are_equal_ex(end, a_end, ignore_case);
return result; return result;
} }
fn b32 s8_starts_with(s8_t a, s8_t start, b32 ignore_case) { fn b32 s8_starts_with_ex(s8_t a, s8_t start, b32 ignore_case) {
s8_t a_start = s8_get_prefix(a, start.len); s8_t a_start = s8_get_prefix(a, start.len);
b32 result = s8_are_equal_ex(start, a_start, ignore_case); b32 result = s8_are_equal_ex(start, a_start, ignore_case);
return result; return result;
} }
fn b32 s8_ends_with(s8_t a, s8_t end) {
return s8_ends_with_ex(a, end, false);
}
fn b32 s8_starts_with(s8_t a, s8_t start) {
return s8_starts_with_ex(a, start, false);
}
fn void s8_normalize_path_unsafe(s8_t s) { fn void s8_normalize_path_unsafe(s8_t s) {
for (int64_t i = 0; i < s.len; i++) { for (int64_t i = 0; i < s.len; i++) {
if (s.str[i] == '\\') if (s.str[i] == '\\')
@@ -297,34 +283,35 @@ fn int64_t s8_find(s8_t string, s8_t find, s8_seek_t flag) {
return result; return result;
} }
fn s8_t s8_chop_last_slash(s8_t s) { fn s8_t s8_chop_last_char(s8_t s, s8_t ch) {
s8_t result = s; s8_t result = s;
s8_seek(s, s8_lit("/"), s8_seek_match_find_last, &result.len); s8_seek(s, ch, s8_seek_match_find_last, &result.len);
return result; return result;
} }
fn s8_t s8_chop_last_slash(s8_t s) {
return s8_chop_last_char(s, s8_lit("/"));
}
fn s8_t s8_chop_last_period(s8_t s) { fn s8_t s8_chop_last_period(s8_t s) {
return s8_chop_last_char(s, s8_lit("."));
}
fn s8_t s8_skip_to_last_char(s8_t s, s8_t ch) {
int64_t pos;
s8_t result = s; s8_t result = s;
s8_seek(s, s8_lit("."), s8_seek_match_find_last, &result.len); if (s8_seek(s, ch, s8_seek_match_find_last, &pos)) {
result = s8_skip(result, pos + 1);
}
return result; return result;
} }
fn s8_t s8_skip_to_last_slash(s8_t s) { fn s8_t s8_skip_to_last_slash(s8_t s) {
int64_t pos; return s8_skip_to_last_char(s, s8_lit("/"));
s8_t result = s;
if (s8_seek(s, s8_lit("/"), s8_seek_match_find_last, &pos)) {
result = s8_skip(result, pos + 1);
}
return result;
} }
fn s8_t s8_skip_to_last_period(s8_t s) { fn s8_t s8_skip_to_last_period(s8_t s) {
int64_t pos; return s8_skip_to_last_char(s, s8_lit("."));
s8_t result = s;
if (s8_seek(s, s8_lit("."), s8_seek_match_find_last, &pos)) {
result = s8_skip(result, pos + 1);
}
return result;
} }
fn s8_t s8_get_name_no_ext(s8_t s) { fn s8_t s8_get_name_no_ext(s8_t s) {
@@ -333,10 +320,7 @@ fn s8_t s8_get_name_no_ext(s8_t s) {
fn s8_t s8_normalize_path(ma_arena_t *ma, s8_t s) { fn s8_t s8_normalize_path(ma_arena_t *ma, s8_t s) {
s8_t copy = s8_copy(ma, s); s8_t copy = s8_copy(ma, s);
for (int64_t i = 0; i < copy.len; i++) { s8_normalize_path_unsafe(copy);
if (copy.str[i] == '\\')
copy.str[i] = '/';
}
return copy; return copy;
} }
@@ -489,9 +473,9 @@ fn f64 f64_from_s8(s8_t string) {
return result; return result;
} }
gb_read_only i64 fuzzy_closer_word_begin = 5; gb_read_only i64 s8_fuzzy_closer_word_begin = 5;
gb_read_only i64 fuzzy_consecutive_multiplier = 3; gb_read_only i64 s8_fuzzy_consecutive_multiplier = 3;
fn i64 fuzzy_rate_string(s8_t string, s8_t with) { fn i64 s8_fuzzy_rate_string(s8_t string, s8_t with) {
if (with.len == 0) return 0; if (with.len == 0) return 0;
i64 points = 0; i64 points = 0;
@@ -499,26 +483,26 @@ fn i64 fuzzy_rate_string(s8_t string, s8_t with) {
i64 with_i = 0; i64 with_i = 0;
for (i64 i = 0; i < string.len; i++) { for (i64 i = 0; i < string.len; i++) {
if (string.str[i] == with.str[with_i]) { if (string.str[i] == with.str[with_i]) {
i64 closer_begin = CLAMP_BOT((i64)0, fuzzy_closer_word_begin - i); i64 closer_begin = CLAMP_BOT((i64)0, s8_fuzzy_closer_word_begin - i);
points += closer_begin; points += closer_begin;
consecutive++; consecutive++;
with_i += 1; with_i += 1;
} else { } else {
points += consecutive * fuzzy_consecutive_multiplier; points += consecutive * s8_fuzzy_consecutive_multiplier;
consecutive = 0; consecutive = 0;
with_i = 0; with_i = 0;
} }
if (with_i >= with.len) with_i = 0; if (with_i >= with.len) with_i = 0;
} }
points += consecutive * fuzzy_consecutive_multiplier; points += consecutive * s8_fuzzy_consecutive_multiplier;
return points; return points;
} }
fn fuzzy_pair_t *fuzzy_rate_array(ma_arena_t *arena, s8_t needle, s8_t *array, i32 len) { fn fuzzy_pair_t *s8_fuzzy_rate_array(ma_arena_t *arena, s8_t needle, s8_t *array, i32 len) {
fuzzy_pair_t *pairs = ma_push_array(arena, fuzzy_pair_t, len); fuzzy_pair_t *pairs = ma_push_array(arena, fuzzy_pair_t, len);
for (i32 i = 0; i < len; i += 1) { for (i32 i = 0; i < len; i += 1) {
pairs[i].rating = fuzzy_rate_string(array[i], needle); pairs[i].rating = s8_fuzzy_rate_string(array[i], needle);
pairs[i].index = i; pairs[i].index = i;
} }

View File

@@ -4,18 +4,6 @@ struct s8_t {
int64_t len; int64_t len;
}; };
typedef struct s16_t s16_t;
struct s16_t {
u16 *str;
i64 len;
};
typedef struct s32_t s32_t;
struct s32_t {
u32 *str;
i64 len;
};
typedef struct sb8_node_t sb8_node_t; typedef struct sb8_node_t sb8_node_t;
struct sb8_node_t { struct sb8_node_t {
sb8_node_t *next; sb8_node_t *next;
@@ -54,7 +42,6 @@ enum { s8_ignore_case = 1 };
// //
// char and char string operations // char and char string operations
fn i32 str_len(char *str); fn i32 str_len(char *str);
fn i64 wstr_len(wchar_t *string);
fn b32 str_eq(char *a, char *b); fn b32 str_eq(char *a, char *b);
fn char char_to_lower_case(char a); fn char char_to_lower_case(char a);
fn char char_to_upper_case(char a); fn char char_to_upper_case(char a);
@@ -81,15 +68,15 @@ fn f64 f64_from_s8(s8_t string);
fn s8_t s8_from_range(char *begin, char *end); fn s8_t s8_from_range(char *begin, char *end);
fn s8_t s8_from_char(char *string); fn s8_t s8_from_char(char *string);
fn s8_t s8_copy(ma_arena_t *ma, s8_t string); fn s8_t s8_copy(ma_arena_t *ma, s8_t string);
fn s16_t s16_from_s8(ma_arena_t *ma, s8_t string);
fn s8_t s8_from_s16(ma_arena_t *ma, s16_t string);
// //
// conditional // conditional
fn b32 s8_are_equal_ex(s8_t a, s8_t b, b32 ignore_case); fn b32 s8_are_equal_ex(s8_t a, s8_t b, b32 ignore_case);
fn b32 s8_are_equal(s8_t a, s8_t b); fn b32 s8_are_equal(s8_t a, s8_t b);
fn b32 s8_ends_with(s8_t a, s8_t end, b32 ignore_case); fn b32 s8_ends_with_ex(s8_t a, s8_t end, b32 ignore_case);
fn b32 s8_starts_with(s8_t a, s8_t start, b32 ignore_case); fn b32 s8_starts_with_ex(s8_t a, s8_t start, b32 ignore_case);
fn b32 s8_ends_with(s8_t a, s8_t end);
fn b32 s8_starts_with(s8_t a, s8_t start);
fn b32 s8_is_pointer_inside(s8_t string, char *p);// @todo: maybe more general? fn b32 s8_is_pointer_inside(s8_t string, char *p);// @todo: maybe more general?
// //
@@ -162,7 +149,6 @@ void *sbin_read_data(stream_t *stream, i64 size);
#define S8_CODE(...) s8_lit(#__VA_ARGS__) #define S8_CODE(...) s8_lit(#__VA_ARGS__)
#define S8_FILE s8_lit(__FILE__) #define S8_FILE s8_lit(__FILE__)
#define S8_FILE_AND_LINE s8_lit(FILE_AND_LINE) #define S8_FILE_AND_LINE s8_lit(FILE_AND_LINE)
#define s16(str,len) (s16_t){str, len}
#define S8_FMT(ma, str, result) \ #define S8_FMT(ma, str, result) \
va_list args1; \ va_list args1; \

View File

@@ -0,0 +1,594 @@
fn i64 wstr_len(wchar_t *string) {
i64 len = 0;
while (*string++ != 0)
len++;
return len;
}
fn u16 u16_to_lower_case(u16 a) {
if (a >= 'A' && a <= 'Z') a += 32;
return a;
}
fn u16 u16_to_upper_case(u16 a) {
if (a >= 'a' && a <= 'z') a -= 32;
return a;
}
fn b32 u16_is_whitespace(u16 w) {
b32 result = w == '\n' || w == ' ' || w == '\t' || w == '\v' || w == '\r';
return result;
}
fn b32 u16_is_alphabetic(u16 a) {
b32 result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');
return result;
}
fn b32 u16_is_ident(u16 a) {
b32 result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') || a == '_';
return result;
}
fn b32 u16_is_digit(u16 a) {
b32 result = a >= '0' && a <= '9';
return result;
}
fn b32 u16_is_alphanumeric(u16 a) {
b32 result = u16_is_digit(a) || u16_is_alphabetic(a);
return result;
}
fn s16_t s16_from_range(u16 *begin, u16 *end) {
assert(end >= begin);
intptr_t size = (intptr_t)end - (intptr_t)begin;
s16_t result = {begin, size / 2};
return result;
}
fn s16_t s16_from_u16(u16 *string) {
s16_t result;
result.str = string;
result.len = wstr_len(string);
return result;
}
fn s16_t s16_from_wstr(wchar_t *string) {
return s16_from_u16((u16 *)string);
}
fn s16_t s16_copy(ma_arena_t *ma, s16_t string) {
i64 byte_size = sizeof(u16) * string.len;
u16 *copy = (u16 *)ma_push_size(ma, byte_size + sizeof(u16));
memory_copy(copy, string.str, byte_size);
copy[string.len] = 0;
s16_t result = s16(copy, string.len);
return result;
}
fn s16_t s16_copy_u16(ma_arena_t *ma, u16 *s) {
return s16_copy(ma, s16(s, wstr_len(s)));
}
fn s16_t s16_copy_wstr(ma_arena_t *ma, wchar_t *s) {
return s16_copy(ma, s16(s, wstr_len(s)));
}
fn b32 s16_are_equal_ex(s16_t a, s16_t b, b32 ignore_case) {
if (a.len != b.len) return false;
for (i64 i = 0; i < a.len; i++) {
u16 A = a.str[i];
u16 B = b.str[i];
if (ignore_case) {
A = u16_to_lower_case(A);
B = u16_to_lower_case(B);
}
if (A != B)
return false;
}
return true;
}
fn b32 s16_are_equal(s16_t a, s16_t b) {
return s16_are_equal_ex(a, b, false);
}
fn s16_t s16_from_s8(ma_arena_t *ma, s8_t string) {
u16 *buffer = ma_push_array(ma, u16, string.len + 1);
i64 len = wstr_from_str(buffer, string.len + 1, string.str, string.len);
assert(len <= string.len); // @todo: verify
return (s16_t){buffer, len};
}
fn s8_t s8_from_s16(ma_arena_t *ma, s16_t string) {
i64 buffer_size = (string.len + 1) * 2;
char *buffer = ma_push_array(ma, char, buffer_size);
i64 len = str_from_wstr(buffer, buffer_size, string.str, string.len);
assert(len < buffer_size);
return (s8_t){buffer, len};
}
fn s16_t s16_get_postfix(s16_t string, i64 len) {
len = CLAMP_TOP(len, string.len);
i64 remain_len = string.len - len;
s16_t result = s16(string.str + remain_len, len);
return result;
}
fn s16_t s16_get_prefix(s16_t string, i64 len) {
len = CLAMP_TOP(len, string.len);
s16_t result = s16(string.str, len);
return result;
}
fn s16_t s16_chop(s16_t string, i64 len) {
len = CLAMP_TOP(len, string.len);
s16_t result = s16(string.str, string.len - len);
return result;
}
fn s16_t s16_skip(s16_t string, i64 len) {
len = CLAMP_TOP(len, string.len);
i64 remain = string.len - len;
s16_t result = s16(string.str + len, remain);
return result;
}
fn b32 s16_ends_with_ex(s16_t a, s16_t end, b32 ignore_case) {
s16_t a_end = s16_get_postfix(a, end.len);
b32 result = s16_are_equal_ex(end, a_end, ignore_case);
return result;
}
fn b32 s16_starts_with_ex(s16_t a, s16_t start, b32 ignore_case) {
s16_t a_start = s16_get_prefix(a, start.len);
b32 result = s16_are_equal_ex(start, a_start, ignore_case);
return result;
}
fn b32 s16_ends_with(s16_t a, s16_t end) {
return s16_ends_with_ex(a, end, false);
}
fn b32 s16_starts_with(s16_t a, s16_t start) {
return s16_ends_with_ex(a, start, false);
}
fn void s16_normalize_path_unsafe(s16_t s) {
for (i64 i = 0; i < s.len; i++) {
if (s.str[i] == '\\')
s.str[i] = '/';
}
}
fn s16_t s16_normalize_path(ma_arena_t *ma, s16_t s) {
s16_t copy = s16_copy(ma, s);
s16_normalize_path_unsafe(copy);
return copy;
}
fn b32 s16_is_pointer_inside(s16_t string, u16 *p) {
uintptr_t pointer = (uintptr_t)p;
uintptr_t start = (uintptr_t)string.str;
uintptr_t stop = start + (uintptr_t)string.len * sizeof(u16);
b32 result = pointer >= start && pointer < stop;
return result;
}
fn s16_t s16_cut_start(s16_t *in, i64 size) {
s16_t result = s16_get_prefix(*in, size);
*in = s16_skip(*in, result.len);
return result;
}
fn s16_t s16_cut_end(s16_t *in, i64 size) {
s16_t result = s16_get_postfix(*in, size);
*in = s16_chop(*in, result.len);
return result;
}
fn s16_t s16_slice(s16_t string, i64 first_index, i64 one_past_last_index) {
if (one_past_last_index < 0) one_past_last_index = string.len + one_past_last_index + 1;
if (first_index < 0) first_index = string.len + first_index;
assert(first_index < one_past_last_index);
assert(string.len > 0);
s16_t result = string;
if (string.len > 0) {
if (one_past_last_index > first_index) {
first_index = CLAMP_TOP(first_index, string.len - 1);
one_past_last_index = CLAMP_TOP(one_past_last_index, string.len);
result.str += first_index;
result.len = one_past_last_index - first_index;
}
else {
result.len = 0;
}
}
return result;
}
fn s16_t s16_trim(s16_t string) {
if (string.len == 0)
return string;
i64 whitespace_begin = 0;
for (; whitespace_begin < string.len; whitespace_begin++) {
if (!u16_is_whitespace(string.str[whitespace_begin])) {
break;
}
}
i64 whitespace_end = string.len;
for (; whitespace_end != whitespace_begin; whitespace_end--) {
if (!u16_is_whitespace(string.str[whitespace_end - 1])) {
break;
}
}
if (whitespace_begin == whitespace_end) {
string.len = 0;
}
else {
string = s16_slice(string, whitespace_begin, whitespace_end);
}
return string;
}
fn s16_t s16_trim_end(s16_t string) {
i64 whitespace_end = string.len;
for (; whitespace_end != 0; whitespace_end--) {
if (!u16_is_whitespace(string.str[whitespace_end - 1])) {
break;
}
}
s16_t result = s16_get_prefix(string, whitespace_end);
return result;
}
fn b32 s16_seek(s16_t string, s16_t find, s16_seek_t flags, int64_t *index_out) {
b32 ignore_case = flags & s16_seek_ignore_case ? true : false;
b32 result = false;
if (flags & s16_seek_match_find_last) {
for (int64_t i = string.len; i != 0; i--) {
int64_t index = i - 1;
s16_t substring = s16_slice(string, index, index + find.len);
if (s16_are_equal_ex(substring, find, ignore_case)) {
if (index_out)
*index_out = index;
result = true;
break;
}
}
}
else {
for (int64_t i = 0; i < string.len; i++) {
s16_t substring = s16_slice(string, i, i + find.len);
if (s16_are_equal_ex(substring, find, ignore_case)) {
if (index_out)
*index_out = i;
result = true;
break;
}
}
}
return result;
}
fn int64_t s16_find(s16_t string, s16_t find, s16_seek_t flag) {
int64_t result = -1;
s16_seek(string, find, flag, &result);
return result;
}
fn s16_t s16_chop_last_char(s16_t s, s16_t ch) {
s16_t result = s;
s16_seek(s, ch, s16_seek_match_find_last, &result.len);
return result;
}
fn s16_t s16_chop_last_slash(s16_t s) {
return s16_chop_last_char(s, s16_lit("/"));
}
fn s16_t s16_chop_last_period(s16_t s) {
return s16_chop_last_char(s, s16_lit("."));
}
fn s16_t s16_skip_to_last_char(s16_t s, s16_t ch) {
int64_t pos;
s16_t result = s;
if (s16_seek(s, ch, s16_seek_match_find_last, &pos)) {
result = s16_skip(result, pos + 1);
}
return result;
}
fn s16_t s16_skip_to_last_slash(s16_t s) {
return s16_skip_to_last_char(s, s16_lit("/"));
}
fn s16_t s16_skip_to_last_period(s16_t s) {
return s16_skip_to_last_char(s, s16_lit("."));
}
fn s16_t s16_get_name_no_ext(s16_t s) {
return s16_skip_to_last_slash(s16_chop_last_period(s));
}
fn s16_t s16_to_lower_case(ma_arena_t *ma, s16_t s) {
s16_t copy = s16_copy(ma, s);
for (int64_t i = 0; i < copy.len; i++) {
copy.str[i] = u16_to_lower_case(copy.str[i]);
}
return copy;
}
fn s16_t s16_to_upper_case(ma_arena_t *ma, s16_t s) {
s16_t copy = s16_copy(ma, s);
for (int64_t i = 0; i < copy.len; i++) {
copy.str[i] = u16_to_upper_case(copy.str[i]);
}
return copy;
}
fn s16_t s16_printf(ma_arena_t *ma, const char *str, ...) {
ma_temp_t scratch = ma_begin_scratch1(ma);
S8_FMT(scratch.arena, str, result);
s16_t result16 = s16_from_s8(ma, result);
ma_end_scratch(scratch);
return result16;
}
fn u64 u64_from_s16(s16_t s, u64 base) {
assert(base >= 2 && base <= 16);
u64 acc = 0;
for (i64 i = 0; i < s.len; i++) {
u64 num = u64_from_hexchar((char)s.str[i]);
assert(num < base);
acc *= base;
acc += num;
}
return acc;
}
fn f64 f64_from_s16(s16_t string) {
ma_temp_t scratch = ma_begin_scratch();
s8_t num_string = s8_from_s16(scratch.arena, string);
f64 result = os_parse_float(num_string.str);
ma_end_scratch(scratch);
return result;
}
gb_read_only i64 s16_fuzzy_closer_word_begin = 5;
gb_read_only i64 s16_fuzzy_consecutive_multiplier = 3;
fn i64 s16_fuzzy_rate(s16_t string, s16_t with) {
if (with.len == 0) return 0;
i64 points = 0;
i64 consecutive = 0;
i64 with_i = 0;
for (i64 i = 0; i < string.len; i++) {
if (string.str[i] == with.str[with_i]) {
i64 closer_begin = CLAMP_BOT((i64)0, s16_fuzzy_closer_word_begin - i);
points += closer_begin;
consecutive++;
with_i += 1;
} else {
points += consecutive * s16_fuzzy_consecutive_multiplier;
consecutive = 0;
with_i = 0;
}
if (with_i >= with.len) with_i = 0;
}
points += consecutive * s16_fuzzy_consecutive_multiplier;
return points;
}
fn fuzzy_pair_t *s16_fuzzy_rate_array(ma_arena_t *arena, s16_t needle, s16_t *array, i32 len) {
fuzzy_pair_t *pairs = ma_push_array(arena, fuzzy_pair_t, len);
for (i32 i = 0; i < len; i += 1) {
pairs[i].rating = s16_fuzzy_rate(array[i], needle);
pairs[i].index = i;
}
for (i32 i = 0; i < len - 1; i++) {
for (i32 j = 0; j < len - 1; j++) {
if (pairs[j].rating < pairs[j + 1].rating) {
SWAP(fuzzy_pair_t, pairs[j], pairs[j + 1]);
}
}
}
return pairs;
}
fn sb16_node_t *sb16_create_node(ma_arena_t *ma, s16_t str) {
sb16_node_t *node = ma_push_type(ma, sb16_node_t);
node->string = str;
return node;
}
fn sb16_node_t *sb16_append(sb16_t *list, s16_t string) {
assert(list->arena != NULL);
sb16_node_t *node = sb16_create_node(list->arena, string);
SLLQ_APPEND(list->first, list->last, node);
return node;
}
fn s16_t sb16_printf(sb16_t *sb, const char *str, ...) {
ma_temp_t scratch = ma_begin_scratch1(sb->arena);
S8_FMT(scratch.arena, str, result);
s16_t result16 = s16_from_s8(sb->arena, result);
sb16_append(sb, result16);
ma_end_scratch(scratch);
return result16;
}
fn void sb16_indent(sb16_t *sb) {
sb16_printf(sb, "\n%.*s", sb->indent*4, " ");
}
fn s16_t sb16_stmtf(sb16_t *sb, const char *str, ...) {
ma_temp_t scratch = ma_begin_scratch1(sb->arena);
S8_FMT(scratch.arena, str, result);
s16_t result16 = s16_from_s8(sb->arena, result);
sb16_indent(sb);
sb16_append(sb, result16);
ma_end_scratch(scratch);
return result16;
}
fn int64_t sb16_char_size(sb16_t *sb) {
int64_t result = 0;
for (sb16_node_t *it = sb->first; it; it = it->next) {
result += it->len;
}
return result;
}
fn s16_t sb16_merge(ma_arena_t *arena, sb16_t *sb) {
int64_t size = sb16_char_size(sb) + 1;
i64 byte_size = size * sizeof(u16);
u16 *str = ma_push_size(arena, byte_size);
s16_t result = {str, 0};
for (sb16_node_t *it = sb->first; it; it = it->next) {
memory_copy(result.str + result.len, it->str, it->len * sizeof(u16));
result.len += it->len;
}
result.str[result.len] = 0;
return result;
}
fn sb16_t s16_split(ma_arena_t *ma, s16_t string, s16_t find, s16_split_t flags) {
sb16_t result = (sb16_t){ma};
int64_t index = 0;
s16_seek_t find_flag = flags & s16_split_ignore_case ? s16_seek_ignore_case : s16_seek_none;
while (s16_seek(string, find, find_flag, &index)) {
s16_t before_match = s16(string.str, index);
sb16_append(&result, before_match);
if (flags & s16_split_inclusive) {
s16_t match = s16(string.str + index, find.len);
sb16_append(&result, match);
}
string = s16_skip(string, index + find.len);
}
if (string.len) sb16_append(&result, string);
return result;
}
fn_test void test_string16(void) {
ma_temp_t scratch = ma_begin_scratch();
// string16 lit basic tests
{
s16_t a = s16_lit("memes");
s16_t b = s16_lit("not memes");
s16_t c = s16_lit("MEMES");
assert(a.len == 5);
assert(a.str[0] == L'm');
assert(a.str[4] == L's');
assert(s16_are_equal(a, b) == false);
assert(s16_are_equal(a, a) == true);
assert(s16_are_equal_ex(a, c, true) == true);
assert(sizeof(wchar_t) == sizeof(u16));
}
{
assert(u16_to_upper_case('a') == L'A');
assert(u16_to_upper_case('a') == 'A');
assert(u16_to_upper_case(L'a') == 'A');
assert(u16_is_digit('3'));
}
{
s16_t a = s16_from_wstr(L"memes");
assert(a.len == 5);
assert(s16_are_equal(a, s16_lit("memes")) == true);
s16_t b = s16_copy(scratch.arena, a);
assert(a.str != b.str);
assert(b.len == a.len);
assert(s16_are_equal(a, b));
s16_t c = s16_from_range(a.str, a.str + a.len);
assert(s16_are_equal(a, c));
}
{
s16_t a = s16_lit("thing itself");
assert(s16_starts_with_ex(a, s16_lit("thing"), false));
assert(!s16_starts_with_ex(a, s16_lit("thing itself and"), false));
assert(!s16_starts_with_ex(a, s16_lit("thing itself "), false));
assert(s16_starts_with_ex(a, s16_lit("THING"), true));
assert(!s16_starts_with_ex(a, s16_lit("a"), false));
assert(s16_ends_with_ex(a, s16_lit("itself"), false));
assert(s16_ends_with_ex(a, s16_lit("thing itself"), false));
assert(!s16_ends_with_ex(a, s16_lit("thing itselfa"), false));
s16_t b = s16_lit("memes");
assert(s16_is_pointer_inside(b, b.str));
assert(s16_is_pointer_inside(b, b.str + 4));
assert(!s16_is_pointer_inside(b, b.str + 5));
}
{
s16_t a = s16_lit("C:\\Program Files\\Memes");
s16_normalize_path_unsafe(a);
assert(a.str[2] == '/');
}
{
s16_t a = s16_lit(" thing ");
s16_t b = s16_trim(a);
assert(s16_are_equal(b, s16_lit("thing")));
}
{
s16_t a = s16_printf(scratch.arena, "%d", 432);
assert(s16_are_equal(a, s16_lit("432")));
assert(f64_from_s16(s16_lit("432.0")) == 432.0);
assert(u64_from_s16(s16_lit("432"), 10) == 432);
}
{
sb16_t *list = sb16_serial_begin(scratch.arena);
sb16_printf(list, "%d ", 987);
sb16_printf(list, "ter ");
sb16_printf(list, "|");
s16_t string = sb16_serial_end(scratch.arena, list);
assert(s16_are_equal(string, s16_lit("987 ter |")));
}
{
s16_t a = s16_lit("A|B|dek|mek|vek|");
sb16_t b = s16_split(scratch.arena, a, s16_lit("|"), s16_split_none);
assert(s16_are_equal(b.first->string, s16_lit("A")));
assert(s16_are_equal(b.first->next->string, s16_lit("B")));
assert(s16_are_equal(b.first->next->next->string, s16_lit("dek")));
assert(s16_are_equal(b.first->next->next->next->string, s16_lit("mek")));
assert(s16_are_equal(b.first->next->next->next->next->string, s16_lit("vek")));
assert(b.first->next->next->next->next->next == NULL);
}
{
s16_t a = s16_to_upper_case(scratch.arena, s16_lit("thing Meme"));
assert(s16_are_equal(a, s16_lit("THING MEME")));
a = s16_to_lower_case(scratch.arena, s16_lit("THING Meme"));
assert(s16_are_equal(a, s16_lit("thing meme")));
}
{
s16_t a = s16_lit("C:/thing/itself");
assert(s16_are_equal(s16_chop_last_slash(a), s16_lit("C:/thing")));
}
ma_end_scratch(scratch);
}

View File

@@ -0,0 +1,114 @@
typedef struct s16_t s16_t;
struct s16_t {
u16 *str;
i64 len;
};
typedef struct sb16_node_t sb16_node_t;
struct sb16_node_t {
sb16_node_t *next;
union {
struct { u16 *str; int64_t len; };
s16_t string;
};
};
typedef struct sb16_t sb16_t;
struct sb16_t {
ma_arena_t *arena;
sb16_node_t *first;
sb16_node_t *last;
// WARNING: remember to update typeinfo after editing this
i32 indent;
};
typedef i32 s16_seek_t;
enum {
s16_seek_none = 0,
s16_seek_ignore_case = 1,
s16_seek_match_find_last = 2,
};
typedef i32 s16_split_t;
enum {
s16_split_none = 0,
s16_split_ignore_case = 1,
s16_split_inclusive = 2,
};
enum { s16_ignore_case = 1 };
typedef struct s32_t s32_t;
struct s32_t {
u32 *str;
i64 len;
};
#define s16(str,len) (s16_t){str, len}
#define s16_lit(str) (s16_t){L##str, sizeof(L##str) / sizeof(u16) - 1}
#define s16_invalid s16_lit("<INVALID>")
#define sb16(ARENA) &(sb16_t){.arena = arena}
#define sb16_serial_begin(ARENA) &(sb16_t){.arena = ARENA}
#define sb16_serial_end(ARENA, SB) sb16_merge(ARENA, SB)
fn i64 wstr_len(wchar_t *string);
fn u16 u16_to_lower_case(u16 a);
fn u16 u16_to_upper_case(u16 a);
fn b32 u16_is_whitespace(u16 w);
fn b32 u16_is_alphabetic(u16 a);
fn b32 u16_is_ident(u16 a);
fn b32 u16_is_digit(u16 a);
fn b32 u16_is_alphanumeric(u16 a);
fn s16_t s16_from_range(u16 *begin, u16 *end);
fn s16_t s16_from_u16(u16 *string);
fn s16_t s16_from_wstr(wchar_t *string);
fn s16_t s16_copy(ma_arena_t *ma, s16_t string);
fn s16_t s16_copy_u16(ma_arena_t *ma, u16 *s);
fn s16_t s16_copy_wstr(ma_arena_t *ma, wchar_t *s);
fn b32 s16_are_equal_ex(s16_t a, s16_t b, b32 ignore_case);
fn b32 s16_are_equal(s16_t a, s16_t b);
fn s16_t s16_from_s8(ma_arena_t *ma, s8_t string);
fn s8_t s8_from_s16(ma_arena_t *ma, s16_t string);
fn s16_t s16_get_postfix(s16_t string, i64 len);
fn s16_t s16_get_prefix(s16_t string, i64 len);
fn s16_t s16_chop(s16_t string, i64 len);
fn s16_t s16_skip(s16_t string, i64 len);
fn b32 s16_ends_with_ex(s16_t a, s16_t end, b32 ignore_case);
fn b32 s16_starts_with_ex(s16_t a, s16_t start, b32 ignore_case);
fn b32 s16_ends_with(s16_t a, s16_t end);
fn b32 s16_starts_with(s16_t a, s16_t start);
fn void s16_normalize_path_unsafe(s16_t s);
fn s16_t s16_normalize_path(ma_arena_t *ma, s16_t s);
fn b32 s16_is_pointer_inside(s16_t string, u16 *p);
fn s16_t s16_cut_start(s16_t *in, i64 size);
fn s16_t s16_cut_end(s16_t *in, i64 size);
fn s16_t s16_slice(s16_t string, i64 first_index, i64 one_past_last_index);
fn s16_t s16_trim(s16_t string);
fn s16_t s16_trim_end(s16_t string);
fn b32 s16_seek(s16_t string, s16_t find, s16_seek_t flags, int64_t *index_out);
fn int64_t s16_find(s16_t string, s16_t find, s16_seek_t flag);
fn s16_t s16_chop_last_char(s16_t s, s16_t ch);
fn s16_t s16_chop_last_slash(s16_t s);
fn s16_t s16_chop_last_period(s16_t s);
fn s16_t s16_skip_to_last_char(s16_t s, s16_t ch);
fn s16_t s16_skip_to_last_slash(s16_t s);
fn s16_t s16_skip_to_last_period(s16_t s);
fn s16_t s16_get_name_no_ext(s16_t s);
fn s16_t s16_to_lower_case(ma_arena_t *ma, s16_t s);
fn s16_t s16_to_upper_case(ma_arena_t *ma, s16_t s);
fn s16_t s16_printf(ma_arena_t *ma, const char *str, ...);
fn u64 u64_from_s16(s16_t s, u64 base);
fn f64 f64_from_s16(s16_t string);
fn i64 s16_fuzzy_rate(s16_t string, s16_t with);
fn fuzzy_pair_t *s16_fuzzy_rate_array(ma_arena_t *arena, s16_t needle, s16_t *array, i32 len);
fn sb16_node_t *sb16_create_node(ma_arena_t *ma, s16_t str);
fn sb16_node_t *sb16_append(sb16_t *list, s16_t string);
fn s16_t sb16_printf(sb16_t *sb, const char *str, ...);
fn void sb16_indent(sb16_t *sb);
fn s16_t sb16_stmtf(sb16_t *sb, const char *str, ...);
fn int64_t sb16_char_size(sb16_t *sb);
fn s16_t sb16_merge(ma_arena_t *arena, sb16_t *sb);
fn sb16_t s16_split(ma_arena_t *ma, s16_t string, s16_t find, s16_split_t flags);

View File

@@ -48,7 +48,7 @@ fn mt_file_t *mt_find_file_exact(mt_files_t *root, s8_t path) {
fn mt_file_t *mt_find_file(mt_files_t *root, s8_t name) { fn mt_file_t *mt_find_file(mt_files_t *root, s8_t name) {
for (mt_file_t *it = root->first; it; it = it->next) { for (mt_file_t *it = root->first; it; it = it->next) {
if (s8_ends_with(name, it->path, false)) return it; if (s8_ends_with(name, it->path)) return it;
} }
return NULL; return NULL;
} }

View File

@@ -1,4 +1,5 @@
fn void run_tests(void) { fn void run_tests(void) {
test_string16();
test_hash_table(); test_hash_table();
test_intern_table(); test_intern_table();
} }

View File

@@ -7,6 +7,7 @@ gb_read_only mt_tweak_t tweak_table[] = {
}; };
void run_all_tests(void) { void run_all_tests(void) {
test_string16();
test_hash_table(); test_hash_table();
test_intern_table(); test_intern_table();
ui_test_text_replace(); ui_test_text_replace();

View File

@@ -55,12 +55,12 @@ fn void mt_ui_stacks(ma_arena_t *arena, sb8_t *c, sb8_t *h) {
// create `stack` and `node` columns // create `stack` and `node` columns
for (ast_t *it = table->first; it; it = it->next) { for (ast_t *it = table->first; it; it = it->next) {
s8_t type = mtts(it, "type"); s8_t type = mtts(it, "type");
if (s8_ends_with(type, s8_lit("_t"), false)) { if (s8_ends_with(type, s8_lit("_t"))) {
type = s8_chop(type, 2); type = s8_chop(type, 2);
} }
s8_t ui_type = type; s8_t ui_type = type;
if (!s8_starts_with(ui_type, s8_lit("ui_"), false)) { if (!s8_starts_with(ui_type, s8_lit("ui_"))) {
ui_type = s8_printf(arena, "ui_%S", ui_type); ui_type = s8_printf(arena, "ui_%S", ui_type);
} }
@@ -136,7 +136,7 @@ fn void mt_ui_stacks(ma_arena_t *arena, sb8_t *c, sb8_t *h) {
sb8_stmtf(c, "fn void ui_box_fill_with_colors(ui_box_t *box) {"); sb8_stmtf(c, "fn void ui_box_fill_with_colors(ui_box_t *box) {");
for (ast_t *it = table->first; it; it = it->next) { for (ast_t *it = table->first; it; it = it->next) {
if (!s8_ends_with(mtts(it, "name"), s8_lit("_color"), false)) { if (!s8_ends_with(mtts(it, "name"), s8_lit("_color"))) {
continue; continue;
} }
mt_stmtf(c, it, "box->@name = ui_top_@name();"); mt_stmtf(c, it, "box->@name = ui_top_@name();");

View File

@@ -7,6 +7,7 @@ gb_read_only mt_tweak_t tweak_table[] = {
}; };
void run_all_tests(void) { void run_all_tests(void) {
test_string16();
test_hash_table(); test_hash_table();
test_intern_table(); test_intern_table();
ui_test_text_replace(); ui_test_text_replace();