]> gitweb.michael.orlitzky.com - libsvgtiny.git/blob - svgtiny_list.c
53cfb346a249b1e3a9ab8d7211523beb5a5f60e1
[libsvgtiny.git] / svgtiny_list.c
1 /*
2 * This file is part of Libsvgtiny
3 * Licensed under the MIT License,
4 * http://opensource.org/licenses/mit-license.php
5 * Copyright 2008 James Bursa <james@semichrome.net>
6 */
7
8 /**
9 * A svgtiny_list is a managed array of objects. It grows in chunks to reduce
10 * calls to realloc(), but keeps wasted space low.
11 */
12
13 #include <assert.h>
14 #include "svgtiny.h"
15 #include "svgtiny_internal.h"
16
17
18 struct svgtiny_list {
19 unsigned int size; /* number of slots used */
20 unsigned int allocated; /* number of slots allocated (>= size) */
21 size_t item_size; /* size of each slot / bytes */
22 char *items; /* array of slots */
23 };
24
25
26 /**
27 * Create an empty svgtiny_list.
28 */
29
30 struct svgtiny_list *svgtiny_list_create(size_t item_size)
31 {
32 struct svgtiny_list *list = malloc(sizeof *list);
33 if (!list)
34 return 0;
35 list->size = 0;
36 list->allocated = 0;
37 list->item_size = item_size;
38 list->items = 0;
39 return list;
40 }
41
42
43 /**
44 * Return the number of objects in a list.
45 */
46
47 unsigned int svgtiny_list_size(struct svgtiny_list *list)
48 {
49 return list->size;
50 }
51
52
53 /**
54 * Set the number of objects in a list. If the size is increased, the new
55 * objects are not initialized in any way.
56 *
57 * The allocation size formula is taken from Python's list:
58 * http://svn.python.org/view/python/trunk/Objects/listobject.c?view=markup
59 *
60 * Objects may have moved after this call. Use svgtiny_list_get() to get new
61 * pointers.
62 */
63
64 svgtiny_code svgtiny_list_resize(struct svgtiny_list *list,
65 unsigned int new_size)
66 {
67 unsigned int new_allocated;
68 void *new_items;
69
70 if (new_size <= list->allocated) {
71 list->size = new_size;
72 return svgtiny_OK;
73 }
74
75 new_allocated = (new_size >> 3) + (new_size < 9 ? 3 : 6) + new_size;
76 if (new_size == 0)
77 new_allocated = 0;
78 new_items = realloc(list->items, new_allocated * list->item_size);
79 if (!new_items)
80 return svgtiny_OUT_OF_MEMORY;
81
82 list->size = new_size;
83 list->allocated = new_allocated;
84 list->items = new_items;
85
86 return svgtiny_OK;
87 }
88
89
90 /**
91 * Return a pointer to an object in a list.
92 */
93
94 void *svgtiny_list_get(struct svgtiny_list *list,
95 unsigned int i)
96 {
97 assert(i < list->size);
98 return (void *) (list->items + i * list->item_size);
99 }
100
101
102 /**
103 * Add space for one object to a list and return a pointer to it.
104 */
105
106 void *svgtiny_list_push(struct svgtiny_list *list)
107 {
108 svgtiny_code code;
109 code = svgtiny_list_resize(list, list->size + 1);
110 if (code != svgtiny_OK)
111 return 0;
112 return svgtiny_list_get(list, list->size - 1);
113 }
114
115
116 /**
117 * Free an entire list.
118 */
119
120 void svgtiny_list_free(struct svgtiny_list *list)
121 {
122 free(list->items);
123 free(list);
124 }
125