[map] overhaul the maps, fewer parts, fewer paths, fewer knobs; same great results

This commit is contained in:
Allen Webster
2021-06-06 20:15:48 -07:00
parent d390326e17
commit fb999476fa
9 changed files with 274 additions and 335 deletions
+80 -18
View File
@@ -311,22 +311,20 @@ main:
//~ String-To-Node table
@send(Map)
@doc("Controls the behavior of routines that write into maps when the written key was already in the map.")
@see(MD_Map)
@see(MD_StringMap_Insert)
@see(MD_PtrMap_Insert)
@enum MD_MapCollisionRule: {
@doc("When the key written was already in the map, a new key value pair is attached to the same chain always. Leaving multiple values associated to the same key.")
Chain,
@doc("When the key written was already in the map, the existing value is replaced with the newly inserted value.")
Overwrite,
}
@doc("An abstraction over the types of keys used in a MD_Map and the work of hashing those keys, can be constructed from an MD_String8 or an void*.")
@struct MD_MapKey: {
@doc("The hash of the key. The hash function used is determined from the key type.")
hash: MD_u64,
@doc("For a non-empty MD_String8, the size of the string data. For a void*, zero.")
size: MD_u64,
@doc("For a non-empty MD_String8, points to the string data of the key. For a void*, the direct pointer value.")
ptr: *void,
};
@send(Map)
@doc("A slot containing one (key,value) pair in a MD_Map.")
@see(MD_Map)
@struct MD_MapSlot: {
@doc("The next slot in the same bucket of the MD_Map")
@doc("The next slot in the same bucket of the MD_Map.")
next: *MD_MapSlot,
@doc("For slots with a string key, the hash of the key.")
hash: MD_u64,
@@ -828,12 +826,6 @@ main:
return: MD_f64,
};
@send(Strings)
@func MD_HashString: {
string: MD_String8,
return: MD_u64,
};
@send(Strings)
@func MD_CalculateCStringLength: {
cstr: *char,
@@ -918,9 +910,79 @@ main:
return: MD_String32,
};
////////////////////////////////
//~ Map Table Data Structure
@send(Map)
@func MD_HashString: {
string: MD_String8,
return: MD_u64,
};
@send(Map)
@func MD_HashPointer: {
p: *void,
};
@send(Map)
MD_MapMakeBucketCount: {
bucket_count: MD_u64,
return: MD_Map,
};
@send(Map)
MD_MapMake: {
return: MD_Map,
};
@send(Map)
MD_MapKeyStr: {
string: MD_String8,
return: MD_MapKey,
};
@send(Map)
MD_MapKeyPtr: {
ptr: *void,
return: MD_MapKey,
};
@send(Map)
MD_MapLookup: {
map: *MD_Map,
key: MD_MapKey,
return: *MD_MapSlot,
};
@send(Map)
MD_MapScan: {
first_slot: *MD_MapSlot,
key: MD_MapKey,
return: *MD_MapSlot,
};
@send(Map)
MD_MapInsert: {
map: *MD_Map,
key: MD_MapKey,
val: *void,
return: *MD_MapSlot,
};
@send(Map)
MD_MapOverwrite: {
map: *MD_Map,
key: MD_MapKey,
val: *void,
return: *MD_MapSlot,
};
////////////////////////////////
//~ String-To-Pointer Table
// TODO(allen): update reference for map
@send(Map)
@func MD_StringMap_Lookup: {
table: *MD_Map,
+17 -17
View File
@@ -6,10 +6,10 @@
static MD_Map MapFromChildren(MD_Node *node)
{
MD_Map result = {0};
MD_Map result = MD_MapMake();
for(MD_EachNodeRef(child, node->first_child))
{
MD_StringMap_Insert(&result, MD_MapCollisionRule_Chain, child->string, child);
MD_MapInsert(&result, MD_MapKeyStr(child->string), child);
}
return result;
}
@@ -23,7 +23,7 @@ OutputType_C_LHS_Namespace(FILE *file, MD_Map *user_defined_types, MD_String8 pr
{
MD_Node *node = type->node;
if(MD_StringMap_Lookup(user_defined_types, type->node->string))
if(MD_MapLookup(user_defined_types, MD_MapKeyStr(node->string)))
{
fprintf(file, "%.*s", MD_StringExpand(prefix));
}
@@ -156,10 +156,10 @@ static void AppendConversionCode(FILE *f, MD_Map *user_defined_types, MD_Node *n
for(MD_EachNode(member, old_element->first_child))
{
MD_MapSlot *slot = MD_StringMap_Lookup(&new_element_map, member->string);
MD_MapSlot *slot = MD_MapLookup(&new_element_map, MD_MapKeyStr(member->string));
if(slot)
{
AppendConversionCode(f, user_defined_types, member, slot->value, extended_member_path);
AppendConversionCode(f, user_defined_types, member, slot->val, extended_member_path);
}
else
{
@@ -177,7 +177,7 @@ static void AppendConversionCode(FILE *f, MD_Map *user_defined_types, MD_Node *n
MD_String8 extended_member_path = MD_PushStringF("%.*s.%.*s", MD_StringExpand(member_path),
MD_StringExpand(old_element->string));
if(MD_StringMap_Lookup(user_defined_types, type_name))
if(MD_MapLookup(user_defined_types, MD_MapKeyStr(type_name)))
{
fprintf(f, " result%.*s = %.*sFromV1(v%.*s);\n",
MD_StringExpand(extended_member_path), MD_StringExpand(type_name),
@@ -236,7 +236,7 @@ int main(int argument_count, char **arguments)
// NOTE(mal): Old types get "v1_" as a prefix
fprintf(f, "// V1\n");
MD_Node *v1 = MD_StringMap_Lookup(&ns_map, MD_S8Lit("v1"))->value;
MD_Node *v1 = MD_MapLookup(&ns_map, MD_MapKeyStr(MD_S8Lit("v1")))->val;
MD_Map v1_map = MapFromChildren(v1);
for(MD_EachNodeRef(node, v1->first_child))
{
@@ -247,7 +247,7 @@ int main(int argument_count, char **arguments)
fprintf(f, "// V2\n");
MD_Map empty_map = {0};
MD_Node *v2 = MD_StringMap_Lookup(&ns_map, MD_S8Lit("v2"))->value;
MD_Node *v2 = MD_MapLookup(&ns_map, MD_MapKeyStr(MD_S8Lit("v2")))->val;
for(MD_EachNodeRef(node, v2->first_child))
{
OutputPrefixedType(f, &empty_map, MD_S8Lit(""), node, 0);
@@ -258,8 +258,8 @@ int main(int argument_count, char **arguments)
MD_Map v2_map = MapFromChildren(v2);
for(MD_EachNodeRef(node, v1->first_child))
{
MD_MapSlot *slot = MD_StringMap_Lookup(&v2_map, node->string);
MD_Node *v2_type = slot->value;
MD_MapSlot *slot = MD_MapLookup(&v2_map, MD_MapKeyStr(node->string));
MD_Node *v2_type = slot->val;
MD_Map children_map = MapFromChildren(v2_type);
fprintf(f, "static %.*s %.*sFromV1(v1_%.*s v)\n{\n",
@@ -274,10 +274,10 @@ int main(int argument_count, char **arguments)
{
fprintf(f, " case v1_%.*s_%.*s: ",
MD_StringExpand(node->string), MD_StringExpand(enumerand->string));
MD_MapSlot *slot = MD_StringMap_Lookup(&children_map, enumerand->string);
MD_MapSlot *slot = MD_MapLookup(&children_map, MD_MapKeyStr(enumerand->string));
if(slot)
{
MD_Node *v2_enumerand = slot->value;
MD_Node *v2_enumerand = slot->val;
fprintf(f, "result = %.*s_%.*s; break;\n",
MD_StringExpand(node->string), MD_StringExpand(v2_enumerand->string));
}
@@ -305,7 +305,7 @@ int main(int argument_count, char **arguments)
{
fprintf(f, " if(v & v1_%.*s_%.*s) ",
MD_StringExpand(singular_flag_type_name), MD_StringExpand(flag->string));
MD_MapSlot *slot = MD_StringMap_Lookup(&children_map, flag->string);
MD_MapSlot *slot = MD_MapLookup(&children_map, MD_MapKeyStr(flag->string));
if(slot)
{
fprintf(f, "result |= %.*s_%.*s;\n",
@@ -332,10 +332,10 @@ int main(int argument_count, char **arguments)
}
MD_Map v1_children_map = MapFromChildren(node);
MD_MapSlot *v1_member_slot = MD_StringMap_Lookup(&v1_children_map, authoritative_member->string);
MD_MapSlot *v1_member_slot = MD_MapLookup(&v1_children_map, MD_MapKeyStr(authoritative_member->string));
if(v1_member_slot)
{
AppendConversionCode(f, &v2_map, authoritative_member, v1_member_slot->value, MD_S8Lit(""));
AppendConversionCode(f, &v2_map, authoritative_member, v1_member_slot->val, MD_S8Lit(""));
}
else
{
@@ -348,10 +348,10 @@ int main(int argument_count, char **arguments)
MD_Map v1_children_map = MapFromChildren(node);
for(MD_EachNode(member, v2_type->first_child))
{
MD_MapSlot *v1_member_slot = MD_StringMap_Lookup(&v1_children_map, member->string);
MD_MapSlot *v1_member_slot = MD_MapLookup(&v1_children_map, MD_MapKeyStr(member->string));
if(v1_member_slot)
{
AppendConversionCode(f, &v2_map, member, v1_member_slot->value, MD_S8Lit(""));
AppendConversionCode(f, &v2_map, member, v1_member_slot->val, MD_S8Lit(""));
}
else
{
@@ -25,36 +25,6 @@
</div>
<div class="page_content">
<h1 class="title">Blog</h1><input autofocus id="lister_search_0" class="lister_search" oninput="SearchInput(event, 0)" onkeydown="SearchKeyDown(event, 0)" placeholder="Filter..."></input><ul id="lister_0" class="lister">
<a class="lister_item_link" href="blog1.html">
<li class="lister_item">
<div class="lister_item_text">
<div class="lister_item_title">
Test Blog #1
</div>
<div class="lister_item_date">
30 November 2020
</div>
<div class="lister_item_desc">
This is my test blog.
</div>
</div>
</a>
</li>
<a class="lister_item_link" href="blog2.html">
<li class="lister_item">
<div class="lister_item_text">
<div class="lister_item_title">
Hello, Again!
</div>
<div class="lister_item_date">
28 November 2020
</div>
<div class="lister_item_desc">
This is another test blog.
</div>
</div>
</a>
</li>
</ul>
</div>
@@ -92,7 +92,7 @@ int main(int argument_count, char **arguments)
{
for(MD_EachNode(index_string, node->first_child))
{
MD_StringMap_Insert(&index_table, MD_MapCollisionRule_Chain, index_string->string, root);
MD_MapInsert(&index_table, MD_MapKeyStr(index_string->string), root);
}
goto end_index_build;
}
@@ -515,14 +515,15 @@ GeneratePageContent(MD_Map *index_table, SiteInfo *site_info, PageInfo *page_inf
MD_Node *index_string = 0;
for(MD_u64 idx = 0; !MD_NodeIsNil(index_string = MD_ChildFromIndex(node, idx)); idx += 1)
{
for(MD_MapSlot *slot = MD_StringMap_Lookup(index_table, index_string->string);
for(MD_MapSlot *slot = MD_MapLookup(index_table, MD_MapKeyStr(index_string->string));
slot; slot = slot->next)
{
if(slot->value)
if(slot->val)
{
PageInfo info = ParsePageInfo((MD_Node *)slot->value);
MD_Node *node = slot->val;
PageInfo info = ParsePageInfo(node);
MD_String8 filename = ((MD_Node *)slot->value)->filename;
MD_String8 filename = node->filename;
MD_String8 filename_no_ext = MD_ChopExtension(MD_SkipFolder(filename));
MD_String8 link = MD_PushStringF("%.*s.html", MD_StringExpand(filename_no_ext));
MD_String8 name = info.title->string;
+4 -4
View File
@@ -49,7 +49,7 @@ InsertValueToNamespace(NamespaceNode *ns, MD_String8 string, Value v)
{
Value *v_store = malloc(sizeof(*v_store));
*v_store = v;
MD_StringMap_Insert(&ns->symbol_map, MD_MapCollisionRule_Overwrite, string, v_store);
MD_MapInsert(&ns->symbol_map, MD_MapKeyStr(string), v_store);
}
static Value
@@ -58,10 +58,10 @@ ValueFromString(NamespaceNode *ns, MD_String8 string)
Value v = {0};
for(NamespaceNode *n = ns; n; n = n->parent)
{
MD_MapSlot *slot = MD_StringMap_Lookup(&n->symbol_map, string);
if(slot && slot->value)
MD_MapSlot *slot = MD_MapLookup(&n->symbol_map, MD_MapKeyStr(string));
if(slot && slot->val)
{
v = *(Value *)slot->value;
v = *(Value *)slot->val;
break;
}
}
+17 -30
View File
@@ -382,20 +382,20 @@ struct MD_CodeLoc
//~ String-To-Ptr and Ptr-To-Ptr tables
typedef enum MD_MapCollisionRule
typedef struct MD_MapKey MD_MapKey;
struct MD_MapKey
{
MD_MapCollisionRule_Chain,
MD_MapCollisionRule_Overwrite,
}
MD_MapCollisionRule;
MD_u64 hash;
MD_u64 size;
void *ptr;
};
typedef struct MD_MapSlot MD_MapSlot;
struct MD_MapSlot
{
MD_MapSlot *next;
MD_u64 hash;
void *key;
void *value;
MD_MapKey key;
void *val;
};
typedef struct MD_Map MD_Map;
@@ -627,7 +627,6 @@ MD_FUNCTION MD_String8List MD_SplitString(MD_String8 string, int split_count, MD
MD_FUNCTION MD_String8 MD_JoinStringList(MD_String8List list, MD_String8 separator);
MD_FUNCTION MD_i64 MD_I64FromString(MD_String8 string, MD_u32 radix);
MD_FUNCTION MD_f64 MD_F64FromString(MD_String8 string);
MD_FUNCTION MD_u64 MD_HashString(MD_String8 string);
MD_FUNCTION MD_u64 MD_CalculateCStringLength(char *cstr);
MD_FUNCTION MD_String8 MD_StyledStringFromString(MD_String8 string, MD_WordStyle word_style, MD_String8 separator);
@@ -646,30 +645,18 @@ MD_FUNCTION MD_String16 MD_S16FromS8(MD_String8 str);
MD_FUNCTION MD_String8 MD_S8FromS32(MD_String32 str);
MD_FUNCTION MD_String32 MD_S32FromS8(MD_String8 str);
//~ Allen's Map Proposoal
#if 0
MD_FUNCTION void MD_MapInit(MD_Map *map);
MD_FUNCTION MD_MapSlot* MD_MapLookupString(MD_Map *map, MD_String8 key);
MD_FUNCTION MD_MapSlot* MD_MapLookupPtr(MD_Map *map, void *key);
MD_FUNCTION MD_b32 MD_MapInsertString(MD_Map *map, MD_String8 key, void *val);
MD_FUNCTION MD_b32 MD_MapInsertPtr(MD_Map *map, void *key, void *val);
MD_FUNCTION MD_MapSlot* MD_MapNextString(MD_MapSlot *slot, MD_String8 key);
MD_FUNCTION MD_MapSlot* MD_MapNextPtr(MD_MapSlot *slot, void *key);
#endif
//~ Map Table Data Structure
MD_FUNCTION MD_u64 MD_HashString(MD_String8 string);
MD_FUNCTION MD_u64 MD_HashPointer(void *p);
//- String-To-Pointer Table
MD_FUNCTION MD_MapSlot * MD_StringMap_Lookup(MD_Map *table, MD_String8 string);
MD_FUNCTION MD_b32 MD_StringMap_Insert(MD_Map *table, MD_MapCollisionRule collision_rule, MD_String8 string, void *value);
MD_FUNCTION MD_MapSlot * MD_StringMap_Next(MD_MapSlot *slot, MD_String8 key);
//- Pointer-To-Pointer Table
MD_FUNCTION MD_MapSlot *MD_PtrMap_Lookup(MD_Map *map, void *key);
MD_FUNCTION MD_b32 MD_PtrMap_Insert(MD_Map *map, MD_MapCollisionRule collision_rule, void *key, void *value);
MD_FUNCTION MD_Map MD_MapMakeBucketCount(MD_u64 bucket_count);
MD_FUNCTION MD_Map MD_MapMake(void);
MD_FUNCTION MD_MapKey MD_MapKeyStr(MD_String8 string);
MD_FUNCTION MD_MapKey MD_MapKeyPtr(void *ptr);
MD_FUNCTION MD_MapSlot* MD_MapLookup(MD_Map *map, MD_MapKey key);
MD_FUNCTION MD_MapSlot* MD_MapScan(MD_MapSlot *first_slot, MD_MapKey key);
MD_FUNCTION MD_MapSlot* MD_MapInsert(MD_Map *map, MD_MapKey key, void *val);
MD_FUNCTION MD_MapSlot* MD_MapOverwrite(MD_Map *map, MD_MapKey key, void *val);
//~ Parsing
+112 -176
View File
@@ -489,17 +489,6 @@ MD_F64FromString(MD_String8 string)
return(atof(str));
}
MD_FUNCTION_IMPL MD_u64
MD_HashString(MD_String8 string)
{
MD_u64 result = 5381;
for(MD_u64 i = 0; i < string.size; i += 1)
{
result = ((result << 5) + result) + string.str[i];
}
return result;
}
MD_FUNCTION_IMPL MD_u64
MD_CalculateCStringLength(char *cstr)
{
@@ -926,14 +915,15 @@ MD_S32FromS8(MD_String8 in)
//~ Map Table Data Structure
MD_PRIVATE_FUNCTION_IMPL void
_MD_Map_Initialize(MD_Map *map)
MD_FUNCTION_IMPL MD_u64
MD_HashString(MD_String8 string)
{
if(map->table_size == 0)
MD_u64 result = 5381;
for(MD_u64 i = 0; i < string.size; i += 1)
{
map->table_size = 4096;
map->table = MD_PushArray(MD_MapSlot *, map->table_size);
result = ((result << 5) + result) + string.str[i];
}
return result;
}
// NOTE(mal): Generic 64-bit hash function (https://nullprogram.com/blog/2018/07/31/)
@@ -948,169 +938,115 @@ MD_HashPointer(void *p)
return h;
}
//- String-To-Pointer Table
MD_FUNCTION_IMPL MD_MapSlot *
MD_StringMap_Lookup(MD_Map *map, MD_String8 string)
{
_MD_Map_Initialize(map);
MD_MapSlot *slot = 0;
MD_u64 hash = MD_HashString(string);
MD_u64 index = hash % map->table_size;
for(MD_MapSlot *candidate = map->table[index]; candidate; candidate = candidate->next)
{
if(candidate->hash == hash && MD_StringMatch(*((MD_String8 *)candidate->key), string, 0))
{
slot = candidate;
break;
}
}
return slot;
MD_FUNCTION_IMPL MD_Map
MD_MapMakeBucketCount(MD_u64 bucket_count){
// TODO(allen): permanent arena? scratch arena? -- would really
// make most sense with a parameter
MD_Map result = {0};
result.table_size = bucket_count;
// TODO(allen): push array zero
result.table = MD_PushArray(MD_MapSlot*, bucket_count);
memset(result.table, 0, sizeof(*result.table)*bucket_count);
return(result);
}
MD_FUNCTION_IMPL MD_b32
MD_StringMap_Insert(MD_Map *map, MD_MapCollisionRule collision_rule, MD_String8 string, void *value)
{
_MD_Map_Initialize(map);
MD_MapSlot *slot = 0;
MD_u64 hash = MD_HashString(string);
MD_u64 index = hash % map->table_size;
for(MD_MapSlot *candidate = map->table[index]; candidate; candidate = candidate->next)
{
if(candidate->hash == hash && MD_StringMatch(*((MD_String8 *)candidate->key), string, 0))
{
slot = candidate;
break;
MD_FUNCTION_IMPL MD_Map
MD_MapMake(void){
MD_Map result = MD_MapMakeBucketCount(4093);
return(result);
}
MD_FUNCTION MD_MapKey
MD_MapKeyStr(MD_String8 string){
MD_MapKey result = {0};
if (string.size != 0){
result.hash = MD_HashString(string);
result.size = string.size;
if (string.size > 0){
result.ptr = string.str;
}
}
if(slot == 0 || (slot != 0 && collision_rule == MD_MapCollisionRule_Chain))
{
slot = MD_PushArray(MD_MapSlot, 1);
if(slot)
{
slot->next = 0;
if(map->table[index])
{
for(MD_MapSlot *old_slot = map->table[index]; old_slot; old_slot = old_slot->next)
{
if(old_slot->next == 0)
{
old_slot->next = slot;
return(result);
}
MD_FUNCTION MD_MapKey
MD_MapKeyPtr(void *ptr){
MD_MapKey result = {0};
if (ptr != 0){
result.hash = MD_HashPointer(ptr);
result.size = 0;
result.ptr = ptr;
}
return(result);
}
MD_FUNCTION_IMPL MD_MapSlot*
MD_MapLookup(MD_Map *map, MD_MapKey key){
MD_MapSlot *result = 0;
if (map->table_size > 0){
MD_u64 index = key.hash%map->table_size;
result = MD_MapScan(map->table[index], key);
}
return(result);
}
MD_FUNCTION_IMPL MD_MapSlot*
MD_MapScan(MD_MapSlot *first_slot, MD_MapKey key){
MD_MapSlot *result = 0;
if (first_slot != 0){
MD_b32 ptr_kind = (key.size == 0);
MD_String8 key_string = MD_S8((MD_u8*)key.ptr, key.size);
for (MD_MapSlot *slot = first_slot;
slot != 0;
slot = slot->next){
if (slot->key.hash == key.hash){
if (ptr_kind){
if (slot->key.size == 0 && slot->key.ptr == key.ptr){
result = slot;
break;
}
}
else{
MD_String8 slot_string = MD_S8((MD_u8*)slot->key.ptr, slot->key.size);
if (MD_StringMatch(slot_string, key_string, 0)){
result = slot;
break;
}
}
}
else
{
map->table[index] = slot;
}
}
}
if(slot)
{
slot->value = value;
slot->hash = hash;
MD_String8 *string_copy = MD_PushArray(MD_String8, 1);
*string_copy = MD_PushStringCopy(string);
slot->key = string_copy;
}
return !!slot;
return(result);
}
MD_FUNCTION_IMPL MD_MapSlot *
MD_StringMap_Next(MD_MapSlot *slot, MD_String8 key)
{
MD_MapSlot *next = 0;
if(slot)
{
for(MD_MapSlot *candidate = slot->next; candidate; candidate = candidate->next)
{
if(MD_StringMatch(*(MD_String8 *)candidate->key, key, 0))
{
next = candidate;
break;
}
}
MD_FUNCTION_IMPL MD_MapSlot*
MD_MapInsert(MD_Map *map, MD_MapKey key, void *val){
MD_MapSlot *result = 0;
if (map->table_size > 0){
MD_u64 index = key.hash%map->table_size;
// TODO(allen): again, memory? permanent arena? scratch arena?
// should definitely match the table's memory "object"
MD_MapSlot *slot = MD_PushArray(MD_MapSlot, 1);
// TODO(allen): queue push
slot->next = map->table[index];
map->table[index] = slot;
slot->key = key;
slot->val = val;
result = slot;
}
return next;
return(result);
}
//- Pointer-To-Pointer Table
MD_FUNCTION_IMPL MD_MapSlot *
MD_PtrMap_Lookup(MD_Map *map, void *key)
{
_MD_Map_Initialize(map);
MD_MapSlot *slot = 0;
MD_u64 hash = MD_HashPointer(key);
MD_u64 index = hash % map->table_size;
for(MD_MapSlot *candidate = map->table[index]; candidate; candidate = candidate->next)
{
if(candidate->hash == hash)
{
slot = candidate;
break;
}
MD_FUNCTION_IMPL MD_MapSlot*
MD_MapOverwrite(MD_Map *map, MD_MapKey key, void *val){
MD_MapSlot *result = MD_MapLookup(map, key);
if (result != 0){
result->val = val;
}
return slot;
}
MD_FUNCTION_IMPL MD_b32
MD_PtrMap_Insert(MD_Map *map, MD_MapCollisionRule collision_rule, void *key, void *value)
{
_MD_Map_Initialize(map);
MD_MapSlot *slot = 0;
MD_u64 hash = MD_HashPointer(key);
MD_u64 index = hash % map->table_size;
for(MD_MapSlot *candidate = map->table[index]; candidate; candidate = candidate->next)
{
if(candidate->hash == hash)
{
slot = candidate;
break;
}
else{
result = MD_MapInsert(map, key, val);
}
if(slot == 0 || (slot != 0 && collision_rule == MD_MapCollisionRule_Chain))
{
slot = MD_PushArray(MD_MapSlot, 1);
if(slot)
{
slot->next = 0;
if(map->table[index])
{
for(MD_MapSlot *old_slot = map->table[index]; old_slot; old_slot = old_slot->next)
{
if(old_slot->next == 0)
{
old_slot->next = slot;
break;
}
}
}
else
{
map->table[index] = slot;
}
}
}
if(slot)
{
slot->value = value;
slot->hash = hash;
}
return !!slot;
return(result);
}
//~ Parsing
@@ -2066,16 +2002,17 @@ MD_ParseWholeString(MD_String8 filename, MD_String8 contents)
// NOTE(allen): setup namespace structure
MD_Node *namespaces = _MD_MakeNode_Ctx(&ctx, MD_NodeKind_List,
MD_S8Lit(""), MD_S8Lit(""), ctx.at);
MD_Node *default_namespace = _MD_MakeNode_Ctx(&ctx, MD_NodeKind_List,
MD_S8Lit(""), MD_S8Lit(""), ctx.at);
MD_PushChild(namespaces, default_namespace);
MD_Map namespace_table = MD_MapMake();
MD_Map namespace_table = {0};
MD_StringMap_Insert(&namespace_table, MD_MapCollisionRule_Overwrite, default_namespace->string, default_namespace);
// NOTE(allen): setup default namespace
MD_Node *default_ns = _MD_MakeNode_Ctx(&ctx, MD_NodeKind_List,
MD_S8Lit(""), MD_S8Lit(""), ctx.at);
MD_PushChild(namespaces, default_ns);
MD_MapInsert(&namespace_table, MD_MapKeyStr(default_ns->string), default_ns);
// NOTE(allen): setup namespace
// NOTE(allen): parse loop
MD_NodeFlags next_child_flags = 0;
MD_Node *selected_namespace = default_namespace;
MD_Node *selected_namespace = default_ns;
for(;;)
{
// TODO(allen): I don't get it... this can only happen once between
@@ -2115,20 +2052,19 @@ MD_ParseWholeString(MD_String8 filename, MD_String8 contents)
MD_Token token = MD_ZERO_STRUCT;
if(MD_Parse_RequireKind(&ctx, MD_TokenKind_Identifier, &token))
{
MD_MapSlot *existing_namespace_slot = MD_StringMap_Lookup(&namespace_table, token.string);
if(existing_namespace_slot == 0)
{
MD_MapKey ns_key = MD_MapKeyStr(token.string);
MD_MapSlot *ns_slot = MD_MapLookup(&namespace_table, ns_key);
if (ns_slot == 0){
MD_Node *ns = _MD_MakeNode_Ctx(&ctx, MD_NodeKind_List,
token.string, token.string, token.outer_string.str);
MD_StringMap_Insert(&namespace_table, MD_MapCollisionRule_Overwrite, token.string, ns);
existing_namespace_slot = MD_StringMap_Lookup(&namespace_table, token.string);
MD_PushChild(namespaces, ns);
ns_slot = MD_MapInsert(&namespace_table, ns_key, ns);
}
selected_namespace = (MD_Node *)existing_namespace_slot->value;
selected_namespace = (MD_Node *)ns_slot->val;
}
else
{
selected_namespace = default_namespace;
selected_namespace = default_ns;
}
}
// NOTE(rjf): Not a valid hash thing
+18 -18
View File
@@ -82,8 +82,8 @@ static MD_Node * NewChild(MD_Node *parent)
#define OPTIONAL_TAG "optional"
#define GET_DEPTH(depth_map, node) ((MD_u64)MD_PtrMap_Lookup(depth_map, node)->value)
#define SET_DEPTH(depth_map, node, depth) MD_PtrMap_Insert(depth_map, MD_MapCollisionRule_Overwrite, node, (void *)(depth))
#define GET_DEPTH(depth_map, node) ((MD_u64)MD_MapLookup(depth_map, MD_MapKeyPtr(node))->val)
#define SET_DEPTH(depth_map, node, depth) MD_MapOverwrite(depth_map, MD_MapKeyPtr(node), (void *)(depth))
static void PrintRule(MD_Map *depth_map, MD_Node *rule)
{
MD_b32 is_literal_char = rule->flags & MD_NodeFlag_CharLiteral;
@@ -252,7 +252,7 @@ static void ExpandRule(MD_Node *rule, MD_String8List *out_strings, MD_Node *cur_
}
else // NOTE(mal): Non-terminal production
{
MD_Node * production = MD_StringMap_Lookup(globals.production_table, rule_element->string)->value;
MD_Node * production = MD_MapLookup(globals.production_table, MD_MapKeyStr(rule_element->string))->val;
MD_Assert(production);
ExpandProduction(production, out_strings, cur_node, op_flags, depth_map, max_depth, depth+1);
}
@@ -293,13 +293,13 @@ static MD_Node * FindNonTerminalProduction(MD_Node *node, MD_Map *visited)
MD_b32 should_visit = 1;
if(!MD_NodeIsNil(node->first_child) && node->string.size)
{
if(MD_StringMap_Lookup(visited, node->string))
if(MD_MapLookup(visited, MD_MapKeyStr(node->string)))
{
should_visit = 0;
}
else
{
MD_b32 inserted = MD_StringMap_Insert(visited, MD_MapCollisionRule_Overwrite, node->string, node);
void *inserted = MD_MapOverwrite(visited, MD_MapKeyStr(node->string), node);
MD_Assert(inserted);
}
}
@@ -313,10 +313,10 @@ static MD_Node * FindNonTerminalProduction(MD_Node *node, MD_Map *visited)
}
else
{
MD_MapSlot *slot = MD_StringMap_Lookup(globals.production_table, node->string);
MD_MapSlot *slot = MD_MapLookup(globals.production_table, MD_MapKeyStr(node->string));
if(slot)
{
MD_Node *production = slot->value;
MD_Node *production = slot->val;
result = FindNonTerminalProduction(production, visited);
}
else
@@ -431,7 +431,7 @@ static void ComputeElementDepth(MD_Map *depth_map, MD_Node *re)
}
else
{
MD_Node * production = MD_StringMap_Lookup(globals.production_table, re->string)->value;
MD_Node * production = MD_MapLookup(globals.production_table, MD_MapKeyStr(re->string))->val;
result = GET_DEPTH(depth_map, production)+1;
}
}
@@ -576,29 +576,29 @@ int main(int argument_count, char **arguments)
}
// NOTE(mal): Build production hash table
MD_Map production_table_ = {0};
MD_Map production_table_ = MD_MapMake();
globals.production_table = &production_table_;
for(MD_EachNode(production, productions->first_child))
{
MD_b32 inserted = MD_StringMap_Insert(globals.production_table, MD_MapCollisionRule_Overwrite,
production->string, production);
void *inserted = MD_MapOverwrite(globals.production_table,
MD_MapKeyStr(production->string), production);
MD_Assert(inserted);
}
// NOTE(mal): Check for root production
MD_Node* file_production = 0;
{
MD_MapSlot *file_production_slot = MD_StringMap_Lookup(globals.production_table, MD_S8Lit("file"));
MD_MapSlot *file_production_slot = MD_MapLookup(globals.production_table, MD_MapKeyStr(MD_S8Lit("file")));
if(!file_production_slot)
{
fprintf(stderr, "Error: Grammar file does not specify \"file\" production\n");
goto error;
}
file_production = file_production_slot->value;
file_production = file_production_slot->val;
}
// NOTE(mal): Check that all branches lead to terminal nodes
MD_Map visited_productions = {0};
MD_Map visited_productions = MD_MapMake();
for(MD_EachNode(production, productions->first_child))
{
@@ -613,7 +613,7 @@ int main(int argument_count, char **arguments)
// NOTE(mal): Check that all productions are reachable
for(MD_EachNode(production, productions->first_child))
{
MD_MapSlot *slot = MD_StringMap_Lookup(&visited_productions, production->string);
MD_MapSlot *slot = MD_MapLookup(&visited_productions, MD_MapKeyStr(production->string));
if(!slot)
{
fprintf(stderr, "Warning: Unreachable production \"%.*s\"\n", MD_StringExpand(production->string));
@@ -623,7 +623,7 @@ int main(int argument_count, char **arguments)
// NOTE(mal): Compute depth of productions, rules, rule elements
// NOTE(mal): Init all MD_Node depths to 0
MD_Map depth_map_ = {0};
MD_Map depth_map_ = MD_MapMake();
MD_Map *depth_map = &depth_map_;
for(MD_EachNode(production, productions->first_child))
{
@@ -660,7 +660,7 @@ int main(int argument_count, char **arguments)
MD_Assert(MD_NodeIsNil(rule_element->first_child));
if(!(rule_element->flags & MD_NodeFlag_CharLiteral))
{
MD_Node * production = MD_StringMap_Lookup(globals.production_table, rule_element->string)->value;
MD_Node * production = MD_MapLookup(globals.production_table, MD_MapKeyStr(rule_element->string))->val;
depth = GET_DEPTH(depth_map, production);
}
depth += 1;
@@ -713,7 +713,7 @@ int main(int argument_count, char **arguments)
RandomSeries random_series = rand_seed(0, 0); // NOTE(mal): Reproduceable
globals.random_series = &random_series;
MD_Node* file_production_node = MD_StringMap_Lookup(globals.production_table, MD_S8Lit("file"))->value;
MD_Node* file_production_node = MD_MapLookup(globals.production_table, MD_MapKeyStr(MD_S8Lit("file")))->val;
// NOTE(mal): Generate test_count unique tests, sorted by complexity
MD_u32 test_count = 1000;
+20 -37
View File
@@ -500,53 +500,36 @@ int main(void)
Test("Hash maps")
{
MD_String8 keys[] =
MD_String8 key_strings[] =
{
MD_S8Lit("\xed\x80\x73\x71\x78\xba\xff\xd6\x87\x83\xcd\x20\x28\xf7\x1c\xc1\x5f\xca\x98\x9c\x5a\xab\x0c\xae\x9a\x60\x57\x03\xeb\x1f\xde\x99"),
MD_S8Lit("\x4c\x80\xb7\x8b\xbf\x65\x5a\x4b\xc1\x2a\xc3\x5f\xe1\x66\xfb\x0d\x72\x83\x1c\x63\xba\xb5\x97\x02\x3f\x6a\xe0\x2a\x1b\x82\x07\x76"),
MD_S8Lit("\xd8\xfd\x11\x4b\x04\xdf\xe5\x20\x5b\xd6\x4f\x87\x00\x70\x6a\xc8\xde\xed\xc7\x79\xdb\x87\x24\x36\xa8\x7a\x31\x41\x00\x57\xbd\x8d"),
};
// NOTE(mal): True for MD_HashString is djb2
{
TestResult(MD_HashString(keys[0]) == 1 && MD_HashString(keys[1]) == 1 && MD_HashString(keys[2]) == 3);
MD_MapKey keys[MD_ArrayCount(key_strings)*2];
for (MD_u64 i = 0; i < MD_ArrayCount(key_strings); i += 1){
keys[i] = MD_MapKeyStr(key_strings[i]);
}
for (MD_u64 i = MD_ArrayCount(key_strings); i < MD_ArrayCount(keys); i += 1){
keys[i] = MD_MapKeyPtr((void *)i);
}
{
MD_MapCollisionRule rules[] = { MD_MapCollisionRule_Chain, MD_MapCollisionRule_Overwrite };
for(int i_rule = 0; i_rule < MD_ArrayCount(rules); ++i_rule)
{
MD_Map map = {0};
MD_StringMap_Insert(&map, rules[i_rule], keys[0], (void *)0);
MD_StringMap_Insert(&map, rules[i_rule], keys[1], (void *)1);
MD_StringMap_Insert(&map, rules[i_rule], keys[2], (void *)2);
MD_MapSlot *slot0 = MD_StringMap_Lookup(&map, keys[0]);
MD_MapSlot *slot1 = MD_StringMap_Lookup(&map, keys[1]);
MD_MapSlot *slot2 = MD_StringMap_Lookup(&map, keys[2]);
TestResult(slot0 && slot0->value == (void *)0 &&
slot1 && slot1->value == (void *)1 &&
slot2 && slot2->value == (void *)2);
MD_Map map = MD_MapMake();
for (MD_u64 i = 0; i < MD_ArrayCount(keys); i += 1){
MD_MapInsert(&map, keys[i], (void *)i);
}
}
{
MD_MapCollisionRule rules[] = { MD_MapCollisionRule_Chain, MD_MapCollisionRule_Overwrite };
for(int i_rule = 0; i_rule < MD_ArrayCount(rules); ++i_rule)
{
MD_Map map = {0};
MD_PtrMap_Insert(&map, rules[i_rule], (void *)0, (void *)0);
MD_PtrMap_Insert(&map, rules[i_rule], (void *)1, (void *)1);
MD_PtrMap_Insert(&map, rules[i_rule], (void *)2, (void *)2);
MD_MapSlot *slot0 = MD_PtrMap_Lookup(&map, (void *)0);
MD_MapSlot *slot1 = MD_PtrMap_Lookup(&map, (void *)1);
MD_MapSlot *slot2 = MD_PtrMap_Lookup(&map, (void *)2);
TestResult(slot0 && slot0->value == (void *) 0 &&
slot1 && slot1->value == (void *) 1 &&
slot2 && slot2->value == (void *) 2);
for (MD_u64 i = 0; i < MD_ArrayCount(keys); i += 1){
MD_MapSlot *slot = MD_MapLookup(&map, keys[i]);
TestResult(slot && slot->val == (void *)i);
}
for (MD_u64 i = 0; i < MD_ArrayCount(keys); i += 1){
MD_MapOverwrite(&map, keys[i], (void *)(i + 10));
}
for (MD_u64 i = 0; i < MD_ArrayCount(keys); i += 1){
MD_MapSlot *slot = MD_MapLookup(&map, keys[i]);
TestResult(slot && slot->val == (void *)(i + 10));
}
}
}