shithub: ircd

Download patch

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
 {
--