Started migrating things to EXT
This commit is contained in:
1 parent
e39d60ade9
commit
89254ab5db
11 files changed
+1131
-1071
No files matched your search
+132
-447
@@ -47,187 +47,138 @@
|
||||
/* -------------------------------------------------------------------------
|
||||
* Header
|
||||
* ------------------------------------------------------------------------- */
|
||||
#define CMC_CMC_HASHMAP_CORE_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
/* Hashmap Structure */ \
|
||||
struct SNAME \
|
||||
{ \
|
||||
/* Array of Entries */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * buffer; \
|
||||
\
|
||||
/* Current array capacity */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Current amount of keys */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Load factor in range (0.0, 1.0) */ \
|
||||
double load; \
|
||||
\
|
||||
/* Flags indicating errors or success */ \
|
||||
int flag; \
|
||||
\
|
||||
/* Key function table */ \
|
||||
struct CMC_DEF_FKEY(SNAME) * f_key; \
|
||||
\
|
||||
/* Value function table */ \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val; \
|
||||
\
|
||||
/* Custom allocation functions */ \
|
||||
struct cmc_alloc_node *alloc; \
|
||||
\
|
||||
/* Custom callback functions */ \
|
||||
struct cmc_callbacks *callbacks; \
|
||||
}; \
|
||||
\
|
||||
/* Hashmap Entry */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) \
|
||||
{ \
|
||||
/* Entry Key */ \
|
||||
K key; \
|
||||
\
|
||||
/* Entry Value */ \
|
||||
V value; \
|
||||
\
|
||||
/* The distance of this node to its original position, used by */ \
|
||||
/* robin-hood hashing */ \
|
||||
size_t dist; \
|
||||
\
|
||||
/* The sate of this node (DELETED, EMPTY, FILLED) */ \
|
||||
enum cmc_entry_state state; \
|
||||
}; \
|
||||
\
|
||||
/* Key struct function table */ \
|
||||
struct CMC_DEF_FKEY(SNAME) \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(K, K); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
K (*cpy)(K); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, K); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(K); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(K); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(K, K); \
|
||||
}; \
|
||||
\
|
||||
/* Value struct function table */ \
|
||||
struct CMC_DEF_FVAL(SNAME) \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(V, V); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
V (*cpy)(V); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, V); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(V); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(V); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(V, V); \
|
||||
}; \
|
||||
\
|
||||
/* Hashmap Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target hashmap */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Cursor's position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* Keeps track of relative index to the iteration of elements */ \
|
||||
size_t index; \
|
||||
\
|
||||
/* The index of the first element */ \
|
||||
size_t first; \
|
||||
\
|
||||
/* The index of the last element */ \
|
||||
size_t last; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
}; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \
|
||||
struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val); \
|
||||
struct SNAME *CMC_(PFX, _new_custom)( \
|
||||
size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val, struct cmc_alloc_node * alloc, \
|
||||
struct cmc_callbacks * callbacks); \
|
||||
void CMC_(PFX, _clear)(struct SNAME * _map_); \
|
||||
void CMC_(PFX, _free)(struct SNAME * _map_); \
|
||||
void CMC_(PFX, _release)(struct SNAME _map_); \
|
||||
/* Customization of Allocation and Callbacks */ \
|
||||
void CMC_(PFX, _customize)(struct SNAME * _map_, \
|
||||
struct cmc_alloc_node * alloc, \
|
||||
struct cmc_callbacks * callbacks); \
|
||||
/* Collection Input and Output */ \
|
||||
bool CMC_(PFX, _insert)(struct SNAME * _map_, K key, V value); \
|
||||
bool CMC_(PFX, _update)(struct SNAME * _map_, K key, V new_value, \
|
||||
V * old_value); \
|
||||
bool CMC_(PFX, _remove)(struct SNAME * _map_, K key, V * out_value); \
|
||||
/* Element Access */ \
|
||||
bool CMC_(PFX, _max)(struct SNAME * _map_, K * key, V * value); \
|
||||
bool CMC_(PFX, _min)(struct SNAME * _map_, K * key, V * value); \
|
||||
V CMC_(PFX, _get)(struct SNAME * _map_, K key); \
|
||||
V *CMC_(PFX, _get_ref)(struct SNAME * _map_, K key); \
|
||||
/* Collection State */ \
|
||||
bool CMC_(PFX, _contains)(struct SNAME * _map_, K key); \
|
||||
bool CMC_(PFX, _empty)(struct SNAME * _map_); \
|
||||
bool CMC_(PFX, _full)(struct SNAME * _map_); \
|
||||
size_t CMC_(PFX, _count)(struct SNAME * _map_); \
|
||||
size_t CMC_(PFX, _capacity)(struct SNAME * _map_); \
|
||||
double CMC_(PFX, _load)(struct SNAME * _map_); \
|
||||
int CMC_(PFX, _flag)(struct SNAME * _map_); \
|
||||
/* Collection Utility */ \
|
||||
bool CMC_(PFX, _resize)(struct SNAME * _map_, size_t capacity); \
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _map_); \
|
||||
bool CMC_(PFX, _equals)(struct SNAME * _map1_, struct SNAME * _map2_); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index); \
|
||||
/* Iterator Access */ \
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
#define CMC_CMC_HASHMAP_CORE_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
/* Hashmap Structure */ \
|
||||
struct SNAME \
|
||||
{ \
|
||||
/* Array of Entries */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * buffer; \
|
||||
\
|
||||
/* Current array capacity */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Current amount of keys */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Load factor in range (0.0, 1.0) */ \
|
||||
double load; \
|
||||
\
|
||||
/* Flags indicating errors or success */ \
|
||||
int flag; \
|
||||
\
|
||||
/* Key function table */ \
|
||||
struct CMC_DEF_FKEY(SNAME) * f_key; \
|
||||
\
|
||||
/* Value function table */ \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val; \
|
||||
\
|
||||
/* Custom allocation functions */ \
|
||||
struct cmc_alloc_node *alloc; \
|
||||
\
|
||||
/* Custom callback functions */ \
|
||||
struct cmc_callbacks *callbacks; \
|
||||
}; \
|
||||
\
|
||||
/* Hashmap Entry */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) \
|
||||
{ \
|
||||
/* Entry Key */ \
|
||||
K key; \
|
||||
\
|
||||
/* Entry Value */ \
|
||||
V value; \
|
||||
\
|
||||
/* The distance of this node to its original position, used by */ \
|
||||
/* robin-hood hashing */ \
|
||||
size_t dist; \
|
||||
\
|
||||
/* The sate of this node (DELETED, EMPTY, FILLED) */ \
|
||||
enum cmc_entry_state state; \
|
||||
}; \
|
||||
\
|
||||
/* Key struct function table */ \
|
||||
struct CMC_DEF_FKEY(SNAME) \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(K, K); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
K (*cpy)(K); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, K); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(K); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(K); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(K, K); \
|
||||
}; \
|
||||
\
|
||||
/* Value struct function table */ \
|
||||
struct CMC_DEF_FVAL(SNAME) \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(V, V); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
V (*cpy)(V); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, V); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(V); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(V); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(V, V); \
|
||||
}; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \
|
||||
struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val); \
|
||||
struct SNAME *CMC_(PFX, _new_custom)( \
|
||||
size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val, struct cmc_alloc_node * alloc, \
|
||||
struct cmc_callbacks * callbacks); \
|
||||
void CMC_(PFX, _clear)(struct SNAME * _map_); \
|
||||
void CMC_(PFX, _free)(struct SNAME * _map_); \
|
||||
void CMC_(PFX, _release)(struct SNAME _map_); \
|
||||
/* Customization of Allocation and Callbacks */ \
|
||||
void CMC_(PFX, _customize)(struct SNAME * _map_, \
|
||||
struct cmc_alloc_node * alloc, \
|
||||
struct cmc_callbacks * callbacks); \
|
||||
/* Collection Input and Output */ \
|
||||
bool CMC_(PFX, _insert)(struct SNAME * _map_, K key, V value); \
|
||||
bool CMC_(PFX, _update)(struct SNAME * _map_, K key, V new_value, \
|
||||
V * old_value); \
|
||||
bool CMC_(PFX, _remove)(struct SNAME * _map_, K key, V * out_value); \
|
||||
/* Element Access */ \
|
||||
bool CMC_(PFX, _max)(struct SNAME * _map_, K * key, V * value); \
|
||||
bool CMC_(PFX, _min)(struct SNAME * _map_, K * key, V * value); \
|
||||
V CMC_(PFX, _get)(struct SNAME * _map_, K key); \
|
||||
V *CMC_(PFX, _get_ref)(struct SNAME * _map_, K key); \
|
||||
/* Collection State */ \
|
||||
bool CMC_(PFX, _contains)(struct SNAME * _map_, K key); \
|
||||
bool CMC_(PFX, _empty)(struct SNAME * _map_); \
|
||||
bool CMC_(PFX, _full)(struct SNAME * _map_); \
|
||||
size_t CMC_(PFX, _count)(struct SNAME * _map_); \
|
||||
size_t CMC_(PFX, _capacity)(struct SNAME * _map_); \
|
||||
double CMC_(PFX, _load)(struct SNAME * _map_); \
|
||||
int CMC_(PFX, _flag)(struct SNAME * _map_); \
|
||||
/* Collection Utility */ \
|
||||
bool CMC_(PFX, _resize)(struct SNAME * _map_, size_t capacity); \
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _map_); \
|
||||
bool CMC_(PFX, _equals)(struct SNAME * _map1_, struct SNAME * _map2_);
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Source
|
||||
@@ -842,272 +793,6 @@
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.first; \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.last; \
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->first; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->last; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = \
|
||||
&(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor++; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = \
|
||||
&(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor--; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (K){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].key; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].value; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor].value); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
} \
|
||||
\
|
||||
static struct CMC_DEF_ENTRY(SNAME) * \
|
||||
CMC_(PFX, _impl_get_entry)(struct SNAME * _map_, K key) \
|
||||
{ \
|
||||
|
||||
+135
-514
@@ -54,22 +54,6 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
#include "../cor/hashtable.h"
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* HashMultiMap specific
|
||||
* ------------------------------------------------------------------------- */
|
||||
/* to_string format */
|
||||
static const char *cmc_cmc_string_fmt_hashmultimap = "struct %s<%s, %s> "
|
||||
"at %p { "
|
||||
"buffer:%p, "
|
||||
"capacity:%" PRIuMAX ", "
|
||||
"count:%" PRIuMAX ", "
|
||||
"load:%lf, "
|
||||
"flag:%d, "
|
||||
"f_key:%p, "
|
||||
"f_val:%p, "
|
||||
"alloc:%p, "
|
||||
"callbacks:%p }";
|
||||
|
||||
/**
|
||||
* Core HashMultiMap implementation
|
||||
*/
|
||||
@@ -90,194 +74,141 @@ static const char *cmc_cmc_string_fmt_hashmultimap = "struct %s<%s, %s> "
|
||||
/* -------------------------------------------------------------------------
|
||||
* Header
|
||||
* ------------------------------------------------------------------------- */
|
||||
#define CMC_CMC_HASHMULTIMAP_CORE_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
/* HashMultimap Structure */ \
|
||||
struct SNAME \
|
||||
{ \
|
||||
/* Array of linked list to entries */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * (*buffer)[2]; \
|
||||
\
|
||||
/* Current array capacity */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Current amount of keys */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Load factor in range (0.0, infinity) */ \
|
||||
double load; \
|
||||
\
|
||||
/* Flags indicating errors or success */ \
|
||||
int flag; \
|
||||
\
|
||||
/* Key function table */ \
|
||||
struct CMC_DEF_FKEY(SNAME) * f_key; \
|
||||
\
|
||||
/* Value function table */ \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val; \
|
||||
\
|
||||
/* Custom allocation functions */ \
|
||||
struct cmc_alloc_node *alloc; \
|
||||
\
|
||||
/* Custom callback functions */ \
|
||||
struct cmc_callbacks *callbacks; \
|
||||
}; \
|
||||
\
|
||||
/* HashMultimap Entry */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) \
|
||||
{ \
|
||||
/* Entry Key */ \
|
||||
K key; \
|
||||
\
|
||||
/* Entry Value */ \
|
||||
V value; \
|
||||
\
|
||||
/* Next entry on the linked list */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * next; \
|
||||
\
|
||||
/* Previous entry on the linked list */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * prev; \
|
||||
}; \
|
||||
\
|
||||
/* Key struct function table */ \
|
||||
struct CMC_DEF_FKEY(SNAME) \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(K, K); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
K (*cpy)(K); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, K); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(K); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(K); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(K, K); \
|
||||
}; \
|
||||
\
|
||||
/* Value struct function table */ \
|
||||
struct CMC_DEF_FVAL(SNAME) \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(V, V); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
V (*cpy)(V); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, V); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(V); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(V); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(V, V); \
|
||||
}; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target hashmultimap */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Current entry */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * curr_entry; \
|
||||
\
|
||||
/* Cursor`s position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* Keeps track of relative index to the iteration of elements */ \
|
||||
size_t index; \
|
||||
\
|
||||
/* The index of the first element */ \
|
||||
size_t first; \
|
||||
\
|
||||
/* The index of the last element */ \
|
||||
size_t last; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
}; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \
|
||||
struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val); \
|
||||
struct SNAME *CMC_(PFX, _new_custom)( \
|
||||
size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val, struct cmc_alloc_node * alloc, \
|
||||
struct cmc_callbacks * callbacks); \
|
||||
void CMC_(PFX, _clear)(struct SNAME * _map_); \
|
||||
void CMC_(PFX, _free)(struct SNAME * _map_); \
|
||||
/* Customization of Allocation and Callbacks */ \
|
||||
void CMC_(PFX, _customize)(struct SNAME * _map_, \
|
||||
struct cmc_alloc_node * alloc, \
|
||||
struct cmc_callbacks * callbacks); \
|
||||
/* Collection Input and Output */ \
|
||||
bool CMC_(PFX, _insert)(struct SNAME * _map_, K key, V value); \
|
||||
bool CMC_(PFX, _update)(struct SNAME * _map_, K key, V new_value, \
|
||||
V * old_value); \
|
||||
size_t CMC_(PFX, _update_all)(struct SNAME * _map_, K key, V new_value, \
|
||||
V * *old_values); \
|
||||
bool CMC_(PFX, _remove)(struct SNAME * _map_, K key, V * out_value); \
|
||||
size_t CMC_(PFX, _remove_all)(struct SNAME * _map_, K key, \
|
||||
V * *out_values); \
|
||||
/* Element Access */ \
|
||||
bool CMC_(PFX, _max)(struct SNAME * _map_, K * key, V * value); \
|
||||
bool CMC_(PFX, _min)(struct SNAME * _map_, K * key, V * value); \
|
||||
V CMC_(PFX, _get)(struct SNAME * _map_, K key); \
|
||||
V *CMC_(PFX, _get_ref)(struct SNAME * _map_, K key); \
|
||||
/* Collection State */ \
|
||||
bool CMC_(PFX, _contains)(struct SNAME * _map_, K key); \
|
||||
bool CMC_(PFX, _empty)(struct SNAME * _map_); \
|
||||
bool CMC_(PFX, _full)(struct SNAME * _map_); \
|
||||
size_t CMC_(PFX, _count)(struct SNAME * _map_); \
|
||||
size_t CMC_(PFX, _key_count)(struct SNAME * _map_, K key); \
|
||||
size_t CMC_(PFX, _capacity)(struct SNAME * _map_); \
|
||||
double CMC_(PFX, _load)(struct SNAME * _map_); \
|
||||
int CMC_(PFX, _flag)(struct SNAME * _map_); \
|
||||
/* Collection Utility */ \
|
||||
bool CMC_(PFX, _resize)(struct SNAME * _map_, size_t capacity); \
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _map_); \
|
||||
bool CMC_(PFX, _equals)(struct SNAME * _map1_, struct SNAME * _map2_); \
|
||||
struct cmc_string CMC_(PFX, _to_string)(struct SNAME * _map_); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index); \
|
||||
/* Iterator Access */ \
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
#define CMC_CMC_HASHMULTIMAP_CORE_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
/* HashMultimap Structure */ \
|
||||
struct SNAME \
|
||||
{ \
|
||||
/* Array of linked list to entries */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * (*buffer)[2]; \
|
||||
\
|
||||
/* Current array capacity */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Current amount of keys */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Load factor in range (0.0, infinity) */ \
|
||||
double load; \
|
||||
\
|
||||
/* Flags indicating errors or success */ \
|
||||
int flag; \
|
||||
\
|
||||
/* Key function table */ \
|
||||
struct CMC_DEF_FKEY(SNAME) * f_key; \
|
||||
\
|
||||
/* Value function table */ \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val; \
|
||||
\
|
||||
/* Custom allocation functions */ \
|
||||
struct cmc_alloc_node *alloc; \
|
||||
\
|
||||
/* Custom callback functions */ \
|
||||
struct cmc_callbacks *callbacks; \
|
||||
}; \
|
||||
\
|
||||
/* HashMultimap Entry */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) \
|
||||
{ \
|
||||
/* Entry Key */ \
|
||||
K key; \
|
||||
\
|
||||
/* Entry Value */ \
|
||||
V value; \
|
||||
\
|
||||
/* Next entry on the linked list */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * next; \
|
||||
\
|
||||
/* Previous entry on the linked list */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * prev; \
|
||||
}; \
|
||||
\
|
||||
/* Key struct function table */ \
|
||||
struct CMC_DEF_FKEY(SNAME) \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(K, K); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
K (*cpy)(K); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, K); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(K); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(K); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(K, K); \
|
||||
}; \
|
||||
\
|
||||
/* Value struct function table */ \
|
||||
struct CMC_DEF_FVAL(SNAME) \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(V, V); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
V (*cpy)(V); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, V); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(V); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(V); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(V, V); \
|
||||
}; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \
|
||||
struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val); \
|
||||
struct SNAME *CMC_(PFX, _new_custom)( \
|
||||
size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val, struct cmc_alloc_node * alloc, \
|
||||
struct cmc_callbacks * callbacks); \
|
||||
void CMC_(PFX, _clear)(struct SNAME * _map_); \
|
||||
void CMC_(PFX, _free)(struct SNAME * _map_); \
|
||||
/* Customization of Allocation and Callbacks */ \
|
||||
void CMC_(PFX, _customize)(struct SNAME * _map_, \
|
||||
struct cmc_alloc_node * alloc, \
|
||||
struct cmc_callbacks * callbacks); \
|
||||
/* Collection Input and Output */ \
|
||||
bool CMC_(PFX, _insert)(struct SNAME * _map_, K key, V value); \
|
||||
bool CMC_(PFX, _update)(struct SNAME * _map_, K key, V new_value, \
|
||||
V * old_value); \
|
||||
size_t CMC_(PFX, _update_all)(struct SNAME * _map_, K key, V new_value, \
|
||||
V * *old_values); \
|
||||
bool CMC_(PFX, _remove)(struct SNAME * _map_, K key, V * out_value); \
|
||||
size_t CMC_(PFX, _remove_all)(struct SNAME * _map_, K key, \
|
||||
V * *out_values); \
|
||||
/* Element Access */ \
|
||||
bool CMC_(PFX, _max)(struct SNAME * _map_, K * key, V * value); \
|
||||
bool CMC_(PFX, _min)(struct SNAME * _map_, K * key, V * value); \
|
||||
V CMC_(PFX, _get)(struct SNAME * _map_, K key); \
|
||||
V *CMC_(PFX, _get_ref)(struct SNAME * _map_, K key); \
|
||||
/* Collection State */ \
|
||||
bool CMC_(PFX, _contains)(struct SNAME * _map_, K key); \
|
||||
bool CMC_(PFX, _empty)(struct SNAME * _map_); \
|
||||
bool CMC_(PFX, _full)(struct SNAME * _map_); \
|
||||
size_t CMC_(PFX, _count)(struct SNAME * _map_); \
|
||||
size_t CMC_(PFX, _key_count)(struct SNAME * _map_, K key); \
|
||||
size_t CMC_(PFX, _capacity)(struct SNAME * _map_); \
|
||||
double CMC_(PFX, _load)(struct SNAME * _map_); \
|
||||
int CMC_(PFX, _flag)(struct SNAME * _map_); \
|
||||
/* Collection Utility */ \
|
||||
bool CMC_(PFX, _resize)(struct SNAME * _map_, size_t capacity); \
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _map_); \
|
||||
bool CMC_(PFX, _equals)(struct SNAME * _map1_, struct SNAME * _map2_);
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Source
|
||||
@@ -1111,316 +1042,6 @@ static const char *cmc_cmc_string_fmt_hashmultimap = "struct %s<%s, %s> "
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct cmc_string CMC_(PFX, _to_string)(struct SNAME * _map_) \
|
||||
{ \
|
||||
struct cmc_string str; \
|
||||
struct SNAME *m_ = _map_; \
|
||||
\
|
||||
int n = snprintf( \
|
||||
str.s, cmc_string_len, cmc_cmc_string_fmt_hashmultimap, #SNAME, \
|
||||
#K, #V, m_, m_->buffer, m_->capacity, m_->count, m_->load, \
|
||||
m_->flag, m_->f_key, m_->f_val, m_->alloc, m_->callbacks); \
|
||||
\
|
||||
return n >= 0 ? str : (struct cmc_string){ 0 }; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _map_->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; \
|
||||
\
|
||||
while (scan != NULL) \
|
||||
{ \
|
||||
if (!_map_->f_key->str(fptr, scan->key) || \
|
||||
!_map_->f_val->str(fptr, scan->value)) \
|
||||
return false; \
|
||||
\
|
||||
scan = scan->next; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.curr_entry = NULL; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i][0] != NULL) \
|
||||
{ \
|
||||
iter.curr_entry = target->buffer[i][0]; \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.first; \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1][1] != NULL) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.curr_entry = NULL; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i][0] != NULL) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1][1] != NULL) \
|
||||
{ \
|
||||
iter.curr_entry = target->buffer[i - 1][1]; \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.last; \
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->first; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->curr_entry = iter->target->buffer[iter->first][0]; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->last; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
iter->curr_entry = iter->target->buffer[iter->last][1]; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->curr_entry->next != NULL) \
|
||||
{ \
|
||||
iter->curr_entry = iter->curr_entry->next; \
|
||||
iter->index++; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (iter->cursor == iter->last) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->cursor++; \
|
||||
\
|
||||
while (iter->target->buffer[iter->cursor][0] == NULL) \
|
||||
iter->cursor++; \
|
||||
\
|
||||
iter->curr_entry = iter->target->buffer[iter->cursor][0]; \
|
||||
\
|
||||
iter->index++; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->curr_entry->prev != NULL) \
|
||||
{ \
|
||||
iter->curr_entry = iter->curr_entry->prev; \
|
||||
iter->index--; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (iter->cursor == iter->first) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->cursor--; \
|
||||
\
|
||||
while (iter->target->buffer[iter->cursor][1] == NULL) \
|
||||
iter->cursor--; \
|
||||
\
|
||||
iter->curr_entry = iter->target->buffer[iter->cursor][1]; \
|
||||
\
|
||||
iter->index--; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (K){ 0 }; \
|
||||
\
|
||||
return iter->curr_entry->key; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->curr_entry->value; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->curr_entry->value); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) * \
|
||||
CMC_(PFX, _impl_new_entry)(struct SNAME * _map_, K key, V value) \
|
||||
{ \
|
||||
|
||||
@@ -113,6 +113,7 @@ static const char *cmc_cmc_string_fmt_deque = "struct %s<%s> "
|
||||
CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Deque Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
|
||||
+336
-1
@@ -16,7 +16,7 @@
|
||||
/**
|
||||
* All the EXT parts of CMC HashMap.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMAP_PARTS INIT, STR
|
||||
#define CMC_EXT_CMC_HASHMAP_PARTS INIT, ITER, STR
|
||||
|
||||
/* Used by STR */
|
||||
static const char *cmc_cmc_string_fmt_hashmap = "struct %s<%s, %s> "
|
||||
@@ -112,6 +112,341 @@ static const char *cmc_cmc_string_fmt_hashmap = "struct %s<%s, %s> "
|
||||
return _map_; \
|
||||
}
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMAP_ITER(BODY) \
|
||||
CMC_EXT_CMC_HASHMAP_ITER_HEADER(BODY) \
|
||||
CMC_EXT_CMC_HASHMAP_ITER_SOURCE(BODY)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_ITER_HEADER(BODY) \
|
||||
CMC_EXT_CMC_HASHMAP_ITER_HEADER_(CMC_PARAM_PFX(BODY), \
|
||||
CMC_PARAM_SNAME(BODY), CMC_PARAM_K(BODY), \
|
||||
CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_ITER_SOURCE(BODY) \
|
||||
CMC_EXT_CMC_HASHMAP_ITER_SOURCE_(CMC_PARAM_PFX(BODY), \
|
||||
CMC_PARAM_SNAME(BODY), CMC_PARAM_K(BODY), \
|
||||
CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_ITER_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
/* Hashmap Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target hashmap */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Cursor's position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* Keeps track of relative index to the iteration of elements */ \
|
||||
size_t index; \
|
||||
\
|
||||
/* The index of the first element */ \
|
||||
size_t first; \
|
||||
\
|
||||
/* The index of the last element */ \
|
||||
size_t last; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index); \
|
||||
/* Iterator Access */ \
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_ITER_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.first; \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.last; \
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->first; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->last; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = \
|
||||
&(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor++; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = \
|
||||
&(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor--; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (K){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].key; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].value; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor].value); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*
|
||||
|
||||
@@ -0,0 +1,472 @@
|
||||
/**
|
||||
* hashmultimap.h
|
||||
*
|
||||
* Creation Date: 29/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_HASHMULTIMAP_H
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC HashMultiMap.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_PARTS ITER, STR
|
||||
|
||||
/* Used by STR */
|
||||
static const char *cmc_cmc_string_fmt_hashmultimap = "struct %s<%s, %s> "
|
||||
"at %p { "
|
||||
"buffer:%p, "
|
||||
"capacity:%" PRIuMAX ", "
|
||||
"count:%" PRIuMAX ", "
|
||||
"load:%lf, "
|
||||
"flag:%d, "
|
||||
"f_key:%p, "
|
||||
"f_val:%p, "
|
||||
"alloc:%p, "
|
||||
"callbacks:%p }";
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_ITER(BODY) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER(BODY) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE(BODY)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER(BODY) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER_( \
|
||||
CMC_PARAM_PFX(BODY), CMC_PARAM_SNAME(BODY), CMC_PARAM_K(BODY), \
|
||||
CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE(BODY) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE_( \
|
||||
CMC_PARAM_PFX(BODY), CMC_PARAM_SNAME(BODY), CMC_PARAM_K(BODY), \
|
||||
CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target hashmultimap */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Current entry */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * curr_entry; \
|
||||
\
|
||||
/* Cursor`s position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* Keeps track of relative index to the iteration of elements */ \
|
||||
size_t index; \
|
||||
\
|
||||
/* The index of the first element */ \
|
||||
size_t first; \
|
||||
\
|
||||
/* The index of the last element */ \
|
||||
size_t last; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index); \
|
||||
/* Iterator Access */ \
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.curr_entry = NULL; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
iter.curr_entry = target->buffer[i][0]; \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.first; \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][1]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.curr_entry = NULL; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][1]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
iter.curr_entry = target->buffer[i - 1][1]; \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.last; \
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->first; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->curr_entry = iter->target->buffer[iter->first][0]; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->last; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
iter->curr_entry = iter->target->buffer[iter->last][1]; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->curr_entry->next != NULL) \
|
||||
{ \
|
||||
iter->curr_entry = iter->curr_entry->next; \
|
||||
iter->index++; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (iter->cursor == iter->last) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->cursor++; \
|
||||
\
|
||||
while (iter->target->buffer[iter->cursor][0] == NULL) \
|
||||
iter->cursor++; \
|
||||
\
|
||||
iter->curr_entry = iter->target->buffer[iter->cursor][0]; \
|
||||
\
|
||||
iter->index++; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->curr_entry->prev != NULL) \
|
||||
{ \
|
||||
iter->curr_entry = iter->curr_entry->prev; \
|
||||
iter->index--; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (iter->cursor == iter->first) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->cursor--; \
|
||||
\
|
||||
while (iter->target->buffer[iter->cursor][1] == NULL) \
|
||||
iter->cursor--; \
|
||||
\
|
||||
iter->curr_entry = iter->target->buffer[iter->cursor][1]; \
|
||||
\
|
||||
iter->index--; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (K){ 0 }; \
|
||||
\
|
||||
return iter->curr_entry->key; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->curr_entry->value; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->curr_entry->value); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_STR(BODY) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER(BODY) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE(BODY)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER(BODY) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER_(CMC_PARAM_PFX(BODY), \
|
||||
CMC_PARAM_SNAME(BODY), \
|
||||
CMC_PARAM_K(BODY), CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE(BODY) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE_(CMC_PARAM_PFX(BODY), \
|
||||
CMC_PARAM_SNAME(BODY), \
|
||||
CMC_PARAM_K(BODY), CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, \
|
||||
const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *m_ = _map_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, cmc_cmc_string_fmt_hashmultimap, \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(K), \
|
||||
CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, \
|
||||
m_->count, m_->load, m_->flag, m_->f_key, \
|
||||
m_->f_val, m_->alloc, m_->callbacks); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, \
|
||||
const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
size_t last = 0; \
|
||||
for (size_t i = _map_->capacity; i > 0; i--) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i - 1][1]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = 0; i < _map_->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; \
|
||||
\
|
||||
while (scan != NULL) \
|
||||
{ \
|
||||
if (!_map_->f_key->str(fptr, scan->key)) \
|
||||
return false; \
|
||||
\
|
||||
fprintf(fptr, "%s", key_val_sep); \
|
||||
\
|
||||
if (!_map_->f_val->str(fptr, scan->value)) \
|
||||
return false; \
|
||||
\
|
||||
scan = scan->next; \
|
||||
\
|
||||
if (i + 1 < last) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_HASHMULTIMAP_H */
|
||||
+34
-33
@@ -12,42 +12,43 @@
|
||||
#define CMC_MACRO_COLLECTIONS_H
|
||||
|
||||
// clang-format off
|
||||
#include "cmc/bitset.h" /* Added in 30/04/2020 */
|
||||
#include "cmc/deque.h" /* Added in 20/03/2019 */
|
||||
#include "cmc/hashbidimap.h" /* Added in 26/09/2019 */
|
||||
#include "cmc/hashmap.h" /* Added in 03/04/2019 */
|
||||
#include "cmc/hashmultimap.h" /* Added in 26/04/2019 */
|
||||
#include "cmc/hashmultiset.h" /* Added in 10/04/2019 */
|
||||
#include "cmc/hashset.h" /* Added in 01/04/2019 */
|
||||
#include "cmc/heap.h" /* Added in 25/03/2019 */
|
||||
#include "cmc/intervalheap.h" /* Added in 06/07/2019 */
|
||||
#include "cmc/linkedlist.h" /* Added in 22/03/2019 */
|
||||
#include "cmc/list.h" /* Added in 12/02/2019 */
|
||||
#include "cmc/queue.h" /* Added in 15/02/2019 */
|
||||
#include "cmc/sortedlist.h" /* Added in 17/09/2019 */
|
||||
#include "cmc/stack.h" /* Added in 14/02/2019 */
|
||||
#include "cmc/treemap.h" /* Added in 28/03/2019 */
|
||||
#include "cmc/treeset.h" /* Added in 27/03/2019 */
|
||||
#include "cmc/bitset.h" /* Added in 30/04/2020 */
|
||||
#include "cmc/deque.h" /* Added in 20/03/2019 */
|
||||
#include "cmc/hashbidimap.h" /* Added in 26/09/2019 */
|
||||
#include "cmc/hashmap.h" /* Added in 03/04/2019 */
|
||||
#include "cmc/hashmultimap.h" /* Added in 26/04/2019 */
|
||||
#include "cmc/hashmultiset.h" /* Added in 10/04/2019 */
|
||||
#include "cmc/hashset.h" /* Added in 01/04/2019 */
|
||||
#include "cmc/heap.h" /* Added in 25/03/2019 */
|
||||
#include "cmc/intervalheap.h" /* Added in 06/07/2019 */
|
||||
#include "cmc/linkedlist.h" /* Added in 22/03/2019 */
|
||||
#include "cmc/list.h" /* Added in 12/02/2019 */
|
||||
#include "cmc/queue.h" /* Added in 15/02/2019 */
|
||||
#include "cmc/sortedlist.h" /* Added in 17/09/2019 */
|
||||
#include "cmc/stack.h" /* Added in 14/02/2019 */
|
||||
#include "cmc/treemap.h" /* Added in 28/03/2019 */
|
||||
#include "cmc/treeset.h" /* Added in 27/03/2019 */
|
||||
|
||||
#include "cor/alloc.h" /* Added in 24/05/2020 */
|
||||
#include "cor/bitset.h" /* Added in 20/05/2020 */
|
||||
#include "cor/callbacks.h" /* Added in 24/05/2020 */
|
||||
#include "cor/core.h" /* Added in 17/03/2020 */
|
||||
#include "cor/flags.h" /* Added in 14/05/2020 */
|
||||
#include "cor/ftable.h" /* Added in 27/05/2020 */
|
||||
#include "cor/hashtable.h" /* Added in 17/03/2020 */
|
||||
#include "cor/alloc.h" /* Added in 24/05/2020 */
|
||||
#include "cor/bitset.h" /* Added in 20/05/2020 */
|
||||
#include "cor/callbacks.h" /* Added in 24/05/2020 */
|
||||
#include "cor/core.h" /* Added in 17/03/2020 */
|
||||
#include "cor/flags.h" /* Added in 14/05/2020 */
|
||||
#include "cor/ftable.h" /* Added in 27/05/2020 */
|
||||
#include "cor/hashtable.h" /* Added in 17/03/2020 */
|
||||
|
||||
#include "ext/cmc/deque.h" /* Added in 25/05/2020 */
|
||||
#include "ext/cmc/hashmap.h" /* Added in 25/05/2020 */
|
||||
#include "ext/cmc/deque.h" /* Added in 25/05/2020 */
|
||||
#include "ext/cmc/hashmap.h" /* Added in 25/05/2020 */
|
||||
#include "ext/cmc/hashmultimap.h" /* Added in 29/05/2020 */
|
||||
|
||||
#include "utl/assert.h" /* Added in 27/06/2019 */
|
||||
#include "utl/foreach.h" /* Added in 25/02/2019 */
|
||||
#include "utl/futils.h" /* Added in 15/04/2020 */
|
||||
#include "utl/log.h" /* Added in 21/06/2019 */
|
||||
#include "utl/mutex.h" /* Added in 14/05/2020 */
|
||||
#include "utl/test.h" /* Added in 26/06/2019 */
|
||||
#include "utl/thread.h" /* Added in 14/05/2020 */
|
||||
#include "utl/timer.h" /* Added in 12/04/2019 */
|
||||
#include "utl/assert.h" /* Added in 27/06/2019 */
|
||||
#include "utl/foreach.h" /* Added in 25/02/2019 */
|
||||
#include "utl/futils.h" /* Added in 15/04/2020 */
|
||||
#include "utl/log.h" /* Added in 21/06/2019 */
|
||||
#include "utl/mutex.h" /* Added in 14/05/2020 */
|
||||
#include "utl/test.h" /* Added in 26/06/2019 */
|
||||
#include "utl/thread.h" /* Added in 14/05/2020 */
|
||||
#include "utl/timer.h" /* Added in 12/04/2019 */
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
|
||||
@@ -361,27 +361,6 @@ _Bool d_equals(struct deque *_deque1_, struct deque *_deque2_)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
struct cmc_string d_to_string(struct deque *_deque_)
|
||||
{
|
||||
struct cmc_string str;
|
||||
struct deque *d_ = _deque_;
|
||||
int n = snprintf(str.s, cmc_string_len, cmc_cmc_string_fmt_deque,
|
||||
"CMC_PARAM_SNAME((d, deque, , , size_t))",
|
||||
"CMC_PARAM_V((d, deque, , , size_t))", d_, d_->buffer,
|
||||
d_->capacity, d_->count, d_->front, d_->back, d_->flag,
|
||||
d_->f_val, d_->alloc, d_->callbacks);
|
||||
return n >= 0 ? str : (struct cmc_string){ 0 };
|
||||
}
|
||||
_Bool d_print(struct deque *_deque_, FILE *fptr)
|
||||
{
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++)
|
||||
{
|
||||
if (!_deque_->f_val->str(fptr, _deque_->buffer[i]))
|
||||
return 0;
|
||||
i = (i + 1) % _deque_->capacity;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
struct deque_iter d_iter_start(struct deque *target)
|
||||
{
|
||||
struct deque_iter iter;
|
||||
|
||||
@@ -552,32 +552,6 @@ _Bool hm_equals(struct hashmap *_map1_, struct hashmap *_map2_)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
struct cmc_string hm_to_string(struct hashmap *_map_)
|
||||
{
|
||||
struct cmc_string str;
|
||||
struct hashmap *m_ = _map_;
|
||||
int n = snprintf(str.s, cmc_string_len, cmc_cmc_string_fmt_hashmap,
|
||||
"CMC_PARAM_SNAME((hm, hashmap, , size_t, size_t))",
|
||||
"CMC_PARAM_K((hm, hashmap, , size_t, size_t))",
|
||||
"CMC_PARAM_V((hm, hashmap, , size_t, size_t))", m_,
|
||||
m_->buffer, m_->capacity, m_->count, m_->load, m_->flag,
|
||||
m_->f_key, m_->f_val, m_->alloc, m_->callbacks);
|
||||
return n >= 0 ? str : (struct cmc_string){ 0 };
|
||||
}
|
||||
_Bool hm_print(struct hashmap *_map_, FILE *fptr)
|
||||
{
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
struct hashmap_entry *entry = &(_map_->buffer[i]);
|
||||
if (entry->state == CMC_ES_FILLED)
|
||||
{
|
||||
if (!_map_->f_key->str(fptr, entry->key) ||
|
||||
!_map_->f_val->str(fptr, entry->value))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
struct hashmap_iter hm_iter_start(struct hashmap *target)
|
||||
{
|
||||
struct hashmap_iter iter;
|
||||
|
||||
@@ -720,33 +720,6 @@ _Bool hmm_equals(struct hashmultimap *_map1_, struct hashmultimap *_map2_)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
struct cmc_string hmm_to_string(struct hashmultimap *_map_)
|
||||
{
|
||||
struct cmc_string str;
|
||||
struct hashmultimap *m_ = _map_;
|
||||
int n = snprintf(str.s, cmc_string_len, cmc_cmc_string_fmt_hashmultimap,
|
||||
"CMC_PARAM_SNAME((hmm, hashmultimap, , size_t, size_t))",
|
||||
"CMC_PARAM_K((hmm, hashmultimap, , size_t, size_t))",
|
||||
"CMC_PARAM_V((hmm, hashmultimap, , size_t, size_t))", m_,
|
||||
m_->buffer, m_->capacity, m_->count, m_->load, m_->flag,
|
||||
m_->f_key, m_->f_val, m_->alloc, m_->callbacks);
|
||||
return n >= 0 ? str : (struct cmc_string){ 0 };
|
||||
}
|
||||
_Bool hmm_print(struct hashmultimap *_map_, FILE *fptr)
|
||||
{
|
||||
for (size_t i = 0; i < _map_->capacity; i++)
|
||||
{
|
||||
struct hashmultimap_entry *scan = _map_->buffer[i][0];
|
||||
while (scan != ((void *)0))
|
||||
{
|
||||
if (!_map_->f_key->str(fptr, scan->key) ||
|
||||
!_map_->f_val->str(fptr, scan->value))
|
||||
return 0;
|
||||
scan = scan->next;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
struct hashmultimap_iter hmm_iter_start(struct hashmultimap *target)
|
||||
{
|
||||
struct hashmultimap_iter iter;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
#ifndef CMC_UNIT_TEST_UTL__
|
||||
#define CMC_UNIT_TEST_UTL__
|
||||
|
||||
/**
|
||||
* TEMPORARY
|
||||
*/
|
||||
struct cmc_string
|
||||
{
|
||||
char s[400];
|
||||
};
|
||||
static const size_t cmc_string_len = 400;
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
+12
-2
@@ -3,8 +3,9 @@
|
||||
#include "macro_collections.h"
|
||||
|
||||
// clang-format off
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, DEQUE, ( d, deque, , , int))
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, HASHMAP, ( hm, hashmap, , int, int))
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, DEQUE, ( d, deque, , , int))
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, HASHMAP, ( hm, hashmap, , int, int))
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, HASHMULTIMAP, (hmm, hashmultimap, , int, int))
|
||||
|
||||
struct
|
||||
{
|
||||
@@ -21,16 +22,22 @@ int main(void)
|
||||
struct deque *d = d_new(100, (struct deque_fval *)&int_ftab);
|
||||
struct hashmap *hm = hm_new(100, 0.6, (struct hashmap_fkey *)&int_ftab,
|
||||
(struct hashmap_fval *)&int_ftab);
|
||||
struct hashmultimap *hmm = hmm_new(100, 0.6,
|
||||
(struct hashmultimap_fkey *)&int_ftab,
|
||||
(struct hashmultimap_fval *)&int_ftab);
|
||||
|
||||
d_to_string(d, stdout);
|
||||
d_print(d, stdout, "\n[ ", ", ", " ]\n");
|
||||
hm_to_string(hm, stdout);
|
||||
hm_print(hm, stdout, "\n[ {", "}, {", "} ]\n", " : ");
|
||||
hmm_to_string(hmm, stdout);
|
||||
hmm_print(hmm, stdout, "\n[ {", "}, {", "} ]\n", " : ");
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
d_push_back(d, i);
|
||||
hm_insert(hm, i, i);
|
||||
hmm_insert(hmm, i, i);
|
||||
}
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
@@ -39,9 +46,12 @@ int main(void)
|
||||
d_print(d, stdout, "\n[ ", ", ", " ]\n");
|
||||
hm_to_string(hm, stdout);
|
||||
hm_print(hm, stdout, "\n[ {", "}, {", "} ]\n", " : ");
|
||||
hmm_to_string(hmm, stdout);
|
||||
hmm_print(hmm, stdout, "\n[ {", "}, {", "} ]\n", " : ");
|
||||
|
||||
d_free(d);
|
||||
hm_free(hm);
|
||||
hmm_free(hmm);
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
Reference in new issue
Block a user