1 /*
2 LICENSE INFORMATION:
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public
5 License as published by the Free Software Foundation; either
6 version 2 of the License, or (at your option) any later version.
7 
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 General Public License for more details.
12 
13 You should have received a copy of the GNU General Public
14 License along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 Copyright (c) 2002 Bruno T. C. de Oliveira
17 
18 INFORMA��ES DE LICEN�A:
19 Este programa � um software de livre distribui��o; voc� pode
20 redistribu�-lo e/ou modific�-lo sob os termos da GNU General
21 Public License, conforme publicado pela Free Software Foundation,
22 pela vers�o 2 da licen�a ou qualquer vers�o posterior.
23 
24 Este programa � distribu�do na esperan�a de que ele ser� �til
25 aos seus usu�rios, por�m, SEM QUAISQUER GARANTIAS; sem sequer
26 a garantia impl�cita de COMERCIABILIDADE ou DE ADEQUA��O A
27 QUALQUER FINALIDADE ESPEC�FICA. Consulte a GNU General Public
28 License para obter mais detalhes (uma c�pia acompanha este
29 programa, armazenada no arquivo COPYING).
30 */
31 
32 
33 #include "darray.h"
34 #include "util.h"
35 #include <stdio.h>
36 #include <stdlib.h>
37 
38 #define DEFAULT_CAPACITY 20
39 
40 #define CAPACITY_AHEAD 20  /* when a value is assigned to an out of bounds
41                               item, this is how far beyond it the capacity
42                               grows. */
43 
44 struct DArray_ {
45    int len;
46    int cap;
47    void **items;
48    void (*value_destroyer)(void*);
49 };
50 
darray_create()51 DArray* darray_create() {
52    return darray_create_ex(DEFAULT_CAPACITY, NULL);
53 }
54 
darray_create_ex(int cap,void (* vd)(void *))55 DArray* darray_create_ex(int cap, void (*vd)(void*)) {
56    DArray* da = zalloc(sizeof(DArray));
57 
58    da->len = 0;
59    da->cap = (cap > 0) ? cap : DEFAULT_CAPACITY;
60    da->items = zalloc(sizeof(void*) * da->cap);
61    da->value_destroyer = vd;
62 
63    return da;
64 }
65 
darray_destroy(DArray * da)66 void darray_destroy(DArray* da) {
67    int i;
68    if (!da) return;
69    if (da->value_destroyer) {
70       /* call value destroyer for each item */
71       for (i = 0; i < da->len; i++)
72          if (da->items[i]) (*da->value_destroyer)(da->items[i]);
73    }
74 
75    /* free up the items array then the darray itself */
76    sfree(da->items);
77    sfree(da);
78 }
79 
darray_len(DArray * da)80 int darray_len(DArray* da) {
81    /* this one is really complicated */
82    return da->len;
83 }
84 
darray_get(DArray * da,int i)85 void* darray_get(DArray* da, int i) {
86    return (i >= 0 && i < da->len) ? da->items[i] : NULL;
87 }
88 
darray_set(DArray * da,int i,const void * v)89 void darray_set(DArray* da, int i, const void *v) {
90    if (i < 0) {
91       fprintf(stderr, "*** FATAL ERROR ***\n"
92                       "Attempt to darray_set with negative index %d\n", i);
93       abort();
94    }
95    else if (i >= da->len) {
96       da->cap = i + CAPACITY_AHEAD;
97       da->items = srealloc(da->items, sizeof(void*) * da->cap);
98 
99       /* grow array while assignung NULLs to all newly included items */
100       while (i >= da->len)  da->items[da->len++] = NULL;
101    }
102    else {
103       /* call value destroyer if there was anything there */
104       if (da->items[i] && da->value_destroyer)
105          (*da->value_destroyer)(da->items[i]);
106    }
107 
108    da->items[i] = (void*) v;
109 }
110 
darray_snatch(DArray * da,int i)111 void* darray_snatch(DArray *da, int i) {
112    void *v;
113    if (i >= 0 && i < da->len) {
114       v = da->items[i];
115       da->items[i] = NULL;
116       return v;
117    }
118    else return NULL;
119 }
120 
darray_append(DArray * da,const void * v)121 void darray_append(DArray *da, const void *v) {
122    darray_set(da, da->len, v);
123 }
124 
darray_remove(DArray * da,int i)125 void darray_remove(DArray *da, int i) {
126    if (i < 0 || i >= da->len) return;
127    if (da->items[i] && da->value_destroyer)
128       (*da->value_destroyer)(da->items[i]);
129 
130    while (i < da->len - 1) {
131       da->items[i] = da->items[i+1];
132       i++;
133    }
134 
135    da->len--;
136 }
137 
138