generic containers
This commit is contained in:
+3
-3
@@ -35,7 +35,7 @@ struct Array_List {
|
||||
return data[index];
|
||||
}
|
||||
|
||||
proc _merge(int start, int mid, int end) -> void {
|
||||
void _merge(int start, int mid, int end) {
|
||||
int start2 = mid + 1;
|
||||
|
||||
/* If the direct merge is already sorted */
|
||||
@@ -67,7 +67,7 @@ struct Array_List {
|
||||
}
|
||||
}
|
||||
|
||||
proc sort(int left=-1, int right=-1) -> void {
|
||||
void sort(int left=-1, int right=-1) {
|
||||
if (left == -1) {
|
||||
sort(0, next_index - 1);
|
||||
return;
|
||||
@@ -83,7 +83,7 @@ struct Array_List {
|
||||
_merge(left, middle, right);
|
||||
}
|
||||
|
||||
proc sorted_find(type elem, int left=-1, int right=-1) -> int {
|
||||
int sorted_find(type elem, int left=-1, int right=-1) {
|
||||
if (left == -1) {
|
||||
return sorted_find(elem, 0, next_index - 1);
|
||||
} else if (left == right) {
|
||||
|
||||
+296
-154
@@ -11,159 +11,301 @@
|
||||
// }
|
||||
// }
|
||||
|
||||
#define __for_hm_generator(key_type, hm) \
|
||||
if (key_type key = nullptr); else \
|
||||
if (void* value = nullptr); else \
|
||||
for(int index = 0; index < hm->current_capacity; ++index) \
|
||||
if (!((!hm->data[index].deleted) && \
|
||||
(key = hm->data[index].original) && \
|
||||
(value = hm->data[index].object))); else
|
||||
#define __for_hm_generator(key_type, value_type, hm) \
|
||||
if (key_type key = 0); else \
|
||||
if (value_type value = 0); else \
|
||||
for(int index = 0; index < hm.current_capacity; ++index) \
|
||||
if (!((!hm.data[index].deleted) && \
|
||||
(key = hm.data[index].original) && \
|
||||
(value = hm.data[index].object))); else
|
||||
|
||||
|
||||
#define define_hash_map(type, name) \
|
||||
bool hm_objects_match(type,type); \
|
||||
u32 hm_hash(type); \
|
||||
\
|
||||
struct name##_Hash_Map_Cell { \
|
||||
type original; \
|
||||
u64 hash; \
|
||||
bool deleted; \
|
||||
void* object; \
|
||||
}; \
|
||||
\
|
||||
struct name##_Hash_Map { \
|
||||
int current_capacity; \
|
||||
int cell_count; \
|
||||
name##_Hash_Map_Cell* data; \
|
||||
}; \
|
||||
\
|
||||
name##_Hash_Map* create_##name##_hashmap(int initial_capacity=8) { \
|
||||
name##_Hash_Map* hm = new name##_Hash_Map; \
|
||||
hm->current_capacity = initial_capacity; \
|
||||
hm->cell_count = 0; \
|
||||
/* set all data to nullptr */ \
|
||||
hm->data = (name##_Hash_Map_Cell*)calloc(initial_capacity, sizeof(name##_Hash_Map_Cell)); \
|
||||
/* printf("check: %s\n", hm->data[6].original_string); */ \
|
||||
return hm; \
|
||||
} \
|
||||
\
|
||||
int hm_get_index_of_living_cell_if_it_exists(name##_Hash_Map* hm, type key, u64 hash_val) { \
|
||||
int index = hash_val % hm->current_capacity; \
|
||||
name##_Hash_Map_Cell cell = hm->data[index]; \
|
||||
/* test if cell exists at that index */ \
|
||||
if (cell.original) { \
|
||||
/* check if strings match */ \
|
||||
if (hm_objects_match(key, cell.original)) { \
|
||||
/* we found it, now check it it is deleted: */ \
|
||||
if (cell.deleted) { \
|
||||
/* we found it but it was deleted, we */ \
|
||||
/* dont have to check for collisions then */ \
|
||||
return -1; \
|
||||
} else { \
|
||||
/* we found it and it is not deleted */ \
|
||||
return index; \
|
||||
} \
|
||||
} else { \
|
||||
/* strings dont match, this means we have */ \
|
||||
/* a collision. We just search forward */ \
|
||||
for (int i = 0; i < hm->current_capacity; ++i) { \
|
||||
int new_idx = (i + index) % hm->current_capacity; \
|
||||
cell = hm->data[new_idx]; \
|
||||
if (!cell.original) \
|
||||
return -1; \
|
||||
if (!hm_objects_match(key, cell.original)) \
|
||||
continue; \
|
||||
if (cell.deleted) \
|
||||
continue; \
|
||||
return new_idx; \
|
||||
} \
|
||||
/* not or only deleted cells found */ \
|
||||
return -1; \
|
||||
} \
|
||||
} else { \
|
||||
/* no cell exists at this index so the item was never in the */ \
|
||||
/* hashmap. Either it would be there or be ther and 'deleted' */ \
|
||||
/* or another item would be there and therefore a collistion */ \
|
||||
/* would exist */ \
|
||||
return -1; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
inline bool hm_key_exists(name##_Hash_Map* hm, type key) { \
|
||||
return hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)) != -1; \
|
||||
} \
|
||||
\
|
||||
inline void* hm_get_object(name##_Hash_Map* hm, type key) { \
|
||||
int index = hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)); \
|
||||
if (index != -1) { \
|
||||
return hm->data[index].object; \
|
||||
} \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
inline void hm_delete_object(name##_Hash_Map* hm, type key) { \
|
||||
int index = hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)); \
|
||||
if (index != -1) { \
|
||||
hm->data[index].deleted = true; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void hm_set(name##_Hash_Map* hm, type key, void* obj) { \
|
||||
u64 hash_val = hm_hash(key); \
|
||||
int index = hash_val % hm->current_capacity; \
|
||||
\
|
||||
/* if we the desired cell is just empty, write to it and done :) */ \
|
||||
if (!hm->data[index].original) { \
|
||||
/* insert new cell into desired slot */ \
|
||||
++hm->cell_count; \
|
||||
} else { \
|
||||
if (hm_objects_match(key, hm->data[index].original)) { \
|
||||
/* overwrite object with same key, dont increment cell */ \
|
||||
/* count */ \
|
||||
} else { \
|
||||
/* collision, check resize */ \
|
||||
++hm->cell_count; \
|
||||
if ((hm->cell_count*1.0f / hm->current_capacity) > 0.666f) { \
|
||||
auto old_data = hm->data; \
|
||||
hm->data = (name##_Hash_Map_Cell*)calloc(hm->current_capacity*4, sizeof(name##_Hash_Map_Cell)); \
|
||||
hm->cell_count = 0; \
|
||||
hm->current_capacity *= 4; \
|
||||
\
|
||||
/* insert all old items again */ \
|
||||
for (int i = 0; i < hm->current_capacity/4; ++i) { \
|
||||
auto cell = old_data[i]; \
|
||||
if (cell.original) { \
|
||||
hm_set(hm, cell.original, cell.object); \
|
||||
} \
|
||||
} \
|
||||
free(old_data); \
|
||||
index = hash_val % hm->current_capacity; \
|
||||
} \
|
||||
/* search for empty slot for new cell starting at desired index; */ \
|
||||
/* preventing gotos using lambdas! */ \
|
||||
[&](){ \
|
||||
for (int i = index; i < hm->current_capacity; ++i) { \
|
||||
if (!hm->data[i].original || \
|
||||
hm_objects_match(hm->data[i].original, key)) \
|
||||
{ \
|
||||
index = i; \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
for (int i = 0; i < index; ++i) { \
|
||||
if (!hm->data[i].original || \
|
||||
hm_objects_match(hm->data[i].original, key)) \
|
||||
{ \
|
||||
index = i; \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
}(); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
hm->data[index].deleted = false; \
|
||||
hm->data[index].original = key; \
|
||||
hm->data[index].hash = hash_val; \
|
||||
hm->data[index].object = obj; \
|
||||
} \
|
||||
template <typename key_type, typename value_type>
|
||||
struct Hash_Map {
|
||||
int current_capacity;
|
||||
int cell_count;
|
||||
struct HM_Cell {
|
||||
key_type original;
|
||||
u64 hash;
|
||||
bool deleted;
|
||||
value_type object;
|
||||
}* data;
|
||||
|
||||
Hash_Map(int initial_capacity = 8) {
|
||||
current_capacity = initial_capacity;
|
||||
cell_count = 0;
|
||||
data = (HM_Cell*)calloc(initial_capacity, sizeof(HM_Cell));
|
||||
}
|
||||
|
||||
int get_index_of_living_cell_if_it_exists(key_type key, u64 hash_val) {
|
||||
// int index = hash_val & (current_capacity - 1);
|
||||
int index = hash_val % current_capacity;
|
||||
HM_Cell cell = data[index];
|
||||
/* test if cell exists at that index */
|
||||
if (cell.original) {
|
||||
/* check if strings match */
|
||||
if (hm_objects_match(key, cell.original)) {
|
||||
/* we found it, now check it it is deleted: */
|
||||
if (cell.deleted) {
|
||||
/* we found it but it was deleted, we */
|
||||
/* dont have to check for collisions then */
|
||||
return -1;
|
||||
} else {
|
||||
/* we found it and it is not deleted */
|
||||
return index;
|
||||
}
|
||||
} else {
|
||||
/* strings dont match, this means we have */
|
||||
/* a collision. We just search forward */
|
||||
for (int i = 0; i < current_capacity; ++i) {
|
||||
int new_idx = (i + index) % current_capacity;
|
||||
cell = data[new_idx];
|
||||
if (!cell.original)
|
||||
return -1;
|
||||
if (!hm_objects_match(key, cell.original))
|
||||
continue;
|
||||
if (cell.deleted)
|
||||
continue;
|
||||
return new_idx;
|
||||
}
|
||||
/* not or only deleted cells found */
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* no cell exists at this index so the item was never in the */
|
||||
/* hashmap. Either it would be there or be ther and 'deleted' */
|
||||
/* or another item would be there and therefore a collistion */
|
||||
/* would exist */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool key_exists(key_type key) {
|
||||
return get_index_of_living_cell_if_it_exists(key, hm_hash(key)) != -1;
|
||||
}
|
||||
|
||||
value_type get_object(key_type key) {
|
||||
int index = get_index_of_living_cell_if_it_exists(key, hm_hash(key));
|
||||
if (index != -1) {
|
||||
return data[index].object;
|
||||
}
|
||||
int a = *((int*)(nullptr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void delete_object(key_type key) {
|
||||
int index = get_index_of_living_cell_if_it_exists(key, hm_hash(key));
|
||||
if (index != -1) {
|
||||
data[index].deleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void set_object(key_type key, value_type obj) {
|
||||
u64 hash_val = hm_hash(key);
|
||||
int index = hash_val % current_capacity;
|
||||
|
||||
/* if we the desired cell is just empty, write to it and done :) */
|
||||
if (!data[index].original) {
|
||||
/* insert new cell into desired slot */
|
||||
++cell_count;
|
||||
} else {
|
||||
if (hm_objects_match(key, data[index].original)) {
|
||||
/* overwrite object with same key, dont increment cell */
|
||||
/* count */
|
||||
} else {
|
||||
/* collision, check resize */
|
||||
++cell_count;
|
||||
if ((cell_count*1.0f / current_capacity) > 0.666f) {
|
||||
auto old_data = data;
|
||||
data = (HM_Cell*)calloc(current_capacity*4, sizeof(HM_Cell));
|
||||
cell_count = 0;
|
||||
current_capacity *= 4;
|
||||
|
||||
/* insert all old items again */
|
||||
for (int i = 0; i < current_capacity/4; ++i) {
|
||||
auto cell = old_data[i];
|
||||
if (cell.original) {
|
||||
set_object(cell.original, cell.object);
|
||||
}
|
||||
}
|
||||
free(old_data);
|
||||
index = hash_val % current_capacity;
|
||||
}
|
||||
/* search for empty slot for new cell starting at desired index; */
|
||||
/* preventing gotos using lambdas! */
|
||||
[&](){
|
||||
for (int i = index; i < current_capacity; ++i) {
|
||||
if (!data[i].original ||
|
||||
hm_objects_match(data[i].original, key))
|
||||
{
|
||||
index = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < index; ++i) {
|
||||
if (!data[i].original ||
|
||||
hm_objects_match(data[i].original, key))
|
||||
{
|
||||
index = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
data[index].deleted = false;
|
||||
data[index].original = key;
|
||||
data[index].hash = hash_val;
|
||||
data[index].object = obj;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// #define define_hash_map(type, name) \
|
||||
// bool hm_objects_match(type,type); \
|
||||
// u32 hm_hash(type); \
|
||||
// \
|
||||
// struct name##_Hash_Map_Cell { \
|
||||
// type original; \
|
||||
// u64 hash; \
|
||||
// bool deleted; \
|
||||
// void* object; \
|
||||
// }; \
|
||||
// \
|
||||
// struct name##_Hash_Map { \
|
||||
// int current_capacity; \
|
||||
// int cell_count; \
|
||||
// name##_Hash_Map_Cell* data; \
|
||||
// }; \
|
||||
// \
|
||||
// name##_Hash_Map* create_##name##_hashmap(int initial_capacity=8) { \
|
||||
// name##_Hash_Map* hm = new name##_Hash_Map; \
|
||||
// hm->current_capacity = initial_capacity; \
|
||||
// hm->cell_count = 0; \
|
||||
// /* set all data to nullptr */ \
|
||||
// hm->data = (name##_Hash_Map_Cell*)calloc(initial_capacity, sizeof(name##_Hash_Map_Cell)); \
|
||||
// /* printf("check: %s\n", hm->data[6].original_string); */ \
|
||||
// return hm; \
|
||||
// } \
|
||||
// \
|
||||
// int hm_get_index_of_living_cell_if_it_exists(name##_Hash_Map* hm, type key, u64 hash_val) { \
|
||||
// int index = hash_val % hm->current_capacity; \
|
||||
// name##_Hash_Map_Cell cell = hm->data[index]; \
|
||||
// /* test if cell exists at that index */ \
|
||||
// if (cell.original) { \
|
||||
// /* check if strings match */ \
|
||||
// if (hm_objects_match(key, cell.original)) { \
|
||||
// /* we found it, now check it it is deleted: */ \
|
||||
// if (cell.deleted) { \
|
||||
// /* we found it but it was deleted, we */ \
|
||||
// /* dont have to check for collisions then */ \
|
||||
// return -1; \
|
||||
// } else { \
|
||||
// /* we found it and it is not deleted */ \
|
||||
// return index; \
|
||||
// } \
|
||||
// } else { \
|
||||
// /* strings dont match, this means we have */ \
|
||||
// /* a collision. We just search forward */ \
|
||||
// for (int i = 0; i < hm->current_capacity; ++i) { \
|
||||
// int new_idx = (i + index) % hm->current_capacity; \
|
||||
// cell = hm->data[new_idx]; \
|
||||
// if (!cell.original) \
|
||||
// return -1; \
|
||||
// if (!hm_objects_match(key, cell.original)) \
|
||||
// continue; \
|
||||
// if (cell.deleted) \
|
||||
// continue; \
|
||||
// return new_idx; \
|
||||
// } \
|
||||
// /* not or only deleted cells found */ \
|
||||
// return -1; \
|
||||
// } \
|
||||
// } else { \
|
||||
// /* no cell exists at this index so the item was never in the */ \
|
||||
// /* hashmap. Either it would be there or be ther and 'deleted' */ \
|
||||
// /* or another item would be there and therefore a collistion */ \
|
||||
// /* would exist */ \
|
||||
// return -1; \
|
||||
// } \
|
||||
// } \
|
||||
// \
|
||||
// inline bool hm_key_exists(name##_Hash_Map* hm, type key) { \
|
||||
// return hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)) != -1; \
|
||||
// } \
|
||||
// \
|
||||
// inline void* hm_get_object(name##_Hash_Map* hm, type key) { \
|
||||
// int index = hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)); \
|
||||
// if (index != -1) { \
|
||||
// return hm->data[index].object; \
|
||||
// } \
|
||||
// return nullptr; \
|
||||
// } \
|
||||
// \
|
||||
// inline void hm_delete_object(name##_Hash_Map* hm, type key) { \
|
||||
// int index = hm_get_index_of_living_cell_if_it_exists(hm, key, hm_hash(key)); \
|
||||
// if (index != -1) { \
|
||||
// hm->data[index].deleted = true; \
|
||||
// } \
|
||||
// } \
|
||||
// \
|
||||
// void hm_set(name##_Hash_Map* hm, type key, void* obj) { \
|
||||
// u64 hash_val = hm_hash(key); \
|
||||
// int index = hash_val % hm->current_capacity; \
|
||||
// \
|
||||
// /* if we the desired cell is just empty, write to it and done :) */ \
|
||||
// if (!hm->data[index].original) { \
|
||||
// /* insert new cell into desired slot */ \
|
||||
// ++hm->cell_count; \
|
||||
// } else { \
|
||||
// if (hm_objects_match(key, hm->data[index].original)) { \
|
||||
// /* overwrite object with same key, dont increment cell */ \
|
||||
// /* count */ \
|
||||
// } else { \
|
||||
// /* collision, check resize */ \
|
||||
// ++hm->cell_count; \
|
||||
// if ((hm->cell_count*1.0f / hm->current_capacity) > 0.666f) { \
|
||||
// auto old_data = hm->data; \
|
||||
// hm->data = (name##_Hash_Map_Cell*)calloc(hm->current_capacity*4, sizeof(name##_Hash_Map_Cell)); \
|
||||
// hm->cell_count = 0; \
|
||||
// hm->current_capacity *= 4; \
|
||||
// \
|
||||
// /* insert all old items again */ \
|
||||
// for (int i = 0; i < hm->current_capacity/4; ++i) { \
|
||||
// auto cell = old_data[i]; \
|
||||
// if (cell.original) { \
|
||||
// hm_set(hm, cell.original, cell.object); \
|
||||
// } \
|
||||
// } \
|
||||
// free(old_data); \
|
||||
// index = hash_val % hm->current_capacity; \
|
||||
// } \
|
||||
// /* search for empty slot for new cell starting at desired index; */ \
|
||||
// /* preventing gotos using lambdas! */ \
|
||||
// [&](){ \
|
||||
// for (int i = index; i < hm->current_capacity; ++i) { \
|
||||
// if (!hm->data[i].original || \
|
||||
// hm_objects_match(hm->data[i].original, key)) \
|
||||
// { \
|
||||
// index = i; \
|
||||
// return; \
|
||||
// } \
|
||||
// } \
|
||||
// for (int i = 0; i < index; ++i) { \
|
||||
// if (!hm->data[i].original || \
|
||||
// hm_objects_match(hm->data[i].original, key)) \
|
||||
// { \
|
||||
// index = i; \
|
||||
// return; \
|
||||
// } \
|
||||
// } \
|
||||
// }(); \
|
||||
// } \
|
||||
// } \
|
||||
// \
|
||||
// hm->data[index].deleted = false; \
|
||||
// hm->data[index].original = key; \
|
||||
// hm->data[index].hash = hash_val; \
|
||||
// hm->data[index].object = obj; \
|
||||
// } \
|
||||
|
||||
Reference in New Issue
Block a user