1 /* this is the brisby fancy list */
2 #ifndef __list_h
3 #define __list_h
4
5 #include "mem.h"
6 #include "error.h"
7
8 #include <stdlib.h>
9
10 struct list_s {
11 char *str;
12 struct list_s *next;
13 };
14
15 typedef struct list_s *list_t;
16
list_length(list_t x)17 static int inline list_length(list_t x) {
18 int i;
19 for (i = 0; x; x = x->next, i++);
20 return i;
21 }
list_push(list_t * x,char * str)22 static void inline list_push(list_t *x, char *str) {
23 list_t p;
24
25 /* never push empty stuff on */
26 if (str == 0)
27 return;
28
29 p = mem_alloc(sizeof(list_t));
30 if (!p)
31 cfatal("mem_alloc: %s");
32 p->next = (*x);
33 p->str = str;
34 *x = p;
35 }
list_pop(list_t * x)36 static char inline *list_pop(list_t *x) {
37 list_t p;
38 char *q;
39
40 p = (*x);
41 if (p) {
42 *x = p->next;
43 q = p->str;
44 mem_free(p);
45 } else
46 q = 0;
47 return q;
48 }
list_reverse(list_t * p)49 static void inline list_reverse(list_t *p) {
50 list_t x = 0;
51 char *q;
52
53 if (!p || !*p)
54 return;
55 while ((q = list_pop(p))) {
56 list_push(&x, q);
57 }
58 *p = x;
59 }
__list_randomize_helper(list_t * x)60 static char inline *__list_randomize_helper(list_t *x)
61 {
62 char *q;
63 list_t p;
64 if (!x || !*x || !(*x)->next) return 0;
65 q = (*x)->next->str;
66 p = (*x)->next;
67 (*x)->next = (*x)->next->next;
68 mem_free(p);
69 return q;
70 }
list_randomize(list_t * p)71 static void inline list_randomize(list_t *p) {
72 list_t x = 0, y;
73 int i, j, k, q, z;
74 char *s;
75
76 /* no need */
77 if (!p || !*p || !(*p)->next)
78 return;
79 if (!(*p)->next->next) {
80 /* shortcut */
81 if (rand() % 2 == 0) {
82 list_reverse(p);
83 }
84 return;
85 }
86 /* count list elements */
87 for (i = 0, x = *p; x; i++, x = x->next);
88
89 /* x is 0 again */
90 j = i;
91 for (z = j*j; z > 0; z--) {
92 i = j; while (i > 2 && *p) {
93 k = rand() % (i+1);
94 for (y = *p, q = 0; q < k; q++, y = y->next);
95 if (!y) {
96 i--;
97 list_push(&x, list_pop(p));
98 continue;
99 }
100 s = __list_randomize_helper(&y);
101 if (!s) continue;
102 list_push(&x, s);
103 i--;
104 }
105 while (*p) {
106 list_push(&x, list_pop(p));
107 }
108 }
109 *p = x;
110 }
111
112 #endif
113