summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dimension/parse.c2
-rw-r--r--libdimension/Makefile.am2
-rw-r--r--libdimension/dimension.h1
-rw-r--r--libdimension/dimension/array.h4
-rw-r--r--libdimension/dimension/list.h194
-rw-r--r--libdimension/list.c45
6 files changed, 246 insertions, 2 deletions
diff --git a/dimension/parse.c b/dimension/parse.c
index c50d03f..802a3e5 100644
--- a/dimension/parse.c
+++ b/dimension/parse.c
@@ -683,6 +683,7 @@ dmnsn_eval_unary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
ret.type = DMNSN_AST_VECTOR;
dmnsn_astnode op = dmnsn_copy_astnode(astnode);
+ dmnsn_array_resize(op.children, 1);
for (i = 0; i < DMNSN_VECTOR_NELEM; ++i) {
dmnsn_array_get(rhs.children, i, dmnsn_array_at(op.children, 0));
dmnsn_astnode temp = dmnsn_eval_unary(op, symtable);
@@ -1286,6 +1287,7 @@ dmnsn_eval_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
ret.type = DMNSN_AST_VECTOR;
dmnsn_astnode op = dmnsn_copy_astnode(astnode);
+ dmnsn_array_resize(op.children, 2);
for (i = 0; i < DMNSN_VECTOR_NELEM; ++i) {
dmnsn_array_get(lhs.children, i, dmnsn_array_at(op.children, 0));
dmnsn_array_get(rhs.children, i, dmnsn_array_at(op.children, 1));
diff --git a/libdimension/Makefile.am b/libdimension/Makefile.am
index 7b3cee0..535bd69 100644
--- a/libdimension/Makefile.am
+++ b/libdimension/Makefile.am
@@ -34,6 +34,7 @@ nobase_include_HEADERS = dimension.h \
dimension/interior.h \
dimension/light.h \
dimension/lights.h \
+ dimension/list.h \
dimension/malloc.h \
dimension/object.h \
dimension/objects.h \
@@ -64,6 +65,7 @@ libdimension_la_SOURCES = $(nobase_include_HEADERS) \
inlines.c \
interior.c \
light.c \
+ list.c \
malloc.c \
object.c \
perspective.c \
diff --git a/libdimension/dimension.h b/libdimension/dimension.h
index 5aca9b3..2ad0c16 100644
--- a/libdimension/dimension.h
+++ b/libdimension/dimension.h
@@ -63,6 +63,7 @@ typedef void dmnsn_free_fn(void *ptr);
#include <dimension/error.h>
#include <dimension/malloc.h>
#include <dimension/array.h>
+#include <dimension/list.h>
#include <dimension/progress.h>
#include <dimension/geometry.h>
#include <dimension/color.h>
diff --git a/libdimension/dimension/array.h b/libdimension/dimension/array.h
index f840e58..e383ece 100644
--- a/libdimension/dimension/array.h
+++ b/libdimension/dimension/array.h
@@ -105,11 +105,11 @@ dmnsn_array_set(dmnsn_array *array, size_t i, const void *obj)
/* Element access */
DMNSN_INLINE void *
-dmnsn_array_at(dmnsn_array *array, size_t i)
+dmnsn_array_at(const dmnsn_array *array, size_t i)
{
if (i >= dmnsn_array_size(array)) {
/* Resize if i is out of range */
- dmnsn_array_resize(array, i + 1);
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Array index out of bounds.");
}
return (char *)array->ptr + array->obj_size*i;
}
diff --git a/libdimension/dimension/list.h b/libdimension/dimension/list.h
new file mode 100644
index 0000000..deb7622
--- /dev/null
+++ b/libdimension/dimension/list.h
@@ -0,0 +1,194 @@
+/*************************************************************************
+ * Copyright (C) 2010 Tavian Barnes <tavianator@gmail.com> *
+ * *
+ * This file is part of The Dimension Library. *
+ * *
+ * The Dimension Library is free software; you can redistribute it and/ *
+ * or modify it under the terms of the GNU Lesser General Public License *
+ * as published by the Free Software Foundation; either version 3 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * The Dimension Library is distributed in the hope that it will be *
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty *
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+/*
+ * Simple generalized doubly-linked lists.
+ */
+
+#ifndef DIMENSION_LIST_H
+#define DIMENSION_LIST_H
+
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct dmnsn_list_iterator {
+ void *ptr;
+ size_t obj_size;
+ struct dmnsn_list_iterator *prev, *next;
+} dmnsn_list_iterator;
+
+/* Internal iterator allocation */
+
+DMNSN_INLINE dmnsn_list_iterator *
+dmnsn_new_list_iterator(const void *obj, size_t obj_size)
+{
+ dmnsn_list_iterator *i
+ = (dmnsn_list_iterator *)dmnsn_malloc(sizeof(dmnsn_list_iterator));
+ i->obj_size = obj_size;
+ i->prev = NULL;
+ i->next = NULL;
+ i->ptr = dmnsn_malloc(obj_size);
+ memcpy(i->ptr, obj, obj_size);
+ return i;
+}
+
+DMNSN_INLINE void
+dmnsn_delete_list_iterator(dmnsn_list_iterator *i)
+{
+ if (i) {
+ free(i->ptr);
+ free(i);
+ }
+}
+
+typedef struct dmnsn_list {
+ dmnsn_list_iterator *first, *last;
+ size_t obj_size, length;
+} dmnsn_list;
+
+/* List allocation */
+DMNSN_INLINE dmnsn_list *
+dmnsn_new_list(size_t obj_size)
+{
+ dmnsn_list *list = (dmnsn_list *)dmnsn_malloc(sizeof(dmnsn_list));
+ list->first = NULL;
+ list->last = NULL;
+ list->obj_size = obj_size;
+ list->length = 0;
+ return list;
+}
+
+/* Construction from arrays */
+dmnsn_list *dmnsn_list_from_array(const dmnsn_array *array);
+/* Delete a list */
+void dmnsn_delete_list(dmnsn_list *list);
+
+DMNSN_INLINE dmnsn_list_iterator *
+dmnsn_list_first(dmnsn_list *list)
+{
+ return list->first;
+}
+
+DMNSN_INLINE dmnsn_list_iterator *
+dmnsn_list_last(dmnsn_list *list)
+{
+ return list->last;
+}
+
+DMNSN_INLINE dmnsn_list_iterator *
+dmnsn_list_prev(dmnsn_list_iterator *i)
+{
+ if (!i)
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "NULL list iterator.");
+ return i->prev;
+}
+
+DMNSN_INLINE dmnsn_list_iterator *
+dmnsn_list_next(dmnsn_list_iterator *i)
+{
+ if (!i)
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "NULL list iterator.");
+ return i->next;
+}
+
+DMNSN_INLINE size_t
+dmnsn_list_size(dmnsn_list *list)
+{
+ return list->length;
+}
+
+/* Get the i'th object */
+DMNSN_INLINE void
+dmnsn_list_get(const dmnsn_list_iterator *i, void *obj)
+{
+ if (!i)
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "NULL list iterator.");
+ memcpy(obj, i->ptr, i->obj_size);
+}
+
+/* Set the i'th object, expanding the list if necessary */
+DMNSN_INLINE void
+dmnsn_list_set(dmnsn_list_iterator *i, const void *obj)
+{
+ if (!i)
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "NULL list iterator.");
+ memcpy(i->ptr, obj, i->obj_size);
+}
+
+/* Insert an item before `i' */
+DMNSN_INLINE void
+dmnsn_list_insert(dmnsn_list *list, dmnsn_list_iterator *i, const void *obj)
+{
+ if (!i)
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "NULL list iterator.");
+ dmnsn_list_iterator *j = dmnsn_new_list_iterator(obj, list->obj_size);
+ if (list->first == i)
+ list->first = j;
+ j->next = i;
+ j->prev = i->prev;
+ i->prev = j;
+ ++list->length;
+}
+
+/* Remove the specified item */
+DMNSN_INLINE void
+dmnsn_list_remove(dmnsn_list *list, dmnsn_list_iterator *i)
+{
+ if (!i)
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "NULL list iterator.");
+ if (list->first == i)
+ list->first = i->next;
+ if (list->last == i)
+ list->last = i->prev;
+ if (i->prev)
+ i->prev->next = i->next;
+ if (i->next)
+ i->next->prev = i->prev;
+ dmnsn_delete_list_iterator(i);
+ --list->length;
+}
+
+/* Push obj to the end of the list */
+DMNSN_INLINE void
+dmnsn_list_push(dmnsn_list *list, const void *obj)
+{
+ dmnsn_list_iterator *i = dmnsn_new_list_iterator(obj, list->obj_size);
+ if (!list->first) {
+ list->first = i;
+ } else {
+ i->prev = list->last;
+ i->prev->next = i;
+ }
+ list->last = i;
+ ++list->length;
+}
+
+/* Pop obj from the end of the list */
+DMNSN_INLINE void
+dmnsn_list_pop(dmnsn_list *list, void *obj)
+{
+ if (!list->last) {
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "List is empty.");
+ }
+ dmnsn_list_get(list->last, obj);
+ dmnsn_list_remove(list, list->last);
+}
+
+#endif /* DIMENSION_LIST_H */
diff --git a/libdimension/list.c b/libdimension/list.c
new file mode 100644
index 0000000..0303513
--- /dev/null
+++ b/libdimension/list.c
@@ -0,0 +1,45 @@
+/*************************************************************************
+ * Copyright (C) 2010 Tavian Barnes <tavianator@gmail.com> *
+ * *
+ * This file is part of The Dimension Library. *
+ * *
+ * The Dimension Library is free software; you can redistribute it and/ *
+ * or modify it under the terms of the GNU Lesser General Public License *
+ * as published by the Free Software Foundation; either version 3 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * The Dimension Library is distributed in the hope that it will be *
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty *
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+#include "dimension.h"
+
+dmnsn_list *
+dmnsn_list_from_array(const dmnsn_array *array)
+{
+ dmnsn_list *list = dmnsn_new_list(array->obj_size);
+
+ size_t i;
+ for (i = 0; i < dmnsn_array_size(array); ++i) {
+ dmnsn_list_push(list, dmnsn_array_at(array, i));
+ }
+
+ return list;
+}
+
+void
+dmnsn_delete_list(dmnsn_list *list)
+{
+ if (list) {
+ while (list->first) {
+ dmnsn_list_remove(list, list->first);
+ }
+ free(list);
+ }
+}