|
|
@@ -0,0 +1,175 @@
|
|
|
+#include <stdint.h>
|
|
|
+#include <stddef.h>
|
|
|
+#include <stdbool.h>
|
|
|
+
|
|
|
+#include "zalloc.h"
|
|
|
+#include "systypes.h"
|
|
|
+
|
|
|
+#include "vector.h"
|
|
|
+
|
|
|
+
|
|
|
+static zv_vector_container_t * zv__vector_container_create(void) {
|
|
|
+ zv_vector_container_t *created
|
|
|
+ = (zv_vector_container_t *) zv_malloc(sizeof(zv_vector_container_t));
|
|
|
+
|
|
|
+ created->next = NULL;
|
|
|
+ created->previous = NULL;
|
|
|
+
|
|
|
+ return created;
|
|
|
+}
|
|
|
+
|
|
|
+static void zv__vector_container_drop(zv_vector_container_t *self) {
|
|
|
+ zv_free(self);
|
|
|
+}
|
|
|
+
|
|
|
+static zv_vector_container_t * zv__vector_get_container(
|
|
|
+ zv_vector_t *self,
|
|
|
+ size_t index
|
|
|
+) {
|
|
|
+ if (self->length <= index) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (index < self->length / 2) {
|
|
|
+ zv_vector_container_t *current = self->first;
|
|
|
+
|
|
|
+ while (index > 0) {
|
|
|
+ current = current->next;
|
|
|
+ --index;
|
|
|
+ }
|
|
|
+
|
|
|
+ return current;
|
|
|
+ }
|
|
|
+
|
|
|
+ zv_vector_container_t *current = self->last;
|
|
|
+
|
|
|
+ index = self->length - index;
|
|
|
+
|
|
|
+ while (index > 0) {
|
|
|
+ current = current->previous;
|
|
|
+ --index;
|
|
|
+ }
|
|
|
+
|
|
|
+ return current;
|
|
|
+}
|
|
|
+
|
|
|
+zv_vector_t * zv_vector_create(void) {
|
|
|
+ zv_vector_t *self = (zv_vector_t *) zv_malloc(sizeof(zv_vector_t));
|
|
|
+
|
|
|
+ if (self == NULL) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ self->length = 0x00;
|
|
|
+ self->first = NULL;
|
|
|
+ self->last = NULL;
|
|
|
+
|
|
|
+ return self;
|
|
|
+}
|
|
|
+
|
|
|
+bool zv_vector_append(zv_vector_t *self, zv_universal_t content) {
|
|
|
+ return zv_vector_insert(self, content, self->length);
|
|
|
+}
|
|
|
+
|
|
|
+zv_universal_t zv_vector_pop(zv_vector_t *self) {
|
|
|
+ return zv_vector_indexed_pop(self, self->length - 1);
|
|
|
+}
|
|
|
+
|
|
|
+bool zv_vector_insert(
|
|
|
+ zv_vector_t *self,
|
|
|
+ zv_universal_t content,
|
|
|
+ size_t index
|
|
|
+) {
|
|
|
+ if (index > self->length) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ zv_vector_container_t *target = zv__vector_container_create();
|
|
|
+
|
|
|
+ if (target == NULL) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ target->content = content;
|
|
|
+
|
|
|
+ if (index == 0) {
|
|
|
+ target->previous = NULL;
|
|
|
+ target->next = self->first;
|
|
|
+ self->first = target;
|
|
|
+
|
|
|
+ ++self->length;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (index == self->length) {
|
|
|
+ target->next = NULL;
|
|
|
+ target->previous = self->last;
|
|
|
+ self->last = target;
|
|
|
+
|
|
|
+ ++self->length;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ target->previous = zv__vector_get_container(self, index - 1);
|
|
|
+ target->next = target->previous->next;
|
|
|
+
|
|
|
+ target->previous->next = target;
|
|
|
+ target->next->previous = target;
|
|
|
+
|
|
|
+ ++self->length;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+zv_universal_t zv_vector_indexed_pop(zv_vector_t *self, size_t index) {
|
|
|
+ zv_vector_container_t *container = zv__vector_get_container(self, index);
|
|
|
+
|
|
|
+ if (container == NULL) {
|
|
|
+ return ZV_UNIVERSAL_NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ zv_universal_t content = container->content;
|
|
|
+
|
|
|
+ if (index == 0) {
|
|
|
+ self->first = container->next;
|
|
|
+ self->first->previous = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (index == self->length - 1) {
|
|
|
+ self->last = container->previous;
|
|
|
+ self->last->next = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (index != 0 && index != self->length - 1) {
|
|
|
+ container->next->previous = container->previous;
|
|
|
+ container->previous->next = container->next;
|
|
|
+ }
|
|
|
+
|
|
|
+ --self->length;
|
|
|
+ zv__vector_container_drop(container);
|
|
|
+
|
|
|
+ return content;
|
|
|
+}
|
|
|
+
|
|
|
+void zv_vector_clear(zv_vector_t *self) {
|
|
|
+ if (self->length == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ zv_vector_container_t *current = self->first;
|
|
|
+
|
|
|
+ while (current != NULL) {
|
|
|
+ zv_vector_container_t *previous = current;
|
|
|
+ current = current->next;
|
|
|
+
|
|
|
+ zv__vector_container_drop(previous);
|
|
|
+ }
|
|
|
+
|
|
|
+ self->first = NULL;
|
|
|
+ self->last = NULL;
|
|
|
+ self->length = 0;
|
|
|
+}
|
|
|
+
|
|
|
+void zv_vector_remove(zv_vector_t *self) {
|
|
|
+ zv_vector_clear(self);
|
|
|
+ zv_free(self);
|
|
|
+}
|