1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*-
2 ======================================================================
4 CREATOR: Damon Chaplin 07 March 2001
6 $Id: icalarray.c,v 1.7 2008-01-15 23:17:40 dothebart Exp $
9 (C) COPYRIGHT 2001, Ximian, Inc.
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of either:
14 The LGPL as published by the Free Software Foundation, version
15 2.1, available at: http://www.fsf.org/copyleft/lesser.html
19 The Mozilla Public License Version 1.0. You may obtain a copy of
20 the License at http://www.mozilla.org/MPL/
23 ======================================================================*/
27 * @brief An array of arbitrarily-sized elements which grows
28 * dynamically as elements are added.
38 #include "icalarray.h"
39 #include "icalerror.h"
41 static void icalarray_expand (icalarray *array,
44 /** @brief Constructor
48 icalarray_new (int element_size,
53 array = (icalarray*) malloc (sizeof (icalarray));
55 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
59 array->element_size = element_size;
60 array->increment_size = increment_size;
61 array->num_elements = 0;
62 array->space_allocated = 0;
69 icalarray_alloc_chunk(icalarray *array)
71 void *chunk = malloc(array->element_size * array->increment_size);
73 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
77 icalarray *icalarray_copy (icalarray *originalarray)
79 icalarray *array = icalarray_new(originalarray->element_size, originalarray->increment_size);
80 int chunks = originalarray->space_allocated / originalarray->increment_size;
86 array->num_elements = originalarray->num_elements;
87 array->space_allocated = originalarray->space_allocated;
89 array->chunks = malloc(chunks * sizeof (void *));
91 for (chunk = 0; chunk < chunks; chunk++) {
92 array->chunks[chunk] = icalarray_alloc_chunk(array);
93 if (array->chunks[chunk])
94 memcpy(array->chunks[chunk], originalarray->chunks[chunk],
95 array->increment_size * array->element_size);
99 icalerror_set_errno(ICAL_ALLOCATION_ERROR);
106 /** @brief Destructor
110 icalarray_free (icalarray *array)
113 int chunks = array->space_allocated / array->increment_size;
115 for (chunk = 0; chunk < chunks; chunk++)
116 free(array->chunks[chunk]);
117 free (array->chunks);
126 icalarray_append (icalarray *array,
130 if (array->num_elements >= array->space_allocated)
131 icalarray_expand (array, 1);
133 pos = array->num_elements++;
134 memcpy (icalarray_element_at(array, pos), element, array->element_size);
139 icalarray_element_at (icalarray *array,
142 int chunk = position / array->increment_size;
143 int offset = position % array->increment_size;
145 assert (position >= 0);
146 assert ((unsigned int)position < array->num_elements);
147 return (char *)(array->chunks[chunk]) + (offset * array->element_size);
152 icalarray_remove_element_at (icalarray *array,
156 int elements_to_move;
158 assert (position >= 0);
159 assert ((unsigned int)position < array->num_elements);
161 while (position < array->num_elements - 1) {
162 memmove(icalarray_element_at(array, position),
163 icalarray_element_at(array, position + 1),
164 array->element_size);
168 array->num_elements--;
173 icalarray_sort (icalarray *array,
174 int (*compare) (const void *,
177 if (array->num_elements == 0) {
181 if (array->num_elements <= array->increment_size) {
182 qsort(array->chunks[0], array->num_elements, array->element_size, compare);
185 void *tmp = malloc (array->num_elements * array->element_size);
188 for (pos = 0; pos < array->num_elements; pos++)
189 memcpy((char *) tmp + array->element_size * pos, icalarray_element_at(array, pos), array->element_size);
191 qsort (tmp, array->num_elements, array->element_size, compare);
193 for (pos = 0; pos < array->num_elements; pos++)
194 memcpy(icalarray_element_at(array, pos), (char *) tmp + array->element_size * pos, array->element_size);
201 icalarray_expand (icalarray *array,
204 int num_chunks = array->space_allocated / array->increment_size;
209 num_new_chunks = (space_needed + array->increment_size - 1) / array->increment_size;
213 new_chunks = malloc ((num_chunks + num_new_chunks) * sizeof (void *));
216 memcpy(new_chunks, array->chunks, num_chunks * sizeof (void *));
217 for (c = 0; c < num_new_chunks; c++)
218 new_chunks[c + num_chunks] = icalarray_alloc_chunk(array);
220 free (array->chunks);
221 array->chunks = new_chunks;
222 array->space_allocated = array->space_allocated + num_new_chunks * array->increment_size;
224 icalerror_set_errno(ICAL_ALLOCATION_ERROR);