1 /*
2 * XPilot NG, a multiplayer space war game.
3 *
4 * Copyright (C) 2005 Kristian S�derblom <kps@users.sourceforge.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "xpcommon.h"
22
23 #define ARRAYLIST_INITIAL_NUM_ELEMENTS 16
24 #define ARRAYLIST_ELEMENT_ALIGNMENT sizeof(double)
25
Arraylist_clear(arraylist_t * alp)26 void Arraylist_clear(arraylist_t *alp)
27 {
28 alp->num_elements = 0;
29 }
30
Arraylist_get(arraylist_t * alp,int ind)31 void *Arraylist_get(arraylist_t *alp, int ind)
32 {
33 if (ind < 0 || ind >= alp->num_elements)
34 return NULL;
35 return Arraylist_get_element_pointer(alp, ind);
36 }
37
Arraylist_add(arraylist_t * alp,void * element)38 int Arraylist_add(arraylist_t *alp, void *element)
39 {
40 size_t n;
41 void *p;
42
43 if (alp->num_elements < alp->max_elements) {
44 p = Arraylist_get_element_pointer(alp, alp->num_elements);
45 memcpy(p, element, alp->element_size);
46 return alp->num_elements++;
47 }
48
49 if (alp->max_elements >= ARRAYLIST_INITIAL_NUM_ELEMENTS)
50 n = alp->max_elements * 2;
51 else
52 n = ARRAYLIST_INITIAL_NUM_ELEMENTS;
53 p = realloc(alp->elements, n * alp->element_padded_size);
54 if (p == NULL)
55 return -1;
56
57 alp->elements = p;
58 alp->max_elements = n;
59
60 return Arraylist_add(alp, element);
61 }
62
Arraylist_fast_remove(arraylist_t * alp,int ind)63 void Arraylist_fast_remove(arraylist_t *alp, int ind)
64 {
65 void *p, *last_p;
66
67 /* get pointer to the element to remove */
68 p = Arraylist_get(alp, ind);
69 if (!p)
70 /* warn or return error ? */
71 return;
72
73 /* last element? */
74 if (ind == alp->num_elements - 1) {
75 /* no need to copy anything */
76 alp->num_elements--;
77 return;
78 }
79
80 /* copy last element to index 'ind' */
81 last_p = Arraylist_get(alp, alp->num_elements - 1);
82 assert(last_p != NULL);
83 memcpy(p, last_p, alp->element_padded_size);
84 alp->num_elements--;
85 }
86
Arraylist_alloc(size_t element_size)87 arraylist_t *Arraylist_alloc(size_t element_size)
88 {
89 arraylist_t *alp = XCALLOC(arraylist_t, 1);
90 size_t padded_size = element_size;
91
92 if (((element_size % ARRAYLIST_ELEMENT_ALIGNMENT) != 0)
93 && element_size != 1
94 && element_size != 2
95 && element_size != 4) {
96 padded_size /= ARRAYLIST_ELEMENT_ALIGNMENT;
97 padded_size *= ARRAYLIST_ELEMENT_ALIGNMENT;
98 padded_size += ARRAYLIST_ELEMENT_ALIGNMENT;
99
100 /*warn("Arraylist_create: Increasing element size from %d to %d.",
101 element_size, padded_size);*/
102 }
103
104 if (alp == NULL)
105 goto failed;
106
107 alp->elements = calloc(ARRAYLIST_INITIAL_NUM_ELEMENTS, padded_size);
108 if (alp->elements == NULL)
109 goto failed;
110
111 alp->element_size = element_size;
112 alp->element_padded_size = padded_size;
113 alp->num_elements = 0;
114 alp->max_elements = ARRAYLIST_INITIAL_NUM_ELEMENTS;
115
116 return alp;
117
118 failed:
119 return NULL;
120 }
121
Arraylist_free(arraylist_t * alp)122 void Arraylist_free(arraylist_t *alp)
123 {
124 assert(alp != NULL);
125 assert(alp->elements != NULL);
126 XFREE(alp->elements);
127 XFREE(alp);
128 }
129