Moving more things to EXT
This commit is contained in:
1 parent
97f46b3a81
commit
63eb525406
10 files changed
+1902
-1814
No files matched your search
+1
-298
@@ -161,28 +161,7 @@
|
||||
/* Collection Utility */ \
|
||||
bool CMC_(PFX, _resize)(struct SNAME * _set_, size_t capacity); \
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _set_); \
|
||||
bool CMC_(PFX, _equals)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
\
|
||||
/* Set Operations */ \
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _summation)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_);
|
||||
bool CMC_(PFX, _equals)(struct SNAME * _set1_, struct SNAME * _set2_);
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Source
|
||||
@@ -810,282 +789,6 @@
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); \
|
||||
CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter1); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter1); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
size_t max_ = m1 > m2 ? m1 : m2; \
|
||||
\
|
||||
CMC_(PFX, _update)(_set_r_, value, max_); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); \
|
||||
CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter2); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _impl_multiplicity_of)(_set1_, value); \
|
||||
size_t m2 = CMC_(PFX, _iter_multiplicity)(&iter2); \
|
||||
size_t max_ = m1 > m2 ? m1 : m2; \
|
||||
\
|
||||
CMC_(PFX, _update)(_set_r_, value, max_); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct SNAME *_set_A_ = \
|
||||
_set1_->count < _set2_->count ? _set1_ : _set2_; \
|
||||
struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_A_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set_B_, value); \
|
||||
size_t max_ = m1 < m2 ? m1 : m2; \
|
||||
\
|
||||
CMC_(PFX, _update)(_set_r_, value, max_); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 > m2) \
|
||||
CMC_(PFX, _update)(_set_r_, value, m1 - m2); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _summation)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); \
|
||||
CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert_many) \
|
||||
(_set_r_, CMC_(PFX, _iter_value)(&iter1), \
|
||||
CMC_(PFX, _iter_multiplicity)(&iter1)); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); \
|
||||
CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert_many) \
|
||||
(_set_r_, CMC_(PFX, _iter_value)(&iter2), \
|
||||
CMC_(PFX, _iter_multiplicity)(&iter2)); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); \
|
||||
CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter1); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter1); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 != m2) \
|
||||
{ \
|
||||
if (m1 > m2) \
|
||||
CMC_(PFX, _update)(_set_r_, value, m1 - m2); \
|
||||
else \
|
||||
CMC_(PFX, _update)(_set_r_, value, m2 - m1); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); \
|
||||
CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter2); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _impl_multiplicity_of)(_set1_, value); \
|
||||
size_t m2 = CMC_(PFX, _iter_multiplicity)(&iter2); \
|
||||
\
|
||||
if (m1 != m2) \
|
||||
{ \
|
||||
if (m1 > m2) \
|
||||
CMC_(PFX, _update)(_set_r_, value, m1 - m2); \
|
||||
else \
|
||||
CMC_(PFX, _update)(_set_r_, value, m2 - m1); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
if (_set1_->count > _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 > m2) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
if (_set1_->count >= _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(_set2_)) \
|
||||
return true; \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 >= m2) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_proper_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) != NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
static size_t CMC_(PFX, _impl_multiplicity_of)(struct SNAME * _set_, \
|
||||
V value) \
|
||||
{ \
|
||||
|
||||
+96
-369
@@ -47,121 +47,102 @@
|
||||
/* -------------------------------------------------------------------------
|
||||
* Header
|
||||
* ------------------------------------------------------------------------- */
|
||||
#define CMC_CMC_HASHSET_CORE_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Hashset Structure */ \
|
||||
struct SNAME \
|
||||
{ \
|
||||
/* Array of Entries */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * buffer; \
|
||||
\
|
||||
/* Current Array Capcity */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Current amount of elements */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Load factor in range (0.0, 1.0) */ \
|
||||
double load; \
|
||||
\
|
||||
/* Flags indicating errors or success */ \
|
||||
int flag; \
|
||||
\
|
||||
/* 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; \
|
||||
}; \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) \
|
||||
{ \
|
||||
/* 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; \
|
||||
}; \
|
||||
\
|
||||
/* Value struct function table */ \
|
||||
struct CMC_DEF_FVAL(SNAME) \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
CMC_DEF_FTAB_CMP(V); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
CMC_DEF_FTAB_CPY(V); \
|
||||
\
|
||||
/* To string function */ \
|
||||
CMC_DEF_FTAB_STR(V); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
CMC_DEF_FTAB_FREE(V); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
CMC_DEF_FTAB_HASH(V); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
CMC_DEF_FTAB_PRI(V); \
|
||||
}; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val); \
|
||||
struct SNAME *CMC_(PFX, _new_custom)( \
|
||||
size_t capacity, double load, struct CMC_DEF_FVAL(SNAME) * f_val, \
|
||||
struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); \
|
||||
void CMC_(PFX, _clear)(struct SNAME * _set_); \
|
||||
void CMC_(PFX, _free)(struct SNAME * _set_); \
|
||||
/* Customization of Allocation and Callbacks */ \
|
||||
void CMC_(PFX, _customize)(struct SNAME * _set_, \
|
||||
struct cmc_alloc_node * alloc, \
|
||||
struct cmc_callbacks * callbacks); \
|
||||
/* Collection Input and Output */ \
|
||||
bool CMC_(PFX, _insert)(struct SNAME * _set_, V value); \
|
||||
bool CMC_(PFX, _remove)(struct SNAME * _set_, V value); \
|
||||
/* Element Access */ \
|
||||
bool CMC_(PFX, _max)(struct SNAME * _set_, V * value); \
|
||||
bool CMC_(PFX, _min)(struct SNAME * _set_, V * value); \
|
||||
/* Collection State */ \
|
||||
bool CMC_(PFX, _contains)(struct SNAME * _set_, V value); \
|
||||
bool CMC_(PFX, _empty)(struct SNAME * _set_); \
|
||||
bool CMC_(PFX, _full)(struct SNAME * _set_); \
|
||||
size_t CMC_(PFX, _count)(struct SNAME * _set_); \
|
||||
size_t CMC_(PFX, _capacity)(struct SNAME * _set_); \
|
||||
double CMC_(PFX, _load)(struct SNAME * _set_); \
|
||||
int CMC_(PFX, _flag)(struct SNAME * _set_); \
|
||||
/* Collection Utility */ \
|
||||
bool CMC_(PFX, _resize)(struct SNAME * _set_, size_t capacity); \
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _set_); \
|
||||
bool CMC_(PFX, _equals)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
\
|
||||
/* Set Operations */ \
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_);
|
||||
#define CMC_CMC_HASHSET_CORE_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Hashset Structure */ \
|
||||
struct SNAME \
|
||||
{ \
|
||||
/* Array of Entries */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * buffer; \
|
||||
\
|
||||
/* Current Array Capcity */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Current amount of elements */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Load factor in range (0.0, 1.0) */ \
|
||||
double load; \
|
||||
\
|
||||
/* Flags indicating errors or success */ \
|
||||
int flag; \
|
||||
\
|
||||
/* 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; \
|
||||
}; \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) \
|
||||
{ \
|
||||
/* 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; \
|
||||
}; \
|
||||
\
|
||||
/* Value struct function table */ \
|
||||
struct CMC_DEF_FVAL(SNAME) \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
CMC_DEF_FTAB_CMP(V); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
CMC_DEF_FTAB_CPY(V); \
|
||||
\
|
||||
/* To string function */ \
|
||||
CMC_DEF_FTAB_STR(V); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
CMC_DEF_FTAB_FREE(V); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
CMC_DEF_FTAB_HASH(V); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
CMC_DEF_FTAB_PRI(V); \
|
||||
}; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val); \
|
||||
struct SNAME *CMC_(PFX, _new_custom)( \
|
||||
size_t capacity, double load, struct CMC_DEF_FVAL(SNAME) * f_val, \
|
||||
struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); \
|
||||
void CMC_(PFX, _clear)(struct SNAME * _set_); \
|
||||
void CMC_(PFX, _free)(struct SNAME * _set_); \
|
||||
/* Customization of Allocation and Callbacks */ \
|
||||
void CMC_(PFX, _customize)(struct SNAME * _set_, \
|
||||
struct cmc_alloc_node * alloc, \
|
||||
struct cmc_callbacks * callbacks); \
|
||||
/* Collection Input and Output */ \
|
||||
bool CMC_(PFX, _insert)(struct SNAME * _set_, V value); \
|
||||
bool CMC_(PFX, _remove)(struct SNAME * _set_, V value); \
|
||||
/* Element Access */ \
|
||||
bool CMC_(PFX, _max)(struct SNAME * _set_, V * value); \
|
||||
bool CMC_(PFX, _min)(struct SNAME * _set_, V * value); \
|
||||
/* Collection State */ \
|
||||
bool CMC_(PFX, _contains)(struct SNAME * _set_, V value); \
|
||||
bool CMC_(PFX, _empty)(struct SNAME * _set_); \
|
||||
bool CMC_(PFX, _full)(struct SNAME * _set_); \
|
||||
size_t CMC_(PFX, _count)(struct SNAME * _set_); \
|
||||
size_t CMC_(PFX, _capacity)(struct SNAME * _set_); \
|
||||
double CMC_(PFX, _load)(struct SNAME * _set_); \
|
||||
int CMC_(PFX, _flag)(struct SNAME * _set_); \
|
||||
/* Collection Utility */ \
|
||||
bool CMC_(PFX, _resize)(struct SNAME * _set_, size_t capacity); \
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _set_); \
|
||||
bool CMC_(PFX, _equals)(struct SNAME * _set1_, struct SNAME * _set2_);
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Source
|
||||
@@ -669,260 +650,6 @@
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
/* TODO turn this into a normal loop and check for errors */ \
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); \
|
||||
CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert)(_set_r_, CMC_(PFX, _iter_value)(&iter1)); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); \
|
||||
CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert)(_set_r_, CMC_(PFX, _iter_value)(&iter2)); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *_set_A_ = \
|
||||
_set1_->count < _set2_->count ? _set1_ : _set2_; \
|
||||
struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_A_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set_B_, value) != NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); \
|
||||
CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter1); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); \
|
||||
CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter2); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set1_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a subset of _set2_ ? */ \
|
||||
/* A set X is a subset of a set Y when: X <= Y */ \
|
||||
/* If X is a subset of Y, then Y is a superset of X */ \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_OK; \
|
||||
_set2_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
/* If the cardinality of _set1_ is greater than that of _set2_, */ \
|
||||
/* then it is safe to say that _set1_ can't be a subset of _set2_ */ \
|
||||
if (_set1_->count > _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
/* The empty set is a subset of all sets */ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a superset of _set2_ ? */ \
|
||||
/* A set X is a superset of a set Y when: X >= Y */ \
|
||||
/* If X is a superset of Y, then Y is a subset of X */ \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a proper subset of _set2_ ? */ \
|
||||
/* A set X is a proper subset of a set Y when: X < Y */ \
|
||||
/* If X is a proper subset of Y, then Y is a proper superset of X */ \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_OK; \
|
||||
_set2_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
/* If the cardinality of _set1_ is greater than or equal to that of */ \
|
||||
/* _set2_, then it is safe to say that _set1_ can't be a proper */ \
|
||||
/* subset of _set2_ */ \
|
||||
if (_set1_->count >= _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
{ \
|
||||
/* The empty set is a proper subset of all non-empty sets */ \
|
||||
if (!CMC_(PFX, _empty)(_set2_)) \
|
||||
return true; \
|
||||
/* The empty set is not a proper subset of itself (this is true */ \
|
||||
/* for any set) */ \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a proper superset of _set2_ ? */ \
|
||||
/* A set X is a proper superset of a set Y when: X > Y */ \
|
||||
/* If X is a proper superset of Y, then Y is a proper subset of X */ \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_proper_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a disjointset of _set2_ ? */ \
|
||||
/* A set X is a disjointset of a set Y if their intersection is empty, */ \
|
||||
/* that is, if there are no elements in common between the two */ \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_OK; \
|
||||
_set2_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
/* The intersection of an empty set with any other set will result */ \
|
||||
/* in an empty set */ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) != NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
static struct CMC_DEF_ENTRY(SNAME) * \
|
||||
CMC_(PFX, _impl_get_entry)(struct SNAME * _set_, V value) \
|
||||
{ \
|
||||
|
||||
+577
-1103
File diff suppressed because it is too large.
Load diff
+317
-1
@@ -16,7 +16,7 @@
|
||||
/**
|
||||
* All the EXT parts of CMC HashMultiSet.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTISET_PARTS ITER, STR
|
||||
#define CMC_EXT_CMC_HASHMULTISET_PARTS ITER, SETF, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
@@ -342,6 +342,322 @@
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* SETF
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTISET_SETF(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_SETF_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_SETF_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_SETF_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_SETF_HEADER_( \
|
||||
CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_SETF_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_SETF_SOURCE_( \
|
||||
CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_SETF_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Set Operations */ \
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _summation)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_SETF_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); \
|
||||
CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter1); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter1); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
size_t max_ = m1 > m2 ? m1 : m2; \
|
||||
\
|
||||
CMC_(PFX, _update)(_set_r_, value, max_); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); \
|
||||
CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter2); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _impl_multiplicity_of)(_set1_, value); \
|
||||
size_t m2 = CMC_(PFX, _iter_multiplicity)(&iter2); \
|
||||
size_t max_ = m1 > m2 ? m1 : m2; \
|
||||
\
|
||||
CMC_(PFX, _update)(_set_r_, value, max_); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct SNAME *_set_A_ = \
|
||||
_set1_->count < _set2_->count ? _set1_ : _set2_; \
|
||||
struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_A_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set_B_, value); \
|
||||
size_t max_ = m1 < m2 ? m1 : m2; \
|
||||
\
|
||||
CMC_(PFX, _update)(_set_r_, value, max_); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 > m2) \
|
||||
CMC_(PFX, _update)(_set_r_, value, m1 - m2); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _summation)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); \
|
||||
CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert_many) \
|
||||
(_set_r_, CMC_(PFX, _iter_value)(&iter1), \
|
||||
CMC_(PFX, _iter_multiplicity)(&iter1)); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); \
|
||||
CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert_many) \
|
||||
(_set_r_, CMC_(PFX, _iter_value)(&iter2), \
|
||||
CMC_(PFX, _iter_multiplicity)(&iter2)); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); \
|
||||
CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter1); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter1); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 != m2) \
|
||||
{ \
|
||||
if (m1 > m2) \
|
||||
CMC_(PFX, _update)(_set_r_, value, m1 - m2); \
|
||||
else \
|
||||
CMC_(PFX, _update)(_set_r_, value, m2 - m1); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); \
|
||||
CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter2); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _impl_multiplicity_of)(_set1_, value); \
|
||||
size_t m2 = CMC_(PFX, _iter_multiplicity)(&iter2); \
|
||||
\
|
||||
if (m1 != m2) \
|
||||
{ \
|
||||
if (m1 > m2) \
|
||||
CMC_(PFX, _update)(_set_r_, value, m1 - m2); \
|
||||
else \
|
||||
CMC_(PFX, _update)(_set_r_, value, m2 - m1); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
if (_set1_->count > _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 > m2) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
if (_set1_->count >= _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(_set2_)) \
|
||||
return true; \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 >= m2) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_proper_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) != NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
|
||||
+293
-1
@@ -16,7 +16,7 @@
|
||||
/**
|
||||
* All the EXT parts of CMC HashSet.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHSET_PARTS ITER, STR
|
||||
#define CMC_EXT_CMC_HASHSET_PARTS ITER, SETF, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
@@ -333,6 +333,298 @@
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* SETF
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHSET_SETF(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_SETF_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_SETF_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_SETF_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_SETF_HEADER_( \
|
||||
CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_SETF_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_SETF_SOURCE_( \
|
||||
CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_SETF_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Set Operations */ \
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_);
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_SETF_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
/* TODO turn this into a normal loop and check for errors */ \
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); \
|
||||
CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert)(_set_r_, CMC_(PFX, _iter_value)(&iter1)); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); \
|
||||
CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert)(_set_r_, CMC_(PFX, _iter_value)(&iter2)); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *_set_A_ = \
|
||||
_set1_->count < _set2_->count ? _set1_ : _set2_; \
|
||||
struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_A_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set_B_, value) != NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, \
|
||||
_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); \
|
||||
CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter1); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); \
|
||||
CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter2); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set1_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
_set_r_->callbacks = _set1_->callbacks; \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a subset of _set2_ ? */ \
|
||||
/* A set X is a subset of a set Y when: X <= Y */ \
|
||||
/* If X is a subset of Y, then Y is a superset of X */ \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_OK; \
|
||||
_set2_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
/* If the cardinality of _set1_ is greater than that of _set2_, */ \
|
||||
/* then it is safe to say that _set1_ can't be a subset of _set2_ */ \
|
||||
if (_set1_->count > _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
/* The empty set is a subset of all sets */ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a superset of _set2_ ? */ \
|
||||
/* A set X is a superset of a set Y when: X >= Y */ \
|
||||
/* If X is a superset of Y, then Y is a subset of X */ \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a proper subset of _set2_ ? */ \
|
||||
/* A set X is a proper subset of a set Y when: X < Y */ \
|
||||
/* If X is a proper subset of Y, then Y is a proper superset of X */ \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_OK; \
|
||||
_set2_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
/* If the cardinality of _set1_ is greater than or equal to that of */ \
|
||||
/* _set2_, then it is safe to say that _set1_ can't be a proper */ \
|
||||
/* subset of _set2_ */ \
|
||||
if (_set1_->count >= _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
{ \
|
||||
/* The empty set is a proper subset of all non-empty sets */ \
|
||||
if (!CMC_(PFX, _empty)(_set2_)) \
|
||||
return true; \
|
||||
/* The empty set is not a proper subset of itself (this is true */ \
|
||||
/* for any set) */ \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a proper superset of _set2_ ? */ \
|
||||
/* A set X is a proper superset of a set Y when: X > Y */ \
|
||||
/* If X is a proper superset of Y, then Y is a proper subset of X */ \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_proper_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a disjointset of _set2_ ? */ \
|
||||
/* A set X is a disjointset of a set Y if their intersection is empty, */ \
|
||||
/* that is, if there are no elements in common between the two */ \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_OK; \
|
||||
_set2_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
/* The intersection of an empty set with any other set will result */ \
|
||||
/* in an empty set */ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) != NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,607 @@
|
||||
/**
|
||||
* ext/cmc/linkedlist.h
|
||||
*
|
||||
* Creation Date: 26/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_LINKEDLIST_H
|
||||
#define CMC_EXT_CMC_LINKEDLIST_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC LinkedList.
|
||||
*/
|
||||
#define CMC_EXT_CMC_LINKEDLIST_PARTS ITER, NODE, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_LINKEDLIST_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_ITER_HEADER_( \
|
||||
CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_ITER_SOURCE_( \
|
||||
CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* LinkedList Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target Linked List */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Cursor's current node */ \
|
||||
struct CMC_DEF_NODE(SNAME) * cursor; \
|
||||
\
|
||||
/* Keeps track of relative index to the iteration of elements */ \
|
||||
size_t index; \
|
||||
\
|
||||
/* 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 */ \
|
||||
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); \
|
||||
struct CMC_DEF_NODE(SNAME) * \
|
||||
CMC_(PFX, _iter_node)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = target->head; \
|
||||
iter.index = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
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 = target->tail; \
|
||||
iter.index = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
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->target->head; \
|
||||
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->target->tail; \
|
||||
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->cursor->next == NULL) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor = iter->cursor->next; \
|
||||
iter->index++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor->prev == NULL) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor = iter->cursor->prev; \
|
||||
iter->index--; \
|
||||
\
|
||||
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->cursor->next == NULL) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->index += steps; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
iter->cursor = iter->cursor->next; \
|
||||
\
|
||||
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->cursor->prev == NULL) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->index -= steps; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
iter->cursor = iter->cursor->prev; \
|
||||
\
|
||||
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; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->cursor->value; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->cursor->value); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * \
|
||||
CMC_(PFX, _iter_node)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->cursor; \
|
||||
}
|
||||
|
||||
/**
|
||||
* NODE
|
||||
*/
|
||||
#define CMC_EXT_CMC_LINKEDLIST_NODE(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_NODE_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_NODE_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_NODE_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_NODE_HEADER_( \
|
||||
CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_NODE_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_NODE_SOURCE_( \
|
||||
CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_NODE_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Node Allocation and Deallocation */ \
|
||||
struct CMC_DEF_NODE(SNAME) * \
|
||||
CMC_(PFX, _new_node)(struct SNAME * _list_, V value); \
|
||||
void CMC_(PFX, _free_node)(struct SNAME * _list_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_); \
|
||||
/* Node Access Relative to a Linked List */ \
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _head)(struct SNAME * _list_); \
|
||||
struct CMC_DEF_NODE(SNAME) * \
|
||||
CMC_(PFX, _get_node)(struct SNAME * _list_, size_t index); \
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _tail)(struct SNAME * _list_); \
|
||||
/* Input and Output Relative to a Node */ \
|
||||
bool CMC_(PFX, _add_next)(struct SNAME * _owner_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_, V value); \
|
||||
bool CMC_(PFX, _add_prev)(struct SNAME * _owner_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_, V value); \
|
||||
bool CMC_(PFX, _del_next)(struct SNAME * _owner_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_); \
|
||||
bool CMC_(PFX, _del_curr)(struct SNAME * _owner_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_); \
|
||||
bool CMC_(PFX, _del_prev)(struct SNAME * _owner_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_); \
|
||||
/* Node Access Relative to a Linked List Node */ \
|
||||
struct CMC_DEF_NODE(SNAME) * \
|
||||
CMC_(PFX, _next_node)(struct CMC_DEF_NODE(SNAME) * _node_); \
|
||||
struct CMC_DEF_NODE(SNAME) * \
|
||||
CMC_(PFX, _prev_node)(struct CMC_DEF_NODE(SNAME) * _node_);
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_NODE_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * \
|
||||
CMC_(PFX, _new_node)(struct SNAME * _list_, V value) \
|
||||
{ \
|
||||
struct CMC_DEF_NODE(SNAME) *_node_ = \
|
||||
_list_->alloc->malloc(sizeof(struct CMC_DEF_NODE(SNAME))); \
|
||||
\
|
||||
if (!_node_) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
_node_->value = value; \
|
||||
_node_->next = NULL; \
|
||||
_node_->prev = NULL; \
|
||||
\
|
||||
return _node_; \
|
||||
} \
|
||||
\
|
||||
void CMC_(PFX, _free_node)(struct SNAME * _list_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
_list_->alloc->free(_node_); \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _head)(struct SNAME * _list_) \
|
||||
{ \
|
||||
return _list_->head; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * \
|
||||
CMC_(PFX, _get_node)(struct SNAME * _list_, size_t index) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(_list_)) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_EMPTY; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
if (index >= _list_->count) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_RANGE; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) *_node_ = NULL; \
|
||||
\
|
||||
if (index <= _list_->count / 2) \
|
||||
{ \
|
||||
_node_ = _list_->head; \
|
||||
for (size_t i = 0; i < index; i++) \
|
||||
{ \
|
||||
_node_ = _node_->next; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_node_ = _list_->tail; \
|
||||
for (size_t i = _list_->count - 1; i > index; i--) \
|
||||
{ \
|
||||
_node_ = _node_->prev; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_list_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return _node_; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _tail)(struct SNAME * _list_) \
|
||||
{ \
|
||||
return _list_->tail; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _add_next)(struct SNAME * _owner_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_, V value) \
|
||||
{ \
|
||||
struct CMC_DEF_NODE(SNAME) *new_node = \
|
||||
CMC_(PFX, _new_node)(_owner_, value); \
|
||||
\
|
||||
if (!new_node) \
|
||||
return false; \
|
||||
\
|
||||
new_node->next = _node_->next; \
|
||||
\
|
||||
if (_node_->next != NULL) \
|
||||
_node_->next->prev = new_node; \
|
||||
else \
|
||||
_owner_->tail = new_node; \
|
||||
\
|
||||
new_node->prev = _node_; \
|
||||
_node_->next = new_node; \
|
||||
\
|
||||
_owner_->count++; \
|
||||
_owner_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _add_prev)(struct SNAME * _owner_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_, V value) \
|
||||
{ \
|
||||
struct CMC_DEF_NODE(SNAME) *new_node = \
|
||||
CMC_(PFX, _new_node)(_owner_, value); \
|
||||
\
|
||||
if (!new_node) \
|
||||
return false; \
|
||||
\
|
||||
new_node->prev = _node_->prev; \
|
||||
\
|
||||
if (_node_->prev != NULL) \
|
||||
_node_->prev->next = new_node; \
|
||||
else \
|
||||
_owner_->head = new_node; \
|
||||
\
|
||||
new_node->next = _node_; \
|
||||
_node_->prev = new_node; \
|
||||
\
|
||||
_owner_->count++; \
|
||||
_owner_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _del_next)(struct SNAME * _owner_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
if (_node_->next == NULL) \
|
||||
{ \
|
||||
_owner_->flag = CMC_FLAG_INVALID; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) *tmp = _node_->next; \
|
||||
\
|
||||
_node_->next = _node_->next->next; \
|
||||
\
|
||||
if (tmp->next != NULL) \
|
||||
tmp->next->prev = _node_; \
|
||||
else \
|
||||
_owner_->tail = _node_; \
|
||||
\
|
||||
_owner_->alloc->free(tmp); \
|
||||
\
|
||||
_owner_->count--; \
|
||||
_owner_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _del_curr)(struct SNAME * _owner_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
if (_node_->prev != NULL) \
|
||||
_node_->prev->next = _node_->next; \
|
||||
else \
|
||||
_owner_->head = _node_->next; \
|
||||
\
|
||||
if (_node_->next != NULL) \
|
||||
_node_->next->prev = _node_->prev; \
|
||||
else \
|
||||
_owner_->tail = _node_->prev; \
|
||||
\
|
||||
_owner_->alloc->free(_node_); \
|
||||
\
|
||||
_owner_->count--; \
|
||||
_owner_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _del_prev)(struct SNAME * _owner_, \
|
||||
struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
if (_node_->prev == NULL) \
|
||||
{ \
|
||||
_owner_->flag = CMC_FLAG_INVALID; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) *tmp = _node_->prev; \
|
||||
\
|
||||
_node_->prev = _node_->prev->prev; \
|
||||
\
|
||||
if (tmp->prev != NULL) \
|
||||
tmp->prev->next = _node_; \
|
||||
else \
|
||||
_owner_->head = _node_; \
|
||||
\
|
||||
_owner_->alloc->free(tmp); \
|
||||
\
|
||||
_owner_->count--; \
|
||||
_owner_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * \
|
||||
CMC_(PFX, _next_node)(struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
return _node_->next; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * \
|
||||
CMC_(PFX, _prev_node)(struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
return _node_->prev; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_LINKEDLIST_STR(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_STR_HEADER_( \
|
||||
CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_STR_SOURCE_( \
|
||||
CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _list_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _list_, FILE * fptr, \
|
||||
const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _list_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *l_ = _list_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"head:%p, " \
|
||||
"tail:%p, " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), l_, \
|
||||
l_->count, l_->head, l_->tail, l_->flag, \
|
||||
l_->f_val, l_->alloc, l_->callbacks); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _list_, FILE * fptr, \
|
||||
const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) *scan = _list_->head; \
|
||||
\
|
||||
while (scan != NULL) \
|
||||
{ \
|
||||
if (!_list_->f_val->str(fptr, scan->value)) \
|
||||
return false; \
|
||||
\
|
||||
scan = scan->next; \
|
||||
\
|
||||
if (scan) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_LINKEDLIST_H */
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "ext/cmc/hashset.h" /* Added in 31/05/2020 */
|
||||
#include "ext/cmc/heap.h" /* Added in 01/06/2020 */
|
||||
#include "ext/cmc/intervalheap.h" /* Added in 02/06/2020 */
|
||||
#include "ext/cmc/linkedlist.h" /* Added in 03/06/2020 */
|
||||
|
||||
#include "utl/assert.h" /* Added in 27/06/2019 */
|
||||
#include "utl/foreach.h" /* Added in 25/02/2019 */
|
||||
|
||||
Reference in new issue
Block a user