From 8c37ea7c885c1575b18222a9da051416244fdcf6 Mon Sep 17 00:00:00 2001 From: tylo Date: Mon, 6 Sep 2021 15:21:21 +0200 Subject: Added clist.h + list_test_new.c as working along with cvec. --- include/stc/ccommon.h | 4 +- include/stc/clist.h | 497 ++++++++++++++++++++++---------------------- include/stc/cvec.h | 41 +++- include/stc/list_test_new.c | 57 +++++ include/stc/template.h | 78 +++---- 5 files changed, 393 insertions(+), 284 deletions(-) create mode 100644 include/stc/list_test_new.c diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 6899b1b5..8cd9802c 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -39,9 +39,7 @@ #endif #define STC_INLINE static inline -#if !defined(STC_HEADER) && (defined(STC_IMPLEMENTATION) || defined(i_IMP)) -# error STC_HEADER should be defined when STC_IMPLEMENTATION or i_IMP is used -#elif defined(STC_HEADER) && (defined(STC_IMPLEMENTATION) || defined(i_IMP)) +#if defined(STC_HEADER) || defined(STC_IMPLEMENTATION) || defined(i_IMP) # define STC_API extern # define STC_DEF # define STC_LIBRARY_ONLY(...) __VA_ARGS__ diff --git a/include/stc/clist.h b/include/stc/clist.h index 9c79864a..b64eeac5 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -20,8 +20,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef CLIST_H_INCLUDED -#define CLIST_H_INCLUDED /* Circular Singly-linked Lists. @@ -30,9 +28,11 @@ for being used as a queue, unlike std::forward_list. Basic usage is similar to cvec: #include - #include #include - using_clist(ix, int64_t); + + #define i_TAG ix + #define i_VAL int64_t + #include int main() { c_forvar (clist_ix list = clist_ix_init(), clist_ix_del(&list)) @@ -53,254 +53,46 @@ } } */ + +#ifndef CLIST_H_INCLUDED #include "ccommon.h" +#include "forward.h" #include +#include - - -#define _c_clist_complete_types(Self) \ - struct cx_node_t { \ - struct cx_node_t *next; \ - cx_value_t value; \ +#define _c_clist_complete_types(SELF, dummy) \ + struct SELF##_node_t { \ + struct SELF##_node_t *next; \ + SELF##_value_t value; \ } +#define clist_node_(vp) c_container_of(vp, cx_node_t, value) + _c_clist_types(clist_VOID, int); -_c_clist_complete_types(clist_VOID); -STC_API size_t _clist_count(const clist_VOID* self); -#define _clist_node(Self, vp) c_container_of(vp, cx_node_t, value) - - - defTypes( _c_clist_types(Self, i_VAL); ) \ - _c_clist_complete_types(Self); \ - typedef i_VALRAW cx_rawvalue_t; \ -\ - STC_API Self cx_memb(_clone)(Self cx); \ - STC_API void cx_memb(_del)(Self* self); \ - STC_API void cx_memb(_push_back)(Self* self, i_VAL value); \ - STC_API void cx_memb(_push_front)(Self* self, i_VAL value); \ - STC_API cx_iter_t cx_memb(_insert)(Self* self, cx_iter_t it, i_VAL value); \ - STC_API void cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n); \ - STC_API cx_iter_t cx_memb(_erase_at)(Self* self, cx_iter_t it); \ - STC_API cx_iter_t cx_memb(_erase_range)(Self* self, cx_iter_t it1, cx_iter_t it2); \ - STC_API size_t cx_memb(_remove)(Self* self, i_VALRAW val); \ - STC_API cx_iter_t cx_memb(_splice)(Self* self, cx_iter_t it, Self* other); \ - STC_API Self cx_memb(_split_off)(Self* self, cx_iter_t it1, cx_iter_t it2); \ - STC_API void cx_memb(_sort)(Self* self); \ - STC_API cx_iter_t cx_memb(_find_in)(cx_iter_t it1, cx_iter_t it2, i_VALRAW val); \ - STC_API cx_node_t* cx_memb(_erase_after_)(Self* self, cx_node_t* node); \ -\ - STC_INLINE Self cx_memb(_init)(void) { return c_make(Self){NULL}; } \ - STC_INLINE bool cx_memb(_empty)(Self cx) { return cx.last == NULL; } \ - STC_INLINE size_t cx_memb(_count)(Self cx) \ - { return _clist_count((const clist_VOID*) &cx); } \ - STC_INLINE void cx_memb(_clear)(Self* self) {cx_memb(_del)(self); } \ - STC_INLINE i_VAL cx_memb(_value_fromraw)(i_VALRAW raw) { return i_VALFROM(raw); } \ - STC_INLINE i_VALRAW cx_memb(_value_toraw)(cx_value_t* pval) { return i_VALTO(pval); } \ - STC_INLINE i_VAL cx_memb(_value_clone)(i_VAL val) \ - { return i_VALFROM(i_VALTO(&val)); } \ - STC_INLINE void cx_memb(_pop_front)(Self* self) \ - {cx_memb(_erase_after_)(self, self->last); } \ - STC_INLINE cx_iter_t cx_memb(_erase)(Self* self, cx_iter_t it) \ - { return cx_memb(_erase_at)(self, it); } \ - STC_INLINE void cx_memb(_emplace_back)(Self* self, i_VALRAW raw) \ - {cx_memb(_push_back)(self, i_VALFROM(raw)); } \ - STC_INLINE void cx_memb(_emplace_front)(Self* self, i_VALRAW raw) \ - {cx_memb(_push_front)(self, i_VALFROM(raw)); } \ - STC_INLINE cx_iter_t cx_memb(_emplace)(Self* self, cx_iter_t it, i_VALRAW raw) \ - { return cx_memb(_insert)(self, it, i_VALFROM(raw)); } \ - STC_INLINE cx_value_t* cx_memb(_front)(const Self* self) { return &self->last->next->value; } \ - STC_INLINE cx_value_t* cx_memb(_back)(const Self* self) { return &self->last->value; } \ -\ - STC_INLINE cx_iter_t \ - cx_memb(_iter)(const Self* self, cx_node_t* prev) { \ - return c_make(cx_iter_t){&self->last, prev, &prev->next->value}; \ - } \ -\ - STC_INLINE cx_iter_t \ - cx_memb(_begin)(const Self* self) { \ - cx_value_t* head = self->last ? &self->last->next->value : NULL; \ - return c_make(cx_iter_t){&self->last, self->last, head}; \ - } \ -\ - STC_INLINE cx_iter_t \ - cx_memb(_end)(const Self* self) { \ - return c_make(cx_iter_t){NULL}; \ - } \ -\ - STC_INLINE void \ - cx_memb(_next)(cx_iter_t* it) { \ - cx_node_t* node = it->prev = _clist_node(Self, it->ref); \ - it->ref = (node == *it->_last ? NULL : &node->next->value); \ - } \ -\ - STC_INLINE cx_iter_t \ - cx_memb(_fwd)(cx_iter_t it, size_t n) { \ - while (n-- && it.ref) cx_memb(_next)(&it); \ - return it; \ - } \ -\ - STC_INLINE cx_iter_t \ - cx_memb(_splice_range)(Self* self, cx_iter_t it, \ - Self* other, cx_iter_t it1, cx_iter_t it2) { \ - Self tmp = cx_memb(_split_off)(other, it1, it2); \ - return cx_memb(_splice)(self, it, &tmp); \ - } \ -\ - STC_INLINE cx_iter_t \ - cx_memb(_find)(const Self* self, i_VALRAW val) { \ - return cx_memb(_find_in)(cx_memb(_begin)(self), cx_memb(_end)(self), val); \ - } \ -\ - STC_INLINE cx_value_t* \ - cx_memb(_get)(const Self* self, i_VALRAW val) { \ - return cx_memb(_find_in)(cx_memb(_begin)(self), cx_memb(_end)(self), val).ref; \ - } \ -\ - _c_implement_clist(Self, i_VAL, i_CMP, i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW) \ - struct stc_trailing_semicolon - -/* -------------------------- IMPLEMENTATION ------------------------- */ - -#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) -#define _c_implement_clist(Self, i_VAL, i_CMP, i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW) \ -\ - STC_DEF Self \ - cx_memb(_clone)(Self cx) { \ - Self out = cx_memb(_init)(); \ - c_foreach_3 (it, Self, cx) cx_memb(_emplace_back)(&out, i_VALTO(it.ref)); \ - return out; \ - } \ -\ - STC_DEF void \ - cx_memb(_del)(Self* self) { \ - while (self->last) cx_memb(_erase_after_)(self, self->last); \ - } \ -\ - STC_DEF void \ - cx_memb(_push_back)(Self* self, i_VAL value) { \ - _c_clist_insert_after(self, Self, self->last, value); \ - self->last = entry; \ - } \ -\ - STC_DEF void \ - cx_memb(_push_front)(Self* self, i_VAL value) { \ - _c_clist_insert_after(self, Self, self->last, value); \ - if (!self->last) self->last = entry; \ - } \ -\ - STC_DEF void \ - cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n) { \ - for (size_t i=0; ilast; \ - _c_clist_insert_after(self, Self, node, value); \ - if (!self->last || !it.ref) { \ - it.prev = self->last ? self->last : entry; \ - self->last = entry; \ - } \ - it.ref = &entry->value; \ - return it; \ - } \ -\ - STC_DEF cx_iter_t \ - cx_memb(_erase_at)(Self* self, cx_iter_t it) { \ - cx_node_t *node = _clist_node(Self, it.ref); \ - it.ref = (node == self->last) ? NULL : &node->next->value; \ - cx_memb(_erase_after_)(self, it.prev); \ - return it; \ - } \ -\ - STC_DEF cx_iter_t \ - cx_memb(_erase_range)(Self* self, cx_iter_t it1, cx_iter_t it2) { \ - cx_node_t *node = it1.ref ? it1.prev : NULL, \ - *done = it2.ref ? _clist_node(Self, it2.ref) : NULL; \ - while (node && node->next != done) \ - node = cx_memb(_erase_after_)(self, node); \ - return it2; \ - } \ -\ - STC_DEF cx_iter_t \ - cx_memb(_find_in)(cx_iter_t it1, cx_iter_t it2, i_VALRAW val) { \ - c_foreach_4 (it, Self, it1, it2) { \ - i_VALRAW r = i_VALTO(it.ref); \ - if (i_CMP(&r, &val) == 0) return it; \ - } \ - it2.ref = NULL; return it2; \ - } \ -\ - STC_DEF cx_node_t* \ - cx_memb(_erase_after_)(Self* self, cx_node_t* node) { \ - cx_node_t* del = node->next, *next = del->next; \ - node->next = next; \ - if (del == next) self->last = node = NULL; \ - else if (self->last == del) self->last = node, node = NULL; \ - i_VALDEL(&del->value); c_free(del); \ - return node; \ - } \ -\ - STC_DEF size_t \ - cx_memb(_remove)(Self* self, i_VALRAW val) { \ - size_t n = 0; \ - cx_node_t* prev = self->last, *node; \ - while (prev) { \ - node = prev->next; \ - i_VALRAW r = i_VALTO(&node->value); \ - if (i_CMP(&r, &val) == 0) \ - prev = cx_memb(_erase_after_)(self, prev), ++n; \ - else \ - prev = (node == self->last ? NULL : node); \ - } \ - return n; \ - } \ -\ - STC_DEF cx_iter_t \ - cx_memb(_splice)(Self* self, cx_iter_t it, Self* other) { \ - if (!self->last) \ - self->last = other->last; \ - else if (other->last) { \ - cx_node_t *p = it.ref ? it.prev : self->last, *next = p->next; \ - it.prev = other->last; \ - p->next = it.prev->next; \ - it.prev->next = next; \ - if (!it.ref) self->last = it.prev; \ - } \ - other->last = NULL; return it; \ - } \ -\ - STC_DEF Self \ - cx_memb(_split_off)(Self* self, cx_iter_t it1, cx_iter_t it2) { \ - Self cx = {NULL}; \ - if (it1.ref == it2.ref) return cx; \ - cx_node_t *p1 = it1.prev, \ - *p2 = it2.ref ? it2.prev : self->last; \ - p1->next = p2->next, p2->next = _clist_node(Self, it1.ref); \ - if (self->last == p2) self->last = (p1 == p2) ? NULL : p1; \ - cx.last = p2; \ - return cx; \ - } \ -\ - STC_DEF int \ - cx_memb(_sort_cmp_)(const clist_VOID_node_t* x, const clist_VOID_node_t* y) { \ - i_VALRAW a = i_VALTO(&((const cx_node_t *) x)->value); \ - i_VALRAW b = i_VALTO(&((const cx_node_t *) y)->value); \ - return i_CMP(&a, &b); \ - } \ - STC_DEF void \ - cx_memb(_sort)(Self* self) { \ - if (self->last) \ - self->last = (cx_node_t *) _clist_mergesort((clist_VOID_node_t *) self->last->next, cx_memb(_sort_cmp_)); \ - } +_c_clist_complete_types(clist_VOID, dummy); +#endif // CLIST_H_INCLUDED +#define i_MODULE clist +#include "template.h" +#if !defined i_FWD +cx_deftypes(_c_clist_types, Self, i_VAL); +#endif +cx_deftypes(_c_clist_complete_types, Self); +typedef i_VALRAW cx_rawvalue_t; + + +#ifndef CLIST_H_INCLUDED +#define CLIST_H_INCLUDED #define _c_clist_insert_after(self, Self, node, val) \ cx_node_t *entry = c_new (cx_node_t); \ if (node) entry->next = node->next, node->next = entry; \ else entry->next = entry; \ entry->value = val - /* +: set self->last based on node */ + // +: set self->last based on node + +#if !defined(STC_HEADER) || defined(i_IMP) && (i_IMP == 2) +// NON TEMPLATED CODE STC_DEF size_t _clist_count(const clist_VOID* self) { @@ -311,9 +103,8 @@ _clist_count(const clist_VOID* self) { return n; } -/* Singly linked list Mergesort implementation by Simon Tatham. O(n*log n). - * https://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html - */ +// Singly linked list Mergesort implementation by Simon Tatham. O(n*log n). +// https://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html STC_DEF clist_VOID_node_t * _clist_mergesort(clist_VOID_node_t *list, int (*cmp)(const clist_VOID_node_t*, const clist_VOID_node_t*)) { clist_VOID_node_t *p, *q, *e, *tail, *oldhead; @@ -361,7 +152,225 @@ _clist_mergesort(clist_VOID_node_t *list, int (*cmp)(const clist_VOID_node_t*, c insize *= 2; } } - - #endif #endif + +STC_API Self cx_memb(_clone)(Self cx); +STC_API void cx_memb(_del)(Self* self); +STC_API void cx_memb(_push_back)(Self* self, i_VAL value); +STC_API void cx_memb(_push_front)(Self* self, i_VAL value); +STC_API cx_iter_t cx_memb(_insert)(Self* self, cx_iter_t it, i_VAL value); +STC_API void cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n); +STC_API cx_iter_t cx_memb(_erase_at)(Self* self, cx_iter_t it); +STC_API cx_iter_t cx_memb(_erase_range)(Self* self, cx_iter_t it1, cx_iter_t it2); +STC_API size_t cx_memb(_remove)(Self* self, i_VALRAW val); +STC_API cx_iter_t cx_memb(_splice)(Self* self, cx_iter_t it, Self* other); +STC_API Self cx_memb(_split_off)(Self* self, cx_iter_t it1, cx_iter_t it2); +STC_API void cx_memb(_sort)(Self* self); +STC_API cx_iter_t cx_memb(_find_in)(cx_iter_t it1, cx_iter_t it2, i_VALRAW val); +STC_API cx_node_t* cx_memb(_erase_after_)(Self* self, cx_node_t* node); + +STC_INLINE Self cx_memb(_init)(void) { return c_make(Self){NULL}; } +STC_INLINE bool cx_memb(_empty)(Self cx) { return cx.last == NULL; } +STC_INLINE size_t cx_memb(_count)(Self cx) + { return _clist_count((const clist_VOID*) &cx); } +STC_INLINE void cx_memb(_clear)(Self* self) {cx_memb(_del)(self); } +STC_INLINE i_VAL cx_memb(_value_fromraw)(i_VALRAW raw) { return i_VALFROM(raw); } +STC_INLINE i_VALRAW cx_memb(_value_toraw)(cx_value_t* pval) { return i_VALTO(pval); } +STC_INLINE i_VAL cx_memb(_value_clone)(i_VAL val) + { return i_VALFROM(i_VALTO(&val)); } +STC_INLINE void cx_memb(_pop_front)(Self* self) + {cx_memb(_erase_after_)(self, self->last); } +STC_INLINE cx_iter_t cx_memb(_erase)(Self* self, cx_iter_t it) + { return cx_memb(_erase_at)(self, it); } +STC_INLINE void cx_memb(_emplace_back)(Self* self, i_VALRAW raw) + {cx_memb(_push_back)(self, i_VALFROM(raw)); } +STC_INLINE void cx_memb(_emplace_front)(Self* self, i_VALRAW raw) + {cx_memb(_push_front)(self, i_VALFROM(raw)); } +STC_INLINE cx_iter_t cx_memb(_emplace)(Self* self, cx_iter_t it, i_VALRAW raw) + { return cx_memb(_insert)(self, it, i_VALFROM(raw)); } +STC_INLINE cx_value_t* cx_memb(_front)(const Self* self) { return &self->last->next->value; } +STC_INLINE cx_value_t* cx_memb(_back)(const Self* self) { return &self->last->value; } + +STC_INLINE cx_iter_t +cx_memb(_iter)(const Self* self, cx_node_t* prev) { + return c_make(cx_iter_t){&self->last, prev, &prev->next->value}; +} + +STC_INLINE cx_iter_t +cx_memb(_begin)(const Self* self) { + cx_value_t* head = self->last ? &self->last->next->value : NULL; + return c_make(cx_iter_t){&self->last, self->last, head}; +} + +STC_INLINE cx_iter_t +cx_memb(_end)(const Self* self) { + return c_make(cx_iter_t){NULL}; +} + +STC_INLINE void +cx_memb(_next)(cx_iter_t* it) { + cx_node_t* node = it->prev = clist_node_(it->ref); + it->ref = (node == *it->_last ? NULL : &node->next->value); +} + +STC_INLINE cx_iter_t +cx_memb(_fwd)(cx_iter_t it, size_t n) { + while (n-- && it.ref) cx_memb(_next)(&it); + return it; +} + +STC_INLINE cx_iter_t +cx_memb(_splice_range)(Self* self, cx_iter_t it, + Self* other, cx_iter_t it1, cx_iter_t it2) { + Self tmp = cx_memb(_split_off)(other, it1, it2); + return cx_memb(_splice)(self, it, &tmp); +} + +STC_INLINE cx_iter_t +cx_memb(_find)(const Self* self, i_VALRAW val) { + return cx_memb(_find_in)(cx_memb(_begin)(self), cx_memb(_end)(self), val); +} + +STC_INLINE cx_value_t* +cx_memb(_get)(const Self* self, i_VALRAW val) { + return cx_memb(_find_in)(cx_memb(_begin)(self), cx_memb(_end)(self), val).ref; +} + +// -------------------------- IMPLEMENTATION ------------------------- + +#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) || defined(i_IMP) + +STC_DEF Self +cx_memb(_clone)(Self cx) { + Self out = cx_memb(_init)(); + c_foreach (it, Self, cx) cx_memb(_emplace_back)(&out, i_VALTO(it.ref)); + return out; +} + +STC_DEF void +cx_memb(_del)(Self* self) { + while (self->last) cx_memb(_erase_after_)(self, self->last); +} + +STC_DEF void +cx_memb(_push_back)(Self* self, i_VAL value) { + _c_clist_insert_after(self, Self, self->last, value); + self->last = entry; +} + +STC_DEF void +cx_memb(_push_front)(Self* self, i_VAL value) { + _c_clist_insert_after(self, Self, self->last, value); + if (!self->last) self->last = entry; +} + +STC_DEF void +cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n) { + for (size_t i=0; ilast; + _c_clist_insert_after(self, Self, node, value); + if (!self->last || !it.ref) { + it.prev = self->last ? self->last : entry; + self->last = entry; + } + it.ref = &entry->value; + return it; +} + +STC_DEF cx_iter_t +cx_memb(_erase_at)(Self* self, cx_iter_t it) { + cx_node_t *node = clist_node_(it.ref); + it.ref = (node == self->last) ? NULL : &node->next->value; + cx_memb(_erase_after_)(self, it.prev); + return it; +} + +STC_DEF cx_iter_t +cx_memb(_erase_range)(Self* self, cx_iter_t it1, cx_iter_t it2) { + cx_node_t *node = it1.ref ? it1.prev : NULL, + *done = it2.ref ? clist_node_(it2.ref) : NULL; + while (node && node->next != done) + node = cx_memb(_erase_after_)(self, node); + return it2; +} + +STC_DEF cx_iter_t +cx_memb(_find_in)(cx_iter_t it1, cx_iter_t it2, i_VALRAW val) { + c_foreach (it, Self, it1, it2) { + i_VALRAW r = i_VALTO(it.ref); + if (i_CMP(&r, &val) == 0) return it; + } + it2.ref = NULL; return it2; +} + +STC_DEF cx_node_t* +cx_memb(_erase_after_)(Self* self, cx_node_t* node) { + cx_node_t* del = node->next, *next = del->next; + node->next = next; + if (del == next) self->last = node = NULL; + else if (self->last == del) self->last = node, node = NULL; + i_VALDEL(&del->value); c_free(del); + return node; +} + +STC_DEF size_t +cx_memb(_remove)(Self* self, i_VALRAW val) { + size_t n = 0; + cx_node_t* prev = self->last, *node; + while (prev) { + node = prev->next; + i_VALRAW r = i_VALTO(&node->value); + if (i_CMP(&r, &val) == 0) + prev = cx_memb(_erase_after_)(self, prev), ++n; + else + prev = (node == self->last ? NULL : node); + } + return n; +} + +STC_DEF cx_iter_t +cx_memb(_splice)(Self* self, cx_iter_t it, Self* other) { + if (!self->last) + self->last = other->last; + else if (other->last) { + cx_node_t *p = it.ref ? it.prev : self->last, *next = p->next; + it.prev = other->last; + p->next = it.prev->next; + it.prev->next = next; + if (!it.ref) self->last = it.prev; + } + other->last = NULL; return it; +} + +STC_DEF Self +cx_memb(_split_off)(Self* self, cx_iter_t it1, cx_iter_t it2) { + Self cx = {NULL}; + if (it1.ref == it2.ref) return cx; + cx_node_t *p1 = it1.prev, + *p2 = it2.ref ? it2.prev : self->last; + p1->next = p2->next, p2->next = clist_node_(it1.ref); + if (self->last == p2) self->last = (p1 == p2) ? NULL : p1; + cx.last = p2; + return cx; +} + +STC_DEF int +cx_memb(_sort_cmp_)(const clist_VOID_node_t* x, const clist_VOID_node_t* y) { + i_VALRAW a = i_VALTO(&((const cx_node_t *) x)->value); + i_VALRAW b = i_VALTO(&((const cx_node_t *) y)->value); + return i_CMP(&a, &b); +} + +STC_DEF void +cx_memb(_sort)(Self* self) { + if (self->last) + self->last = (cx_node_t *) _clist_mergesort((clist_VOID_node_t *) self->last->next, cx_memb(_sort_cmp_)); +} + +#endif // IMPLEMENTATION +#include "template.h" diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 9491bacb..b79116cb 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -20,6 +20,42 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ + +/* +#include +#include + +forward_cvec(i32, int); + +struct MyStruct { + cvec_i32 int_vec; + cstr name; +} typedef MyStruct; + +#define i_VAL float +#include + +#define i_VAL_str // special for cstr +#include + +#define f_TAG i32 // f: forward declared above; shorthand for i_FWD +#define i_VAL int +#include + +int main() { + cvec_i32 vec = cvec_i32_init(); + cvec_i32_push_back(&vec, 123); + cvec_i32_del(&vec); + + cvec_float fvec = cvec_float_init(); + cvec_float_push_back(&fvec, 123.3); + cvec_float_del(&fvec); + + cvec_str svec = cvec_str_init(); + cvec_str_emplace_back(&svec, "Hello, friend"); + cvec_str_del(&svec); +} +*/ #ifndef CVEC_H_INCLUDED #include "ccommon.h" @@ -183,8 +219,10 @@ cx_memb(_sort)(Self* self) { /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined i_IMP +#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) || defined(i_IMP) + #ifndef CVEC_H_INCLUDED +#define CVEC_H_INCLUDED static struct cvec_Rep_ _cvec_sentinel = {0, 0}; #endif @@ -322,5 +360,4 @@ cx_memb(_value_compare)(const cx_value_t* x, const cx_value_t* y) { } #endif -#define CVEC_H_INCLUDED #include "template.h" diff --git a/include/stc/list_test_new.c b/include/stc/list_test_new.c new file mode 100644 index 00000000..83f6107c --- /dev/null +++ b/include/stc/list_test_new.c @@ -0,0 +1,57 @@ +#include "cstr.h" +#include "forward.h" + +forward_clist(i32, int); +forward_clist(pnt, struct Point); + +struct MyStruct { + clist_i32 intlst; + clist_pnt pntlst; +} typedef MyStruct; + + +#define f_TAG i32 +#define i_VAL int +#include "clist.h" + +struct Point { int x, y; } typedef Point; +int point_compare(const Point* a, const Point* b) { + int c = c_default_compare(&a->x, &b->x); + return c ? c : c_default_compare(&a->y, &b->y); +} +#define f_TAG pnt +#define i_VAL Point +#define i_CMP point_compare +#include "clist.h" + +#define i_VAL float +#include "clist.h" + +#define i_VAL_str +#include "clist.h" + + +int main() +{ + clist_i32 lst = clist_i32_init(); + clist_i32_push_back(&lst, 123); + clist_i32_del(&lst); + + clist_float flst = clist_float_init(); + clist_float_push_back(&flst, 123.3); + clist_float_del(&flst); + + clist_pnt plst = clist_pnt_init(); + clist_pnt_push_back(&plst, (Point){42, 14}); + clist_pnt_push_back(&plst, (Point){32, 94}); + clist_pnt_push_back(&plst, (Point){62, 81}); + clist_pnt_sort(&plst); + c_foreach (i, clist_pnt, plst) + printf(" (%d %d)", i.ref->x, i.ref->y); + puts(""); + clist_pnt_del(&plst); + + clist_str slst = clist_str_init(); + clist_str_emplace_back(&slst, "Hello, friend"); + clist_str_del(&slst); +} \ No newline at end of file diff --git a/include/stc/template.h b/include/stc/template.h index eb770c9a..c601d359 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -1,5 +1,45 @@ -#ifndef STC_TEMPLATE_INCLUDED -#define STC_TEMPLATE_INCLUDED +/* MIT License + * + * Copyright (c) 2021 Tyge Løvset, NORCE, www.norceresearch.no + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef i_TEMPLATE +#define i_TEMPLATE + +#ifndef STC_TEMPLATE_H_INCLUDED +#define STC_TEMPLATE_H_INCLUDED +#define cx_memb(name) c_PASTE(Self, name) +#define Self c_PASTE3(i_MODULE, _, i_TAG) +// typedef container types defined in forward.h +#define cx_deftypes(macro, SELF, ...) macro(SELF, __VA_ARGS__) + +#define cx_value_t cx_memb(_value_t) +#define cx_key_t cx_memb(_key_t) +#define cx_mapped_t cx_memb(_mapped_t) +#define cx_rawvalue_t cx_memb(_rawvalue_t) +#define cx_rawkey_t cx_memb(_rawkey_t) +#define cx_rawmapped_t cx_memb(_rawmapped_t) +#define cx_iter_t cx_memb(_iter_t) +#define cx_result_t cx_memb(_result_t) +#define cx_node_t cx_memb(_node_t) +#endif #if defined f_TAG #define i_TAG f_TAG @@ -37,13 +77,6 @@ #define i_TAG i_VAL #endif -#define Self c_PASTE3(i_MODULE, _, i_TAG) -#define cx_memb(name) c_PASTE(Self, name) - -#define cx_value_t cx_memb(_value_t) -#define cx_rawvalue_t cx_memb(_rawvalue_t) -#define cx_iter_t cx_memb(_iter_t) - #if (defined i_VALTO ^ defined i_VALRAW) || (defined i_VALRAW && !defined i_VALFROM) #error if i_VALRAW defined, both i_VALFROM and i_VALTO must be defined #endif @@ -52,12 +85,6 @@ #endif #if defined i_KEY - #define cx_key_t cx_memb(_key_t) - #define cx_rawkey_t cx_memb(_rawkey_t) - #define cx_mapped_t cx_memb(_mapped_t) - #define cx_rawmapped_t cx_memb(_rawmapped_t) - #define cx_result_t cx_memb(_result_t) - #if !defined i_KEYFROM && defined i_KEYDEL #define i_KEYFROM c_no_clone #elif !defined i_KEYFROM @@ -96,13 +123,6 @@ #define i_CMP c_default_compare #endif -// typedef container types defined in forward.h -#define cx_deftypes(macro, Self, ...) macro(Self, __VA_ARGS__) -// criteria for implementation -#if !defined i_IMP && (defined STC_IMPLEMENTATION || !defined STC_HEADER) -#define i_IMP -#endif - #else // ------------------------------------------------------- #undef i_MODULE @@ -126,17 +146,5 @@ #undef i_KEYTO #undef i_KEYRAW -#undef Self -#undef cx_memb -#undef cx_deftypes -#undef cx_value_t -#undef cx_rawvalue_t -#undef cx_iter_t -#undef cx_key_t -#undef cx_rawkey_t -#undef cx_mapped_t -#undef cx_rawmapped_t -#undef cx_result_t - -#undef STC_TEMPLATE_INCLUDED +#undef i_TEMPLATE #endif -- cgit v1.2.3