aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-12-19 11:43:25 (GMT)
committerJouni Malinen <j@w1.fi>2009-12-19 11:43:25 (GMT)
commitdacf47835208a24ae5ba51c4a869b36339f78897 (patch)
treec5d38334b051d530cb34d4df949d9d261a1150a8
parentd2e6100c1671a96377e44efa92d51a75f1d650fa (diff)
downloadhostap-dacf47835208a24ae5ba51c4a869b36339f78897.zip
hostap-dacf47835208a24ae5ba51c4a869b36339f78897.tar.gz
hostap-dacf47835208a24ae5ba51c4a869b36339f78897.tar.bz2
Add generic doubly-linked list implementation
-rw-r--r--src/utils/list.h89
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile6
-rw-r--r--tests/test-list.c78
4 files changed, 173 insertions, 1 deletions
diff --git a/src/utils/list.h b/src/utils/list.h
new file mode 100644
index 0000000..ed7c022
--- /dev/null
+++ b/src/utils/list.h
@@ -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 */
diff --git a/tests/.gitignore b/tests/.gitignore
index 9c64aa6..5b992a3 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,6 +1,7 @@
test-aes
test-asn1
test-base64
+test-list
test-md4
test-md5
test-milenage
diff --git a/tests/Makefile b/tests/Makefile
index dcb9a2d..210a1b4 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,5 +1,5 @@
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)
@@ -45,6 +45,9 @@ test-asn1: test-asn1.o $(LIBS)
test-base64: test-base64.o $(LIBS)
$(LDO) $(LDFLAGS) -o $@ $^
+test-list: test-list.o $(LIBS)
+ $(LDO) $(LDFLAGS) -o $@ $^
+
test-md4: test-md4.o $(LIBS)
$(LDO) $(LDFLAGS) -o $@ $^
@@ -72,6 +75,7 @@ test-x509v3: test-x509v3.o $(LIBS)
run-tests: $(TESTS)
./test-aes
+ ./test-list
./test-md4
./test-md5
./test-milenage
diff --git a/tests/test-list.c b/tests/test-list.c
new file mode 100644
index 0000000..930ce41
--- /dev/null
+++ b/tests/test-list.c
@@ -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;
+}