Use va_arg for linking
This commit is contained in:
parent
53643eba88
commit
b435f5cc55
54
llist.c
54
llist.c
@ -18,13 +18,13 @@
|
||||
|
||||
#include "llist.h"
|
||||
|
||||
#include <stdarg.h> // va_args
|
||||
#include <stdint.h> // uintmax_t
|
||||
#include <stdlib.h> // malloc() free()
|
||||
|
||||
static llist_err corelibs_llist_create(void*, void (*)(void*), llist_t**);
|
||||
|
||||
static llist_err corelibs_llist_link_duo(llist_t*, llist_t*);
|
||||
static llist_err corelibs_llist_link_trio(llist_t*, llist_t*, llist_t*);
|
||||
static llist_err corelibs_llist_link(uintmax_t cnt, ...);
|
||||
|
||||
static llist_err corelibs_llist_free_list(llist_t*);
|
||||
static llist_err corelibs_llist_free_elem(llist_t*);
|
||||
@ -45,7 +45,8 @@ struct llist_t {
|
||||
};
|
||||
|
||||
enum { // Avoid collision in error numbers
|
||||
CORELIBS_LLIST_ERR_UNDEF = -3,
|
||||
CORELIBS_LLIST_ERR_MARGS = -4,
|
||||
CORELIBS_LLIST_ERR_UNDEF,
|
||||
CORELIBS_LLIST_ERR_NULL,
|
||||
CORELIBS_LLIST_ERR_ALLOC,
|
||||
CORELIBS_LLIST_ERR_UNK = 0,
|
||||
@ -54,10 +55,7 @@ enum { // Avoid collision in error numbers
|
||||
|
||||
struct corelibs_llist_interface const llist = {
|
||||
.create = corelibs_llist_create,
|
||||
.link = {
|
||||
.duo = corelibs_llist_link_duo,
|
||||
.trio = corelibs_llist_link_trio,
|
||||
},
|
||||
.link = corelibs_llist_link,
|
||||
.free = {
|
||||
.list = corelibs_llist_free_list,
|
||||
.elem = corelibs_llist_free_elem,
|
||||
@ -79,6 +77,9 @@ struct corelibs_llist_interface const llist = {
|
||||
.null = CORELIBS_LLIST_ERR_NULL,
|
||||
.alloc = CORELIBS_LLIST_ERR_ALLOC,
|
||||
},
|
||||
.args = {
|
||||
.mis = CORELIBS_LLIST_ERR_MARGS,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -148,37 +149,32 @@ ret:
|
||||
}
|
||||
|
||||
static llist_err
|
||||
corelibs_llist_link_duo(llist_t* a, llist_t* b)
|
||||
corelibs_llist_link(uintmax_t cnt, ...)
|
||||
{
|
||||
llist_err err = CORELIBS_LLIST_ERR_OK;
|
||||
|
||||
if (a == NULL && b == NULL) {
|
||||
err = CORELIBS_LLIST_ERR_NULL;
|
||||
if (cnt <= 1) {
|
||||
err = CORELIBS_LLIST_ERR_MARGS;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (a != NULL) a->next = b;
|
||||
if (b != NULL) b->prev = a;
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, cnt);
|
||||
|
||||
static llist_err
|
||||
corelibs_llist_link_trio(llist_t* a, llist_t* b, llist_t* c)
|
||||
{
|
||||
llist_err err = CORELIBS_LLIST_ERR_OK;
|
||||
uintmax_t ccnt = 0;
|
||||
llist_t * a = NULL, *b = NULL;
|
||||
while (ccnt < cnt) {
|
||||
a = b;
|
||||
b = va_arg(ap, llist_t*);
|
||||
if (ccnt < 1) continue; // Fill at least first 2 slots
|
||||
|
||||
if (a == NULL && b == NULL && c == NULL) {
|
||||
err = CORELIBS_LLIST_ERR_NULL;
|
||||
goto ret;
|
||||
if (a != NULL) a->next = b;
|
||||
if (b != NULL) b->prev = a;
|
||||
|
||||
ccnt++;
|
||||
}
|
||||
|
||||
if (a != NULL) a->next = b;
|
||||
if (b != NULL) {
|
||||
b->next = c;
|
||||
b->prev = a;
|
||||
}
|
||||
if (c != NULL) c->prev = b;
|
||||
va_end(ap);
|
||||
ret:
|
||||
return err;
|
||||
}
|
||||
@ -270,7 +266,7 @@ ret:
|
||||
static void
|
||||
corelibs_llist_remove(llist_t* e)
|
||||
{
|
||||
corelibs_llist_link_duo(e->prev, e->next);
|
||||
corelibs_llist_link(2, e->prev, e->next);
|
||||
if (e->free != NULL) e->free(e->cont);
|
||||
free(e);
|
||||
}
|
||||
|
10
llist.h
10
llist.h
@ -16,6 +16,8 @@
|
||||
* along with corelibs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h> // uintmax_t
|
||||
|
||||
#ifndef CORELIBS_GUARD_LLIST
|
||||
#define CORELIBS_GUARD_LLIST
|
||||
|
||||
@ -24,10 +26,7 @@ typedef signed short int llist_err;
|
||||
|
||||
struct corelibs_llist_interface {
|
||||
llist_err (*const create)(void* content, void (*const free_function)(void*), llist_t** save);
|
||||
const struct {
|
||||
llist_err (*const duo)(llist_t* element_a, llist_t* element_b);
|
||||
llist_err (*const trio)(llist_t* element_a, llist_t* element_b, llist_t* element_c);
|
||||
} link;
|
||||
llist_err (*const link)(uintmax_t elements, ...);
|
||||
const struct {
|
||||
llist_err (*const list)(llist_t* element);
|
||||
llist_err (*const elem)(llist_t* element);
|
||||
@ -49,6 +48,9 @@ struct corelibs_llist_interface {
|
||||
const llist_err null, // NULL address was passed
|
||||
alloc; // Allocation failed
|
||||
} mem;
|
||||
const struct {
|
||||
const llist_err mis; // Missing arguments / Not enough arguments
|
||||
} args;
|
||||
} err;
|
||||
};
|
||||
extern const struct corelibs_llist_interface llist;
|
||||
|
Reference in New Issue
Block a user