Files
corelang/common.c
2022-05-06 10:13:16 +02:00

198 lines
4.3 KiB
C

function S64
clamp_top_s64(S64 val, S64 max){
if(val>max)return max;
return val;
}
function SizeU
clamp_top_sizeu(SizeU val, SizeU max){
if(val>max)return max;
return val;
}
function SizeU
get_align_offset(SizeU size, SizeU align){
SizeU mask = align - 1;
SizeU val = size & mask;
if(val){
val = align - val;
}
return val;
}
function SizeU
align_up(SizeU size, SizeU align){
SizeU result = size + get_align_offset(size, align);
return result;
}
function U64
hash_fnv(String string) {
U64 hash = (U64)14695981039346656037ULL;
for (U64 i = 0; i < string.len; i++) {
hash = hash ^ (U64)(string.str[i]);
hash = hash * (U64)1099511628211ULL;
}
return hash;
}
function U64
is_pow2(U64 x) {
assert(x != 0);
B32 result = (x & (x - 1llu)) == 0;
return result;
}
function U64
wrap_around_pow2(U64 x, U64 power_of_2) {
assert(is_pow2(power_of_2));
U64 r = (((x)&((power_of_2)-1llu)));
return r;
}
//-----------------------------------------------------------------------------
// Strings
//-----------------------------------------------------------------------------
global String string_empty;
function B32
string_compare(String a, String b){
if(a.len != b.len)
return false;
for(S64 i = 0; i < a.len; i++){
if(a.str[i] != b.str[i])
return false;
}
return true;
}
function U8
char_to_lower(U8 c){
if(c >= 'A' && c <= 'Z')
c += 32;
return c;
}
function U8
char_to_upper(U8 c){
if(c >= 'a' && c <= 'z')
c -= 32;
return c;
}
function B32
string_is_empty(String a){
B32 result = a.len == 0;
return result;
}
function String
string_to_lower(Arena *arena, String string){
String result = arena_push_string_copy(arena, string);
for(S64 i = 0; i < string.len; i++){
result.str[i] = char_to_lower(result.str[i]);
}
return result;
}
//-----------------------------------------------------------------------------
// String interning
//-----------------------------------------------------------------------------
typedef struct Table_Index{
U64 hash;
U64 index;
U64 iter;
U64 max_size;
}Table_Index;
typedef struct Intern_String{
String s;
}Intern_String;
typedef struct Intern_Table{
S64 interns_in_bytes;
S64 interns_inserted;
S64 interns_max;
Intern_String *interns;
Arena *arena;
}Intern_Table;
function Intern_Table
intern_table(Arena *arena, SizeU size){
Intern_Table result = {0};
result.arena = arena;
result.interns = arena_push_array(arena, Intern_String, size);
result.interns_max = size;
return result;
}
function Table_Index
table_index_from_hash(U64 hash, U64 max_size){
Table_Index result = {0};
result.hash = hash;
result.index = result.hash % max_size;
result.iter = result.index;
result.max_size = max_size;
return result;
}
function Table_Index
table_index_from_string(String string, U64 max_size){
U64 hash = hash_fnv(string);
Table_Index result = table_index_from_hash(hash, max_size);
return result;
}
function B32
table_index_advance(Table_Index *index){
index->iter = wrap_around_pow2(index->iter + 1, index->max_size);
B32 result = index->iter == index->index;
return result;
}
function Intern_String
intern_string(Intern_Table *p, String string){
Intern_String result = {0};
Table_Index index = table_index_from_string(string, p->interns_max);
for(;;){
Intern_String *intern = p->interns + index.iter;
if(intern->s.str == 0){
result.s = arena_push_string_copy(p->arena, string);
p->interns_in_bytes += string.len;
p->interns_inserted += 1;
*intern = result;
break;
}
else if(string_compare(intern->s, string)){
result = *intern;
break;
}
if (table_index_advance(&index))
break;
}
return result;
}
function B32
intern_compare(Intern_String a, Intern_String b){
B32 result = a.s.str == b.s.str;
return result;
}
function void
intern_test(){
Arena *scratch = arena_begin_scratch();
Intern_Table table = intern_table(scratch, 512);
assert(intern_compare(intern_string(&table, lit("Thing")),
intern_string(&table, lit("Thing"))));
assert(!intern_compare(intern_string(&table, lit("Thing")),
intern_string(&table, lit("No_Thing"))));
assert(intern_compare(intern_string(&table, lit("No_Thing")),
intern_string(&table, lit("No_Thing"))));
}