From 02828a0109a00a908676e6f85cf2c07d1e53f9b5 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Thu, 11 Jul 2024 21:41:14 +0200 Subject: [PATCH] Fix interface of Intrusive List (Reported by Brian Sipos): * incorrect clear operator usage * useless prototype of _insert, inconsistent with the policy of other functions * syntax error in _insert --- README.md | 9 +++++--- example/ex-i-list.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ m-i-list.h | 19 ++++++--------- 3 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 example/ex-i-list.c diff --git a/README.md b/README.md index 82f14e15..8085ed2f 100644 --- a/README.md +++ b/README.md @@ -4777,6 +4777,10 @@ It shall be put within the structure of the object to link, at the top level of the structure. See example of `ILIST_DEF`. +#### `ILIST_INIT_FIELD(name, object)` + +Initialize the fields added by `ILIST_INTERFACE` of the object. + #### `ILIST_DEF(name, type[, oplist])` #### `ILIST_DEF_AS(name, name_t, name_it_t, type[, oplist])` @@ -4931,10 +4935,9 @@ or NULL if there is no more object. Return the object that is before the object `*obj` in the list or NULL if there is no more object. -##### `void name_insert(name_t list, name_it_t it, type x)` +##### `void name_insert(name_t list, name_it_t it, type *x)` -This method is the same as the generic one, -except it is only created if the `NEW` and `INIT_SET` methods are provided. +This method is the same as the generic one, except it is really `x` that is added in the list, not a copy. ##### `void name_splice_back(name_t list1, name_t list2, name_it_t it)` diff --git a/example/ex-i-list.c b/example/ex-i-list.c new file mode 100644 index 00000000..7289ceee --- /dev/null +++ b/example/ex-i-list.c @@ -0,0 +1,56 @@ +#include "m-i-list.h" + +typedef struct data_s { + M_ILIST_INTERFACE(list1, struct data_s); + char *ptr; + int n; +} data_t; + +static void +data_init(data_t *p) +{ + M_ILIST_INIT_FIELD(list1, *p); + p->ptr = malloc(100); + p->n = 100; +} + +static void +data_clear(data_t *p) +{ + free(p->ptr); + p->n = 0; +} + +static void +data_init_set(data_t *p, data_t s) +{ + p->ptr = malloc(s.n); + p->n = s.n; + memcpy(p->ptr, s.ptr, s.n); +} + +#define DATA_OP (INIT(API_2(data_init)), INIT_SET(API_2(data_init_set)), CLEAR(API_2(data_clear)) ) + +M_ILIST_DEF(list1, data_t, DATA_OP) + +data_t pool[100]; + +int main(void) +{ + list1_t l; + + list1_init(l); + data_init(&pool[0]); + list1_push_back(l, &pool[0]); + data_init(&pool[1]); + list1_push_back(l, &pool[1]); + + list1_it_t it; + list1_it(it, l); + data_init(&pool[2]); + list1_insert(l, it, &pool[2]); + + list1_clear(l); + + exit(0); +} \ No newline at end of file diff --git a/m-i-list.h b/m-i-list.h index 4e0aad80..55e0877d 100644 --- a/m-i-list.h +++ b/m-i-list.h @@ -71,6 +71,10 @@ ((__VA_ARGS__, M_BASIC_OPLIST), \ (__VA_ARGS__ ))) +#define M_ILIST_INIT_FIELD(name, obj) do { \ + (obj).name.next = NULL; \ + (obj).name.prev = NULL; \ + } while(0) /*****************************************************************************/ /******************************** INTERNAL ***********************************/ @@ -117,7 +121,6 @@ typedef struct m_il1st_head_s { IT_REF(M_F(name,_ref)), \ IT_CREF(M_F(name,_cref)), \ IT_REMOVE(M_F(name,_remove)), \ - M_IF_METHOD(NEW, oplist)(IT_INSERT(M_F(name,_insert)),), \ OPLIST(oplist), \ SPLICE_BACK(M_F(name,_splice_back)) \ ) @@ -517,30 +520,22 @@ typedef struct m_il1st_head_s { type *obj = M_TYPE_FROM_FIELD(type, it->current, \ struct m_il1st_head_s, name); \ M_F(name, _unlink)(obj); \ - M_CALL_CLEAR(oplist, obj); \ + M_CALL_CLEAR(oplist, *obj); \ M_IF_METHOD(DEL, oplist)(M_CALL_DEL(oplist, obj), (void) 0); \ M_F(name, _next)(it); \ } \ \ - M_IF_METHOD2(NEW, INIT_SET, oplist)( \ M_INLINE void \ - M_F(name, _insert)(list_t list, it_t it, type x) \ + M_F(name, _insert)(list_t list, it_t it, type *p) \ { \ M_IL1ST_CONTRACT(name, list); \ M_IL1ST_NODE_CONTRACT(it->current); \ - type *p = M_CALL_NEW(oplist, type); \ - if (M_UNLIKELY_NOMEM (p == NULL)) { \ - M_MEMORY_FULL (sizeof (type)); \ - return ; \ - } \ - M_CALL_INIT_SET(oplist, *p, x); \ type *obj = M_F(name, _ref)(it); \ M_F(name, _push_after)(obj, p); \ - it->current = p; \ + it->current = &p->name; \ (void) list; \ M_IL1ST_CONTRACT(name, list); \ } \ - , /* NEW & INIT_SET not defined */) \ \ M_INLINE type * \ M_F(name, _pop_back)(list_t list) \