From 7a1fcaa88c3836fc922fdc16199147d9cdcaa099 Mon Sep 17 00:00:00 2001
From: overflowerror <mail@overflowerror.com>
Date: Sat, 15 Apr 2017 00:13:28 +0200
Subject: [PATCH] we now have linked lists

---
 Makefile           |   7 +-
 crap.h             |   1 +
 example.c          |  23 ++++--
 lists/linkedlist.c | 169 +++++++++++++++++++++++++++++++++++++++++++++
 lists/linkedlist.h |  27 ++++++++
 5 files changed, 217 insertions(+), 10 deletions(-)
 create mode 100644 lists/linkedlist.c
 create mode 100644 lists/linkedlist.h

diff --git a/Makefile b/Makefile
index 7eb90f1..432c98e 100644
--- a/Makefile
+++ b/Makefile
@@ -17,13 +17,13 @@ all: example libcrap.so
 %.o: %.c
 	$(CC) $(CFLAGS) -c -o $@ $<
 
-example: example.o memory.o try.o oop.o exceptions/stdex.o tools/strbuilder.o lists/lists.o lists/arraylist.o
+example: example.o memory.o try.o oop.o exceptions/stdex.o tools/strbuilder.o lists/lists.o lists/arraylist.o lists/linkedlist.o
 	$(CC) $(LDFLAGS) -o $@ $^
 
-libcrap.so: memory.o try.o oop.o exceptions/stdex.o tools/strbuilder.o lists/lists.o lists/arraylist.o
+libcrap.so: memory.o try.o oop.o exceptions/stdex.o tools/strbuilder.o lists/lists.o lists/arraylist.o lists/linkedlist.o
 	$(CC) $(LIBFLAGS) -o $@ $^
 
-example.o: example.c try.h
+example.o: example.c try.h crap.h
 memory.o: memory.c memory.h oop.h exceptions/stdex.h
 try.o: try.c try.h oop.h exceptions/stdex.h
 oop.o: oop.h misc.h
@@ -34,6 +34,7 @@ tools/strbuilder.o: tools/strbuilder.c tools/strbuilder.h exceptions/stdex.h
 
 lists/lists.o: lists/lists.c lists/lists.h oop.h
 lists/arraylist.o: lists/arraylist.c lists/arraylist.h oop.h
