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