Add generic doubly-linked list implementation
This commit is contained in:
parent
d2e6100c16
commit
dacf478352
4 changed files with 173 additions and 1 deletions
89
src/utils/list.h
Normal file
89
src/utils/list.h
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Doubly-linked list
|
||||||
|
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Alternatively, this software may be distributed under the terms of BSD
|
||||||
|
* license.
|
||||||
|
*
|
||||||
|
* See README and COPYING for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIST_H
|
||||||
|
#define LIST_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct dl_list - Doubly-linked list
|
||||||
|
*/
|
||||||
|
struct dl_list {
|
||||||
|
struct dl_list *next;
|
||||||
|
struct dl_list *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void dl_list_init(struct dl_list *list)
|
||||||
|
{
|
||||||
|
list->next = list;
|
||||||
|
list->prev = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dl_list_add(struct dl_list *list, struct dl_list *item)
|
||||||
|
{
|
||||||
|
item->next = list->next;
|
||||||
|
item->prev = list;
|
||||||
|
list->next->prev = item;
|
||||||
|
list->next = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item)
|
||||||
|
{
|
||||||
|
dl_list_add(list->prev, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dl_list_del(struct dl_list *item)
|
||||||
|
{
|
||||||
|
item->next->prev = item->prev;
|
||||||
|
item->prev->next = item->next;
|
||||||
|
item->next = NULL;
|
||||||
|
item->prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dl_list_empty(struct dl_list *list)
|
||||||
|
{
|
||||||
|
return list->next == list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int dl_list_len(struct dl_list *list)
|
||||||
|
{
|
||||||
|
struct dl_list *item;
|
||||||
|
int count = 0;
|
||||||
|
for (item = list->next; item != list; item = item->next)
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef offsetof
|
||||||
|
#define offsetof(type, member) ((long) &((type *) 0)->member)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define dl_list_entry(item, type, member) \
|
||||||
|
((type *) ((char *) item - offsetof(type, member)))
|
||||||
|
|
||||||
|
#define dl_list_first(list, type, member) \
|
||||||
|
(dl_list_empty((list)) ? NULL : \
|
||||||
|
dl_list_entry((list)->next, type, member))
|
||||||
|
|
||||||
|
#define dl_list_for_each(item, list, type, member) \
|
||||||
|
for (item = dl_list_entry((list)->next, type, member); \
|
||||||
|
&item->member != (list); \
|
||||||
|
item = dl_list_entry(item->member.next, type, member))
|
||||||
|
|
||||||
|
#define dl_list_for_each_safe(item, n, list, type, member) \
|
||||||
|
for (item = dl_list_entry((list)->next, type, member), \
|
||||||
|
n = dl_list_entry(item->member.next, type, member); \
|
||||||
|
&item->member != (list); \
|
||||||
|
item = n, n = dl_list_entry(n->member.next, type, member))
|
||||||
|
|
||||||
|
#endif /* LIST_H */
|
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
|
@ -1,6 +1,7 @@
|
||||||
test-aes
|
test-aes
|
||||||
test-asn1
|
test-asn1
|
||||||
test-base64
|
test-base64
|
||||||
|
test-list
|
||||||
test-md4
|
test-md4
|
||||||
test-md5
|
test-md5
|
||||||
test-milenage
|
test-milenage
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
TESTS=test-base64 test-md4 test-md5 test-milenage test-ms_funcs test-sha1 \
|
TESTS=test-base64 test-md4 test-md5 test-milenage test-ms_funcs test-sha1 \
|
||||||
test-sha256 test-aes test-asn1 test-x509 test-x509v3
|
test-sha256 test-aes test-asn1 test-x509 test-x509v3 test-list
|
||||||
|
|
||||||
all: $(TESTS)
|
all: $(TESTS)
|
||||||
|
|
||||||
|
@ -45,6 +45,9 @@ test-asn1: test-asn1.o $(LIBS)
|
||||||
test-base64: test-base64.o $(LIBS)
|
test-base64: test-base64.o $(LIBS)
|
||||||
$(LDO) $(LDFLAGS) -o $@ $^
|
$(LDO) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
test-list: test-list.o $(LIBS)
|
||||||
|
$(LDO) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
test-md4: test-md4.o $(LIBS)
|
test-md4: test-md4.o $(LIBS)
|
||||||
$(LDO) $(LDFLAGS) -o $@ $^
|
$(LDO) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
@ -72,6 +75,7 @@ test-x509v3: test-x509v3.o $(LIBS)
|
||||||
|
|
||||||
run-tests: $(TESTS)
|
run-tests: $(TESTS)
|
||||||
./test-aes
|
./test-aes
|
||||||
|
./test-list
|
||||||
./test-md4
|
./test-md4
|
||||||
./test-md5
|
./test-md5
|
||||||
./test-milenage
|
./test-milenage
|
||||||
|
|
78
tests/test-list.c
Normal file
78
tests/test-list.c
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Doubly-linked list - test program
|
||||||
|
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Alternatively, this software may be distributed under the terms of BSD
|
||||||
|
* license.
|
||||||
|
*
|
||||||
|
* See README and COPYING for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils/includes.h"
|
||||||
|
#include "utils/os.h"
|
||||||
|
#include "utils/list.h"
|
||||||
|
|
||||||
|
struct test {
|
||||||
|
struct dl_list list;
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dump_list(struct dl_list *head)
|
||||||
|
{
|
||||||
|
struct test *t;
|
||||||
|
printf("dump:");
|
||||||
|
dl_list_for_each(t, head, struct test, list)
|
||||||
|
printf(" %d", t->value);
|
||||||
|
printf(" (len=%d%s)\n", dl_list_len(head),
|
||||||
|
dl_list_empty(head) ? " empty" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct dl_list head;
|
||||||
|
struct test *t, *tmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dl_list_init(&head);
|
||||||
|
dump_list(&head);
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
t = os_zalloc(sizeof(*t));
|
||||||
|
if (t == NULL)
|
||||||
|
return -1;
|
||||||
|
t->value = i;
|
||||||
|
dl_list_add(&head, &t->list);
|
||||||
|
dump_list(&head);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 10; i > 5; i--) {
|
||||||
|
t = os_zalloc(sizeof(*t));
|
||||||
|
if (t == NULL)
|
||||||
|
return -1;
|
||||||
|
t->value = i;
|
||||||
|
dl_list_add_tail(&head, &t->list);
|
||||||
|
dump_list(&head);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
dl_list_for_each(t, &head, struct test, list)
|
||||||
|
if (++i == 5)
|
||||||
|
break;
|
||||||
|
printf("move: %d\n", t->value);
|
||||||
|
dl_list_del(&t->list);
|
||||||
|
dl_list_add(&head, &t->list);
|
||||||
|
dump_list(&head);
|
||||||
|
|
||||||
|
dl_list_for_each_safe(t, tmp, &head, struct test, list) {
|
||||||
|
printf("delete: %d\n", t->value);
|
||||||
|
dl_list_del(&t->list);
|
||||||
|
os_free(t);
|
||||||
|
dump_list(&head);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue