1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*-
2 ======================================================================
3 FILE: icalarray.c
4 CREATOR: Damon Chaplin 07 March 2001
5
6 $Id: icalarray.c,v 1.7 2008-01-15 23:17:40 dothebart Exp $
7 $Locker: $
8
9 (C) COPYRIGHT 2001, Ximian, Inc.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of either:
13
14 The LGPL as published by the Free Software Foundation, version
15 2.1, available at: http://www.fsf.org/copyleft/lesser.html
16
17 Or:
18
19 The Mozilla Public License Version 1.0. You may obtain a copy of
20 the License at http://www.mozilla.org/MPL/
21
22
23 ======================================================================*/
24
25 /** @file icalarray.c
26 *
27 * @brief An array of arbitrarily-sized elements which grows
28 * dynamically as elements are added.
29 */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "icalarray.h"
39 #include "icalerror.h"
40
41
42 static void icalarray_expand (icalarray *array,
43 int space_needed);
44
45 /** @brief Constructor
46 */
47
48 icalarray*
icalarray_new(int element_size,int increment_size)49 icalarray_new (int element_size,
50 int increment_size)
51 {
52 icalarray *array;
53
54 array = (icalarray*) malloc (sizeof (icalarray));
55 if (!array) {
56 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
57 return NULL;
58 }
59
60 array->element_size = element_size;
61 array->increment_size = increment_size;
62 array->num_elements = 0;
63 array->space_allocated = 0;
64 array->data = NULL;
65
66 return array;
67 }
68
69
icalarray_copy(icalarray * originalarray)70 icalarray *icalarray_copy (icalarray *originalarray)
71 {
72 icalarray *array = icalarray_new(originalarray->element_size, originalarray->increment_size);
73
74 if (!array)
75 return NULL;
76
77 array->num_elements = originalarray->num_elements;
78 array->space_allocated = originalarray->space_allocated;
79
80 array->data = malloc(array->space_allocated * array->element_size);
81
82 if (array->data) {
83 memcpy(array->data, originalarray->data,
84 array->element_size*array->space_allocated);
85 } else {
86 icalerror_set_errno(ICAL_ALLOCATION_ERROR);
87 }
88
89 return array;
90 }
91
92
93 /** @brief Destructor
94 */
95
96 void
icalarray_free(icalarray * array)97 icalarray_free (icalarray *array)
98 {
99 if (array->data) {
100 free (array->data);
101 array->data = 0;
102 }
103 free (array);
104 array = 0;
105 }
106
107
108 void
icalarray_append(icalarray * array,const void * element)109 icalarray_append (icalarray *array,
110 const void *element)
111 {
112 if (array->num_elements >= array->space_allocated)
113 icalarray_expand (array, 1);
114
115 memcpy ((char *)(array->data) + ( array->num_elements * array->element_size ), element,
116 array->element_size);
117 array->num_elements++;
118 }
119
120
121 void*
icalarray_element_at(icalarray * array,int position)122 icalarray_element_at (icalarray *array,
123 int position)
124 {
125 assert (position >= 0);
126 assert ((unsigned int)position < array->num_elements);
127
128 return (char *)(array->data) + (position * array->element_size);
129 }
130
131
132 void
icalarray_remove_element_at(icalarray * array,int position)133 icalarray_remove_element_at (icalarray *array,
134 int position)
135 {
136 void *dest;
137 int elements_to_move;
138
139 assert (position >= 0);
140 assert ((unsigned int)position < array->num_elements);
141
142 dest = (char *)array->data + (position * array->element_size);
143 elements_to_move = array->num_elements - position - 1;
144
145 if (elements_to_move > 0)
146 memmove (dest, (char *)dest + array->element_size,
147 elements_to_move * array->element_size);
148
149 array->num_elements--;
150 }
151
152
153 void
icalarray_sort(icalarray * array,int (* compare)(const void *,const void *))154 icalarray_sort (icalarray *array,
155 int (*compare) (const void *,
156 const void *))
157 {
158 qsort (array->data, array->num_elements, array->element_size, compare);
159 }
160
161
162 static void
icalarray_expand(icalarray * array,int space_needed)163 icalarray_expand (icalarray *array,
164 int space_needed)
165 {
166 int new_space_allocated;
167 void *new_data;
168
169 new_space_allocated = array->space_allocated + array->increment_size;
170
171 if ((unsigned int)space_needed > array->increment_size)
172 new_space_allocated += space_needed;
173
174 /*
175 new_data = realloc (array->data,
176 new_space_allocated * array->element_size);
177 */
178 new_data = malloc(new_space_allocated * array->element_size);
179
180 if (new_data) {
181 memcpy(new_data,array->data,array->element_size*array->space_allocated);
182 if (array->data) {
183 free(array->data);
184 array->data = 0;
185 }
186 array->data = new_data;
187 array->space_allocated = new_space_allocated;
188 } else {
189 icalerror_set_errno(ICAL_ALLOCATION_ERROR);
190 }
191 }
192
193
194