diff --git a/doc/utlist.txt b/doc/utlist.txt index 47dc625..aa96514 100644 --- a/doc/utlist.txt +++ b/doc/utlist.txt @@ -108,6 +108,7 @@ iterating over them. |LL_INSERT_INORDER(head,add,cmp); | DL_INSERT_INORDER(head,add,cmp); | CDL_INSERT_INORDER(head,add,cmp); |LL_CONCAT(head1,head2); | DL_CONCAT(head1,head2); | |LL_DELETE(head,del); | DL_DELETE(head,del); | CDL_DELETE(head,del); +|LL_REVERSE(head); | DL_REVERSE(head); | CDL_REVERSE(head); |LL_SORT(head,cmp); | DL_SORT(head,cmp); | CDL_SORT(head,cmp); |LL_FOREACH(head,elt) {...}| DL_FOREACH(head,elt) {...} | CDL_FOREACH(head,elt) {...} |LL_FOREACH_SAFE(head,elt,tmp) {...}| DL_FOREACH_SAFE(head,elt,tmp) {...} | CDL_FOREACH_SAFE(head,elt,tmp1,tmp2) {...} @@ -281,6 +282,7 @@ the `prev` and `next` fields (as applicable) as trailing arguments. |LL_INSERT_INORDER2(head,add,cmp,next); | DL_INSERT_INORDER2(head,add,cmp,prev,next); | CDL_INSERT_INORDER2(head,add,cmp,prev,next); |LL_CONCAT2(head1,head2,next); | DL_CONCAT2(head1,head2,prev,next); | |LL_DELETE2(head,del,next); | DL_DELETE2(head,del,prev,next); | CDL_DELETE2(head,del,prev,next); +|LL_REVERSE2(head,next); | DL_REVERSE2(head,prev,next); | CDL_REVERSE2(head,prev,next); |LL_SORT2(head,cmp,next); | DL_SORT2(head,cmp,prev,next); | CDL_SORT2(head,cmp,prev,next); |LL_FOREACH2(head,elt,next) {...} | DL_FOREACH2(head,elt,next) {...} | CDL_FOREACH2(head,elt,next) {...} |LL_FOREACH_SAFE2(head,elt,tmp,next) {...} | DL_FOREACH_SAFE2(head,elt,tmp,next) {...} | CDL_FOREACH_SAFE2(head,elt,tmp1,tmp2,prev,next) {...} diff --git a/src/utlist.h b/src/utlist.h index 9794b5f..5723591 100644 --- a/src/utlist.h +++ b/src/utlist.h @@ -444,6 +444,23 @@ do { } \ } while (0) +#define LL_REVERSE(head) \ + LL_REVERSE2(head,next) + +#define LL_REVERSE2(head,next) \ +do { \ + LDECLTYPE(head) _curr = (head); \ + LDECLTYPE(head) _prev = NULL; \ + LDECLTYPE(head) _next; \ + while (_curr) { \ + _next = _curr->next; \ + _curr->next = _prev; \ + _prev = _curr; \ + _curr = _next; \ + } \ + (head) = _prev; \ +} while (0) + #define LL_REPLACE_ELEM2(head, el, add, next) \ do { \ LDECLTYPE(head) _tmp; \ @@ -615,6 +632,22 @@ do { } \ } while (0) \ +#undef LL_REVERSE2 +#define LL_REVERSE2(head,next) \ +do { \ + if (head) { \ + char *_prev = NULL; \ + char *_next = NULL; \ + while (head) { \ + UTLIST_CASTASGN(_next, (head)->next); \ + UTLIST_CASTASGN((head)->next, _prev); \ + UTLIST_CASTASGN(_prev, (head)); \ + UTLIST_CASTASGN((head), _next); \ + } \ + UTLIST_CASTASGN((head), _prev); \ + } \ +} while (0) + #endif /* NO_DECLTYPE */ /****************************************************************************** @@ -753,6 +786,27 @@ do { #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 #define DL_SEARCH2 LL_SEARCH2 +#define DL_REVERSE(head) \ + DL_REVERSE2(head,prev,next) + +#define DL_REVERSE2(head,prev,next) \ +do { \ + if ((head) && (head)->next) { \ + LDECLTYPE(head) _tail = (head); \ + LDECLTYPE(head) _curr = (head); \ + LDECLTYPE(head) _prev = NULL; \ + while (_curr) { \ + _prev = _curr->prev; \ + _curr->prev = _curr->next; \ + _curr->next = _prev; \ + _curr = _curr->prev; \ + } \ + (head) = _prev->prev; \ + _tail->next = NULL; \ + (head)->prev = _tail; \ + } \ +} while (0) + #define DL_REPLACE_ELEM2(head, el, add, prev, next) \ do { \ assert((head) != NULL); \ @@ -855,6 +909,31 @@ do { } \ } \ } while (0) + +#undef DL_REVERSE2 +#define DL_REVERSE2(head,prev,next) \ +do { \ + if ((head) && (head)->next) { \ + char *_tail; \ + char *_prev; \ + char *_tmp; \ + UTLIST_CASTASGN(_tail, (head)); \ + while (head) { \ + UTLIST_CASTASGN(_prev, (head)->prev); \ + (head)->prev = (head)->next; \ + UTLIST_CASTASGN((head)->next, _prev); \ + (head) = (head)->prev; \ + } \ + UTLIST_CASTASGN((head), _prev); \ + (head) = (head)->prev; \ + UTLIST_CASTASGN(_tmp, (head)); \ + UTLIST_CASTASGN((head), _tail); \ + (head)->next = NULL; \ + UTLIST_CASTASGN((head), _tmp); \ + UTLIST_CASTASGN((head)->prev, _tail); \ + } \ +} while (0) + #endif /* NO_DECLTYPE */ /****************************************************************************** @@ -983,6 +1062,24 @@ do { } \ } while (0) +#define CDL_REVERSE(head) \ + CDL_REVERSE2(head,prev,next) + +#define CDL_REVERSE2(head,prev,next) \ +do { \ + if ((head) && (head)->next) { \ + LDECLTYPE(head) _curr = (head); \ + LDECLTYPE(head) _prev = NULL; \ + do { \ + _prev = _curr->prev; \ + _curr->prev = _curr->next; \ + _curr->next = _prev; \ + _curr = _curr->prev; \ + } while(_curr != (head)); \ + (head) = (head)->next; \ + } \ +} while (0) + #define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ do { \ assert((head) != NULL); \ @@ -1071,6 +1168,24 @@ do { UTLIST_RS(head); \ } \ } while (0) + +#undef CDL_REVERSE2 +#define CDL_REVERSE2(head,prev,next) \ +do { \ + if ((head) && (head)->next) { \ + char *_curr; \ + char *_prev; \ + UTLIST_CASTASGN(_curr, (head)); \ + do { \ + UTLIST_CASTASGN(_prev, (head)->prev); \ + (head)->prev = (head)->next; \ + UTLIST_CASTASGN((head)->next, _prev); \ + (head) = (head)->prev; \ + } while(_curr != (char*)(head)); \ + (head) = (head)->next; \ + } \ +} while (0) + #endif /* NO_DECLTYPE */ #endif /* UTLIST_H */ diff --git a/tests/Makefile b/tests/Makefile index e96a109..e9e6737 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -13,7 +13,7 @@ PROGS = test1 test2 test3 test4 test5 test6 test7 test8 test9 \ test74 test75 test76 test77 test78 test79 test80 test81 \ test82 test83 test84 test85 test86 test87 test88 test89 \ test90 test91 test92 test93 test94 test95 test96 test97 \ - test98 test99 test100 + test98 test99 test100 test101 test102 test103 CFLAGS += -I$(HASHDIR) #CFLAGS += -DHASH_BLOOM=16 #CFLAGS += -O2 diff --git a/tests/test101.ans b/tests/test101.ans new file mode 100644 index 0000000..804c021 --- /dev/null +++ b/tests/test101.ans @@ -0,0 +1,13 @@ +0 +1 +2 +4 +8 +16 +32 +64 +128 +256 +512 +1024 +2048 diff --git a/tests/test101.c b/tests/test101.c new file mode 100644 index 0000000..b4a0618 --- /dev/null +++ b/tests/test101.c @@ -0,0 +1,38 @@ +#include +#include +#include "utlist.h" + +typedef struct List { + int value; + struct List *next; +} List; + +int main(void) { + List *list = NULL, *node, *tmp; + int i; + + for(i = 1; i <= 1024; i <<= 1) { + node = (List*)malloc(sizeof(*node)); + node->value = i; + LL_PREPEND(list, node); + } + + LL_REVERSE(list); + + node = (List*)malloc(sizeof(*node)); + node->value = 0; + LL_PREPEND(list, node); + + node = (List*)malloc(sizeof(*node)); + node->value = 2048; + LL_APPEND(list, node); + + LL_FOREACH(list, node) { + printf("%d\n", node->value); + } + + LL_FOREACH_SAFE(list, node, tmp) { + LL_DELETE(list, node); + free(node); + } +} diff --git a/tests/test102.ans b/tests/test102.ans new file mode 100644 index 0000000..8e0e6e4 --- /dev/null +++ b/tests/test102.ans @@ -0,0 +1,13 @@ +2048 +1024 +512 +256 +128 +64 +32 +16 +8 +4 +2 +1 +0 diff --git a/tests/test102.c b/tests/test102.c new file mode 100644 index 0000000..cb3f365 --- /dev/null +++ b/tests/test102.c @@ -0,0 +1,39 @@ +#include +#include +#include "utlist.h" + +typedef struct List { + int value; + struct List *prev; + struct List *next; +} List; + +int main(void) { + List *list = NULL, *node, *tmp; + int i; + + for(i = 1; i <= 1024; i <<= 1) { + node = (List*)malloc(sizeof(*node)); + node->value = i; + DL_APPEND(list, node); + } + + DL_REVERSE(list); + + node = (List*)malloc(sizeof(*node)); + node->value = 0; + DL_APPEND(list, node); + + node = (List*)malloc(sizeof(*node)); + node->value = 2048; + DL_PREPEND(list, node); + + DL_FOREACH(list, node) { + printf("%d\n", node->value); + } + + DL_FOREACH_SAFE(list, node, tmp) { + LL_DELETE(list, node); + free(node); + } +} diff --git a/tests/test103.ans b/tests/test103.ans new file mode 100644 index 0000000..8e0e6e4 --- /dev/null +++ b/tests/test103.ans @@ -0,0 +1,13 @@ +2048 +1024 +512 +256 +128 +64 +32 +16 +8 +4 +2 +1 +0 diff --git a/tests/test103.c b/tests/test103.c new file mode 100644 index 0000000..a68bec8 --- /dev/null +++ b/tests/test103.c @@ -0,0 +1,40 @@ +#include +#include +#include "utlist.h" + +typedef struct List { + int value; + struct List *prev; + struct List *next; +} List; + +int main(void) { + List *list = NULL, *node, + *tmp1, *tmp2; + int i; + + for(i = 1; i <= 1024; i <<= 1) { + node = (List*)malloc(sizeof(*node)); + node->value = i; + CDL_APPEND(list, node); + } + + CDL_REVERSE(list); + + node = (List*)malloc(sizeof(*node)); + node->value = 0; + CDL_APPEND(list, node); + + node = (List*)malloc(sizeof(*node)); + node->value = 2048; + CDL_PREPEND(list, node); + + CDL_FOREACH(list, node) { + printf("%d\n", node->value); + } + + CDL_FOREACH_SAFE(list, node, tmp1, tmp2) { + CDL_DELETE(list, node); + free(node); + } +}