summaryrefslogtreecommitdiff
path: root/src/svgtiny_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/svgtiny_list.c')
-rw-r--r--src/svgtiny_list.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/svgtiny_list.c b/src/svgtiny_list.c
new file mode 100644
index 0000000..53cfb34
--- /dev/null
+++ b/src/svgtiny_list.c
@@ -0,0 +1,125 @@
+/*
+ * This file is part of Libsvgtiny
+ * Licensed under the MIT License,
+ * http://opensource.org/licenses/mit-license.php
+ * Copyright 2008 James Bursa <james@semichrome.net>
+ */
+
+/**
+ * A svgtiny_list is a managed array of objects. It grows in chunks to reduce
+ * calls to realloc(), but keeps wasted space low.
+ */
+
+#include <assert.h>
+#include "svgtiny.h"
+#include "svgtiny_internal.h"
+
+
+struct svgtiny_list {
+ unsigned int size; /* number of slots used */
+ unsigned int allocated; /* number of slots allocated (>= size) */
+ size_t item_size; /* size of each slot / bytes */
+ char *items; /* array of slots */
+};
+
+
+/**
+ * Create an empty svgtiny_list.
+ */
+
+struct svgtiny_list *svgtiny_list_create(size_t item_size)
+{
+ struct svgtiny_list *list = malloc(sizeof *list);
+ if (!list)
+ return 0;
+ list->size = 0;
+ list->allocated = 0;
+ list->item_size = item_size;
+ list->items = 0;
+ return list;
+}
+
+
+/**
+ * Return the number of objects in a list.
+ */
+
+unsigned int svgtiny_list_size(struct svgtiny_list *list)
+{
+ return list->size;
+}
+
+
+/**
+ * Set the number of objects in a list. If the size is increased, the new
+ * objects are not initialized in any way.
+ *
+ * The allocation size formula is taken from Python's list:
+ * http://svn.python.org/view/python/trunk/Objects/listobject.c?view=markup
+ *
+ * Objects may have moved after this call. Use svgtiny_list_get() to get new
+ * pointers.
+ */
+
+svgtiny_code svgtiny_list_resize(struct svgtiny_list *list,
+ unsigned int new_size)
+{
+ unsigned int new_allocated;
+ void *new_items;
+
+ if (new_size <= list->allocated) {
+ list->size = new_size;
+ return svgtiny_OK;
+ }
+
+ new_allocated = (new_size >> 3) + (new_size < 9 ? 3 : 6) + new_size;
+ if (new_size == 0)
+ new_allocated = 0;
+ new_items = realloc(list->items, new_allocated * list->item_size);
+ if (!new_items)
+ return svgtiny_OUT_OF_MEMORY;
+
+ list->size = new_size;
+ list->allocated = new_allocated;
+ list->items = new_items;
+
+ return svgtiny_OK;
+}
+
+
+/**
+ * Return a pointer to an object in a list.
+ */
+
+void *svgtiny_list_get(struct svgtiny_list *list,
+ unsigned int i)
+{
+ assert(i < list->size);
+ return (void *) (list->items + i * list->item_size);
+}
+
+
+/**
+ * Add space for one object to a list and return a pointer to it.
+ */
+
+void *svgtiny_list_push(struct svgtiny_list *list)
+{
+ svgtiny_code code;
+ code = svgtiny_list_resize(list, list->size + 1);
+ if (code != svgtiny_OK)
+ return 0;
+ return svgtiny_list_get(list, list->size - 1);
+}
+
+
+/**
+ * Free an entire list.
+ */
+
+void svgtiny_list_free(struct svgtiny_list *list)
+{
+ free(list->items);
+ free(list);
+}
+