ref: b7b579414649750ca39b3ba85bb17dc32bdfb6da
parent: 117bc0cd9615e08d4b583ddb87fa55d05610f532
author: sirjofri <sirjofri@sirjofri.de>
date: Mon Jul 21 17:51:15 EDT 2025
adds generic linked list, fixes tests
--- /dev/null
+++ b/ll.c
@@ -1,0 +1,58 @@
+#include <u.h>
+#include <libc.h>
+#include "ll.h"
+
+void
+ladd(Linked **ll, void *ptr)
+{
+ Linked *l;
+ l = mallocz(sizeof(Linked), 1);
+ l->ptr = ptr;
+
+ if (!(*ll)) {
+ *ll = l;
+ return;
+ }
+ l->next = *ll;
+ (*ll)->prev = l;
+ (*ll) = l;
+}
+
+void
+ldel(Linked **ll, void *ptr, void (*f)(void*))
+{
+ Linked *l = nil;
+ if (!(*ll))
+ return;
+ for (Linked *fl = *ll; fl; fl = fl->next) {
+ if (fl->ptr == ptr) {
+ l = fl;
+ break;
+ }
+ }
+
+ if (!l)
+ return;
+
+ if (!l->prev) {
+ *ll = l->next;
+ if (l->next)
+ l->next->prev = nil;
+ } else {
+ l->prev->next = l->next;
+ if (l->next)
+ l->next->prev = l->prev;
+ }
+ if (f)
+ f(l->ptr);
+}
+
+void*
+lfind(Linked **ll, int (*f)(void*,void*), void *aux)
+{
+ for (Linked *l = *ll; l; l = l->next) {
+ if (f(l->ptr, aux))
+ return l->ptr;
+ }
+ return nil;
+}
--- /dev/null
+++ b/ll.h
@@ -1,0 +1,11 @@
+typedef struct Linked Linked;
+struct Linked
+{
+ void *ptr;
+ Linked *next;
+ Linked *prev;
+};
+
+void ladd(Linked**, void*);
+void ldel(Linked**, void*, void (*f)(void*));
+void* lfind(Linked**, int (*f)(void*,void*), void*);
--- a/mkfile
+++ b/mkfile
@@ -9,7 +9,8 @@
reply.$O\
users.$O\
client.$O\
+ ll.$O\
-HFILES=fns.h dat.h cmd.h version.h
+HFILES=fns.h dat.h cmd.h version.h ll.h
</sys/src/cmd/mkone
--- /dev/null
+++ b/test/lltest.c
@@ -1,0 +1,81 @@
+#include <u.h>
+#include <libc.h>
+#include "../ll.h"
+
+Linked *list = nil;
+
+int fail = 0;
+
+static int
+find(void *ptr, void *aux)
+{
+ return ptr == aux;
+}
+
+static void
+destr(void *ptr)
+{
+ char c = (char)ptr;
+ fprint(2, "fail: destructor called for %c\n", c);
+ fail = 1;
+}
+
+static void
+test(char c, int exp)
+{
+ char r = (char)lfind(&list, find, (void*)c);
+ char found = r == c;
+ if (found) {
+ if (!exp) {
+ fail = 1;
+ goto Fail;
+ }
+ } else {
+ if (exp) {
+ fail = 1;
+ goto Fail;
+ }
+ }
+ return;
+Fail:
+ fprint(2, "fail: %c was%s expected, but was%s found!\n", c,
+ exp ? "" : " not",
+ found ? "" : " not"
+ );
+}
+
+static void
+testall(int a, int b, int c, int d)
+{
+ test('a', a);
+ test('b', b);
+ test('c', c);
+ test('d', d);
+}
+
+void
+main(int, char**)
+{
+ testall(0, 0, 0, 0);
+ ladd(&list, (void*)'a');
+ testall(1, 0, 0, 0);
+ ladd(&list, (void*)'b');
+ testall(1, 1, 0, 0);
+ ladd(&list, (void*)'c');
+ testall(1, 1, 1, 0);
+
+ ldel(&list, (void*)'b', nil);
+ testall(1, 0, 1, 0);
+ ladd(&list, (void*)'b');
+ testall(1, 1, 1, 0);
+
+ ldel(&list, (void*)'a', nil);
+ testall(0, 1, 1, 0);
+
+ ldel(&list, (void*)'c', nil);
+ testall(0, 1, 0, 0);
+
+ ldel(&list, (void*)'c', destr);
+
+ exits(fail ? "failed" : nil);
+}
--- a/test/mkfile
+++ b/test/mkfile
@@ -2,7 +2,9 @@
TEST=\
parsetest\
+ lltest\
</sys/src/cmd/mktest
$O.parsetest: ../parse.$O ../cmd.$O ../fmt.$O
+$O.lltest: ../ll.$O
--- a/test/parsetest.c
+++ b/test/parsetest.c
@@ -3,6 +3,42 @@
#include "../dat.h"
#include "../fns.h"
+int debug;
+char *sysnameb;
+char *welcome;
+
+char*
+getversion(void)
+{
+ return "";
+}
+
+User*
+finduser(char*)
+{
+ return nil;
+}
+
+User*
+adduser(char*)
+{
+ return nil;
+}
+
+Client*
+findnick(char*)
+{
+ return nil;
+}
+
+void
+reply(Client*, Reply r, ...)
+{
+ va_list arg;
+ va_start(arg, r);
+ va_end(arg);
+}
+
typedef struct Req Req;
struct Req
{
--
⑨