diff --git a/src/cmc/bidimap.h b/src/cmc/bidimap.h index 5d6b51c..464bf7c 100644 --- a/src/cmc/bidimap.h +++ b/src/cmc/bidimap.h @@ -45,10 +45,10 @@ */ struct cmc_string { - char s[300]; + char s[400]; }; -static const size_t cmc_string_len = 300; +static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node @@ -105,7 +105,9 @@ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " "key_cmp:%p, " "val_cmp:%p, " "key_hash:%p, " - "val_hash:%p }"; + "val_hash:%p, " + "alloc:%p, " + "callbacks:%p }"; /** * Custom BidiMap callbacks. @@ -132,7 +134,9 @@ struct cmc_callbacks_bidimap #define CMC_WRAPGEN_BIDIMAP_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V) -/* HEADER ********************************************************************/ +/* ------------------------------------------------------------------------------------------------- + * Header + ------------------------------------------------------------------------------------------------ */ #define CMC_GENERATE_BIDIMAP_HEADER(PFX, SNAME, K, V) \ \ /* BidiMap Structure */ \ @@ -282,9 +286,11 @@ struct cmc_callbacks_bidimap /* Iterator Access */ \ K PFX##_iter_key(struct SNAME##_iter *iter); \ V PFX##_iter_value(struct SNAME##_iter *iter); \ - size_t PFX##_iter_index(struct SNAME##_iter *iter); \ - \ -/* SOURCE ********************************************************************/ + size_t PFX##_iter_index(struct SNAME##_iter *iter); + +/* ------------------------------------------------------------------------------------------------- + * Source + ------------------------------------------------------------------------------------------------ */ #define CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V) \ \ /* Implementation Detail Functions */ \ @@ -869,14 +875,12 @@ struct cmc_callbacks_bidimap int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, \ name, #K, #V, m_, m_->key_buffer, m_->val_buffer, m_->capacity, \ m_->count, m_->load, m_->key_cmp, m_->val_cmp, m_->key_hash, \ - m_->val_hash); \ + m_->val_hash, m_->alloc, m_->callbacks); \ \ - if (n < 0) \ - { \ + if (n < 0 || n == cmc_string_len) \ return (struct cmc_string){0}; \ - } \ \ - str.s[n - 1] = '\0'; \ + str.s[n] = '\0'; \ \ return str; \ } \ diff --git a/src/cmc/deque.h b/src/cmc/deque.h index 7358b18..49085b9 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -36,10 +36,68 @@ #include #include #include -#include "../utl/cmc_string.h" +/* ------------------------------------------------------------------------------------------------- + * Core functionalities of the C Macro Collections Library + ------------------------------------------------------------------------------------------------ */ +#ifndef CMC_CORE_H +#define CMC_CORE_H + +/** + * struct cmc_string + * + * Used by all collections when calling the to_string function. + */ +struct cmc_string +{ + char s[400]; +}; + +static const size_t cmc_string_len = 400; + +/** + * struct cmc_alloc_node + * + * Custom allocation node. Allows collections to use custom allocation functions. + */ +struct cmc_alloc_node +{ + void *(*malloc)(size_t); + void *(*calloc)(size_t, size_t); + void *(*realloc)(void *, size_t); + void (*free)(void *); +} cmc_alloc_node_default = {malloc, calloc, realloc, free}; + +#endif /* CMC_CORE_H */ + +/* ------------------------------------------------------------------------------------------------- + * Deque specific + ------------------------------------------------------------------------------------------------ */ /* to_string format */ -static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", front:%" PRIuMAX ", back:%" PRIuMAX " }"; +static const char *cmc_string_fmt_deque = "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" PRIuMAX ", " + "count:%" PRIuMAX ", " + "front:%" PRIuMAX ", " + "back:%" PRIuMAX ", " + "alloc:%p, " + "callbacks:%p }"; + +/** + * Custom Deque callbacks. + * + * There are two types of callbacks, 'before' and 'after': + * _ + */ +struct cmc_callbacks_deque +{ + void (*before_clear)(void *); + void (*after_clear)(void *); + void (*before_free)(void *); + void (*after_free)(void *); + // TODO implement all callbacks +}; #define CMC_GENERATE_DEQUE(PFX, SNAME, V) \ CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V) \ @@ -51,7 +109,9 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI #define CMC_WRAPGEN_DEQUE_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V) -/* HEADER ********************************************************************/ +/* ------------------------------------------------------------------------------------------------- + * Header + ------------------------------------------------------------------------------------------------ */ #define CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V) \ \ /* Deque Structure */ \ @@ -77,6 +137,12 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI \ /* Function that returns an iterator to the end of the deque */ \ struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_deque *callbacks; \ }; \ \ /* Deque Iterator */ \ @@ -101,8 +167,13 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ struct SNAME *PFX##_new(size_t capacity); \ + struct SNAME *PFX##_new_custom(size_t capacity, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_deque *callbacks); \ void PFX##_clear(struct SNAME *_deque_, void (*deallocator)(V)); \ void PFX##_free(struct SNAME *_deque_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_deque_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_deque *callbacks); \ /* Collection Input and Output */ \ bool PFX##_push_front(struct SNAME *_deque_, V element); \ bool PFX##_push_back(struct SNAME *_deque_, V element); \ @@ -143,9 +214,11 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI /* Iterator Access */ \ V PFX##_iter_value(struct SNAME##_iter *iter); \ V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ - size_t PFX##_iter_index(struct SNAME##_iter *iter); \ - \ -/* SOURCE ********************************************************************/ + size_t PFX##_iter_index(struct SNAME##_iter *iter); + +/* ------------------------------------------------------------------------------------------------- + * Source + ------------------------------------------------------------------------------------------------ */ #define CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ @@ -154,19 +227,21 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI \ struct SNAME *PFX##_new(size_t capacity) \ { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ if (capacity < 1) \ return NULL; \ \ - struct SNAME *_deque_ = malloc(sizeof(struct SNAME)); \ + struct SNAME *_deque_ = alloc->malloc(sizeof(struct SNAME)); \ \ if (!_deque_) \ return NULL; \ \ - _deque_->buffer = calloc(capacity, sizeof(V)); \ + _deque_->buffer = alloc->calloc(capacity, sizeof(V)); \ \ if (!_deque_->buffer) \ { \ - free(_deque_); \ + alloc->free(_deque_); \ return NULL; \ } \ \ @@ -178,6 +253,45 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI _deque_->it_start = PFX##_impl_it_start; \ _deque_->it_end = PFX##_impl_it_end; \ \ + _deque_->alloc = alloc; \ + _deque_->callbacks = NULL; \ + \ + return _deque_; \ + } \ + \ + struct SNAME *PFX##_new_custom(size_t capacity, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_deque *callbacks) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_deque_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_deque_) \ + return NULL; \ + \ + _deque_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_deque_->buffer) \ + { \ + alloc->free(_deque_); \ + return NULL; \ + } \ + \ + _deque_->capacity = capacity; \ + _deque_->count = 0; \ + _deque_->front = 0; \ + _deque_->back = 0; \ + \ + _deque_->it_start = PFX##_impl_it_start; \ + _deque_->it_end = PFX##_impl_it_end; \ + \ + _deque_->alloc = alloc; \ + _deque_->callbacks = callbacks; \ + \ return _deque_; \ } \ \ @@ -212,8 +326,18 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI } \ } \ \ - free(_deque_->buffer); \ - free(_deque_); \ + _deque_->alloc->free(_deque_->buffer); \ + _deque_->alloc->free(_deque_); \ + } \ + \ + void PFX##_customize(struct SNAME *_deque_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_deque *callbacks) \ + { \ + if (alloc) \ + _deque_->alloc = alloc; \ + \ + if (callbacks) \ + _deque_->callbacks = callbacks; \ } \ \ bool PFX##_push_front(struct SNAME *_deque_, V element) \ @@ -335,7 +459,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI if (capacity < PFX##_count(_deque_)) \ return false; \ \ - V *new_buffer = malloc(sizeof(V) * capacity); \ + V *new_buffer = _deque_->alloc->malloc(sizeof(V) * capacity); \ \ if (!new_buffer) \ return false; \ @@ -347,7 +471,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI i = (i + 1) % PFX##_capacity(_deque_); \ } \ \ - free(_deque_->buffer); \ + _deque_->alloc->free(_deque_->buffer); \ \ _deque_->buffer = new_buffer; \ _deque_->capacity = capacity; \ @@ -359,7 +483,8 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI \ struct SNAME *PFX##_copy_of(struct SNAME *_deque_, V (*copy_func)(V)) \ { \ - struct SNAME *result = PFX##_new(_deque_->capacity); \ + struct SNAME *result = PFX##_new_custom(_deque_->capacity, _deque_->alloc, \ + _deque_->callbacks); \ \ if (!result) \ return NULL; \ @@ -412,15 +537,21 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI struct SNAME *d_ = _deque_; \ const char *name = #SNAME; \ \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, \ - name, d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back); \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, \ + name, #V, d_, d_->buffer, d_->capacity, d_->count, \ + d_->front, d_->back, d_->alloc, d_->callbacks); \ + \ + if (n < 0 || n == cmc_string_len) \ + return (struct cmc_string){0}; \ + \ + str.s[n] = '\0'; \ \ return str; \ } \ \ struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ - struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ + struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ \ if (!iter) \ return NULL; \ @@ -432,7 +563,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI \ void PFX##_iter_free(struct SNAME##_iter *iter) \ { \ - free(iter); \ + iter->target->alloc->free(iter); \ } \ \ void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \