diff options
| author | tylo <[email protected]> | 2021-09-06 15:21:21 +0200 |
|---|---|---|
| committer | tylo <[email protected]> | 2021-09-06 15:21:21 +0200 |
| commit | 8c37ea7c885c1575b18222a9da051416244fdcf6 (patch) | |
| tree | af8b8d625cbbdb7b669458b5646a9ca3056c53ff | |
| parent | 256a245c4afeebf44892fdb3abca933f6f542d4f (diff) | |
| download | STC-modified-8c37ea7c885c1575b18222a9da051416244fdcf6.tar.gz STC-modified-8c37ea7c885c1575b18222a9da051416244fdcf6.zip | |
Added clist.h + list_test_new.c as working along with cvec.
| -rw-r--r-- | include/stc/ccommon.h | 4 | ||||
| -rw-r--r-- | include/stc/clist.h | 497 | ||||
| -rw-r--r-- | include/stc/cvec.h | 41 | ||||
| -rw-r--r-- | include/stc/list_test_new.c | 57 | ||||
| -rw-r--r-- | include/stc/template.h | 78 |
5 files changed, 393 insertions, 284 deletions
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 <stdio.h>
- #include <stc/clist.h>
#include <stc/crandom.h>
- using_clist(ix, int64_t);
+
+ #define i_TAG ix
+ #define i_VAL int64_t
+ #include <stc/clist.h>
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 <stdlib.h>
+#include <string.h>
-
-
-#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; i<n; ++i) cx_memb(_push_back)(self, i_VALFROM(arr[i])); \
- } \
-\
- STC_DEF cx_iter_t \
- cx_memb(_insert)(Self* self, cx_iter_t it, i_VAL value) { \
- cx_node_t* node = it.ref ? it.prev : self->last; \
- _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; i<n; ++i) cx_memb(_push_back)(self, i_VALFROM(arr[i]));
+}
+
+STC_DEF cx_iter_t
+cx_memb(_insert)(Self* self, cx_iter_t it, i_VAL value) {
+ cx_node_t* node = it.ref ? it.prev : self->last;
+ _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 <stc/cstr.h>
+#include <stc/forward.h>
+
+forward_cvec(i32, int);
+
+struct MyStruct {
+ cvec_i32 int_vec;
+ cstr name;
+} typedef MyStruct;
+
+#define i_VAL float
+#include <stc/cvec.h>
+
+#define i_VAL_str // special for cstr
+#include <stc/cvec.h>
+
+#define f_TAG i32 // f: forward declared above; shorthand for i_FWD
+#define i_VAL int
+#include <stc/cvec.h>
+
+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
|