+lists/linkedlist.o: lists/linkedlist.c lists/linkedlist.h oop.h
 
 clean:
 	rm -f *.o exceptions/*.o tools/*.o lists/*.o example
diff --git a/crap.h b/crap.h
index 4b8080c..17f103b 100644
--- a/crap.h
+++ b/crap.h
@@ -8,3 +8,4 @@
 
 #include "lists/lists.h"
 #include "lists/arraylist.h"
+#include "lists/linkedlist.h"
diff --git a/example.c b/example.c
index f1c18c0..07a82b0 100644
--- a/example.c
+++ b/example.c
@@ -3,13 +3,14 @@
 #include <stdio.h>
 
 int main(void) {
-	ArrayList_t* list = new ArrayList();
+	//ArrayList_t* list = new (ArrayList)();
+	LinkedList_t* list = new (LinkedList)();
 
 	printf("adding some strings\n");
-	list->add(list, "Hallo");
-	list->add(list, "Welt");
 	list->add(list, "Hello");
 	list->add(list, "World");
+	list->add(list, "Foo");
+	list->add(list, "Bar");
 
 	for (size_t i = 0; i < list->length(list); i++) {
 		printf("%lu: %s\n", i, (const char*) list->get(list, i));
@@ -22,11 +23,19 @@ int main(void) {
 		printf("%lu: %s\n", i, (const char*) list->get(list, i));
 	}
 
-	printf("\nremoving index %lu\n", list->length(list));
-	//list->remove(list, list->length(list));
-	//List_t* list2 = new List();
+	printf("\npush new string\n");
+	list->push(list, "Test");
 
-	Object_t* obj = new Object();
+	printf("poping string\n");
+	const char* string = list->pop(list);
+	printf(": %s\n", string);
+	
+
+	printf("\nremoving index %lu\n", list->length(list));
+
+	list->remove(list, list->length(list));
+
+	list->destruct(list);
 
 	return 0;
 }
diff --git a/lists/linkedlist.c b/lists/linkedlist.c
new file mode 100644
index 0000000..4a1525d
--- /dev/null
+++ b/lists/linkedlist.c
@@ -0,0 +1,169 @@
+#include "linkedlist.h"
+#include "lists.h"
+#include "../oop.h"
+#include "../try.h"
+#include "../exceptions/stdex.h"
+#include "../memory.h"
+
+#include <stdlib.h>
+
+#define DEFAULT_SIZE_STEP 64
+
+#define to_list(name, obj) LinkedList_t* name = (LinkedList_t*) obj 
+
+class_t LinkedList_class;
+
+LinkedList_t* method(LinkedList, construct)(void) {
+	throws(OutOfMemoryException_t);
+
+	sr_(LinkedList_t* list = allocate_object(LinkedList), NULL);
+	populate(LinkedList)(list, LinkedList_class);
+
+	return list;
+}
+
+size_t method(LinkedList, length)(void* this) {
+	to_list(list, this);
+	
+	LinkedListElement_t* elem = list->first;
+	
+	size_t size; 
+	for(size = 0; elem != NULL; size++) 
+		elem = elem->next;
+
+	return size;
+}
+
+void method(LinkedList, add)(void* this, void* obj) {	
+	throws(NullPointerException_t, OutOfMemoryException_t);
+	if (this == NULL)
+		throw(new (NullPointerException)());
+	
+	to_list(list, this);
+
+	s_(LinkedListElement_t* entry = allocate(sizeof(LinkedListElement_t)));
+
+	entry->next = NULL;
+	entry->data = obj;
+
+	if (list->first == NULL) {
+		list->first = entry;
+		return;
+	}
+
+	LinkedListElement_t* last = list->first;
+
+	for(; last->next != NULL; last = last->next);
+	
+	last->next = entry;
+}
+
+void* method(LinkedList, get)(void* this, size_t index) {
+	throws(NullPointerException_t, IndexOutOfBoundsException_t, IndexOutOfBoundsException_t);
+	if (this == NULL)
+		throwr(new (NullPointerException)(), NULL);
+	
+	to_list(list, this);
+
+	size_t size;
+	LinkedListElement_t* next;
+	
+	for(next = list->first, size = 0; next != NULL; size++, next = next->next) {
+		if (size == index)
+			return next->data;
+	}
+
+	throwr(new (IndexOutOfBoundsException)(index, size), NULL);
+}
+void method(LinkedList, remove)(void* this, size_t index) {
+	throws(NullPointerException_t, OutOfMemoryException_t, IndexOutOfBoundsException_t);
+	if (this == NULL)
+		throw(new (NullPointerException)());
+	
+	to_list(list, this);
+
+	size_t size;
+	LinkedListElement_t** next;
+
+	for(next = &(list->first), size = 0; (*next) != NULL; size++, next = &((*next)->next)) {
+		if (size == index) {
+			LinkedListElement_t* tmp;
+			tmp = *next;
+			*next = (*next)->next;
+			free(tmp);
+			return;
+		}
+	}
+
+	throw(new (IndexOutOfBoundsException)(index, size));
+}
+
+void method(LinkedList, push)(void* this, void* obj) {
+	throws(NullPointerException_t);
+	if (this == NULL)
+		throw(new (NullPointerException)());
+	
+	to_list(list, this);
+
+	list->add(list, obj);
+}
+
+void* method(LinkedList, pop)(void* this) {
+	throws(NullPointerException_t, OutOfMemoryException_t);
+	if (this == NULL)
+		throwr(new (NullPointerException)(), NULL);
+	
+	to_list(list, this);
+
+	if (list->first == NULL) {
+		return NULL; // TODO NoElementException?
+	}
+
+	if (list->first->next == NULL) {
+		void* value = list->first->data;
+		free(list->first);
+		list->first = NULL;
+		return value;
+	}
+
+	LinkedListElement_t* current;
+	LinkedListElement_t* prev;
+
+	for(prev = NULL, current = list->first; current->next != NULL; prev = current, current = current->next);
+
+	void* data = current->data;
+	free(current);
+	prev->next = NULL;
+	return data;
+	
+}
+
+void method(LinkedList, destruct)(LinkedList_t* this) {
+	throws(NullPointerException_t);
+	if (this == NULL)
+		throw(new (NullPointerException)());
+	
+	to_list(list, this);
+
+	for(LinkedListElement_t* next = list->first; next != NULL;) {
+		next = next->next;
+		free(next);
+	}
+
+	this->super.destruct((Object_t*) list);
+}
+
+void method(LinkedList, populate)(LinkedList_t* obj, class_t c) {
+	populate(Object)((Object_t*) obj, c);
+
+	obj->first = NULL;
+
+	add_method(obj, LinkedList, destruct);
+	add_method(obj, LinkedList, length);
+	add_method(obj, LinkedList, add);
+	add_method(obj, LinkedList, get);
+	add_method(obj, LinkedList, remove);
+	add_method(obj, LinkedList, push);
+	add_method(obj, LinkedList, pop);
+}
+
diff --git a/lists/linkedlist.h b/lists/linkedlist.h
new file mode 100644
index 0000000..35442c3
--- /dev/null
+++ b/lists/linkedlist.h
@@ -0,0 +1,27 @@
+#ifndef LINKEDLIST_H
+#define LINKEDLIST_H
+
+#include "../oop.h"
+#include "lists.h"
+
+typedef struct LinkedListElement {
+	void* data;
+	struct LinkedListElement* next;
+} LinkedListElement_t;
+
+// #define LinkedList construct(LinkedList)
+extern class(LinkedList, Object_class, (interfaces){4 namely {Cloneable_class and List_class and Countable_class and Stack_class}}, true) {
+	extends(Object_t);
+	implements(Cloneable);
+	implements(List);
+	implements(Countable);
+	implements(Stack);
+	void (*destruct)(defclass LinkedList*);
+
+	LinkedListElement_t* first;
+} LinkedList_t;
+
+LinkedList_t* method(LinkedList, construct)(void);
+void method(LinkedList, populate)(LinkedList_t*, class_t);
+
+#endif