1 /*************************************************************************
2 * xarray.c: Mutable (dynamically growable) array
3 *************************************************************************
4 * Copyright (C) 2004 Commonwealth Scientific and Industrial Research
5 * Organisation (CSIRO) Australia
6 * Copyright (C) 2004 the VideoLAN team
10 * Authors: Andre Pang <Andre.Pang@csiro.au>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 ************************************************************************/
35 #include <vlc_memory.h>
37 /* local prototypes */
38 XArray * xarray_New (unsigned int);
41 #define XARRAY_ASSERT_NOT_NULL(xarray) \
43 if (xarray == NULL) return XARRAY_ENULLPOINTER; \
46 #define XARRAY_BOUNDS_CHECK(xarray, index) \
48 if (xarray->last_valid_element != -1 && \
49 (int) index > xarray->last_valid_element) \
50 return XARRAY_EINDEXTOOLARGE; \
53 #define XARRAY_GROW_ARRAY(xarray) \
55 xarray->array = realloc_or_free (xarray->array, xarray->size * 2); \
56 if (xarray->array == NULL) return XARRAY_ENOMEM; \
59 XArray * xarray_New (unsigned int initial_size_hint)
61 XArray *new_xarray = NULL;
63 unsigned int initial_size;
65 new_xarray = (XArray *) malloc (sizeof(XArray));
66 if (new_xarray == NULL) return NULL;
68 if (initial_size_hint == 0)
69 initial_size = XARRAY_DEFAULT_SIZE;
71 initial_size = initial_size_hint;
73 inner_array = calloc (initial_size, sizeof(void *));
75 new_xarray->last_valid_element = -1;
76 new_xarray->size = initial_size;
77 new_xarray->last_error = 0;
79 if (inner_array == NULL)
85 new_xarray->array = inner_array;
90 int xarray_ObjectAtIndex (XArray *xarray, unsigned int index,
93 XARRAY_ASSERT_NOT_NULL (xarray);
94 XARRAY_BOUNDS_CHECK (xarray, index);
96 *out_object = xarray->array[index];
98 return XARRAY_SUCCESS;
101 int xarray_AddObject (XArray *xarray, void *object)
103 XARRAY_ASSERT_NOT_NULL (xarray);
105 ++xarray->last_valid_element;
106 if (xarray->last_valid_element >= (int) xarray->size)
108 XARRAY_GROW_ARRAY (xarray);
111 xarray->array[xarray->last_valid_element] = object;
113 return XARRAY_SUCCESS;
116 int xarray_InsertObject (XArray *xarray, void *object,
117 unsigned int at_index)
119 XARRAY_ASSERT_NOT_NULL (xarray);
120 ++xarray->last_valid_element;
121 XARRAY_BOUNDS_CHECK (xarray, at_index);
122 if (xarray->last_valid_element >= (int) xarray->size)
124 XARRAY_GROW_ARRAY (xarray);
127 /* Shift everything from a[i] onward one pointer forward */
129 if ((int) at_index < xarray->last_valid_element)
131 (void) memmove (&xarray->array[at_index + 1],
132 &xarray->array[at_index],
133 (xarray->last_valid_element - at_index) *
137 xarray->array[at_index] = object;
139 return XARRAY_SUCCESS;
142 int xarray_RemoveLastObject (XArray *xarray)
144 XARRAY_ASSERT_NOT_NULL (xarray);
146 if (xarray->last_valid_element == -1)
147 return XARRAY_EEMPTYARRAY;
149 xarray->array[xarray->last_valid_element] = NULL;
150 --xarray->last_valid_element;
152 return XARRAY_SUCCESS;
155 int xarray_RemoveObject (XArray *xarray, unsigned int at_index)
157 XARRAY_ASSERT_NOT_NULL (xarray);
158 XARRAY_BOUNDS_CHECK (xarray, at_index);
160 /* Shift everything from a[i] onward one pointer backward */
162 if ((int) at_index < xarray->last_valid_element)
164 (void) memmove (&xarray->array[at_index],
165 &xarray->array[at_index + 1],
166 (xarray->last_valid_element - at_index) *
170 xarray->array[xarray->last_valid_element] = NULL;
171 --xarray->last_valid_element;
173 return XARRAY_SUCCESS;
176 int xarray_RemoveObjects (XArray *xarray, unsigned int at_index,
181 XARRAY_ASSERT_NOT_NULL (xarray);
182 XARRAY_BOUNDS_CHECK (xarray, at_index);
184 if (count == 0) return XARRAY_SUCCESS;
186 if ((int) at_index + (count - 1) > xarray->last_valid_element)
187 return XARRAY_ECOUNTOUTOFBOUNDS;
189 for (i = 0; i < count; i++)
191 int e = xarray_RemoveObject (xarray, at_index);
192 if (e != XARRAY_SUCCESS) return e;
195 return XARRAY_SUCCESS;
198 int xarray_RemoveObjectsAfter (XArray *xarray, unsigned int index)
200 XARRAY_ASSERT_NOT_NULL (xarray);
201 XARRAY_BOUNDS_CHECK (xarray, index);
205 while ((int) index <= xarray->last_valid_element)
207 int e = xarray_RemoveObject (xarray, index);
208 if (e != XARRAY_SUCCESS) return e;
211 return XARRAY_SUCCESS;
214 int xarray_ReplaceObject (XArray *xarray, unsigned int index,
217 XARRAY_ASSERT_NOT_NULL (xarray);
218 XARRAY_BOUNDS_CHECK (xarray, index);
220 xarray->array[index] = new_object;
222 return XARRAY_SUCCESS;
225 int xarray_Count (XArray *xarray, unsigned int *out_count)
227 XARRAY_ASSERT_NOT_NULL (xarray);
229 *out_count = xarray->last_valid_element + 1;
231 return XARRAY_SUCCESS;
235 #undef XARRAY_ASSERT_NOT_NULL
236 #undef XARRAY_BOUNDS_CHECK
237 #undef XARRAY_GROW_ARRAY