source: vis_dev/glu-2.3/src/array/array.c @ 64

Last change on this file since 64 was 15, checked in by cecile, 13 years ago

Vis main file for expermeriments

File size: 6.6 KB
Line 
1/*
2 * $Id: array.c,v 1.6 2002/08/27 06:26:29 fabio Exp $
3 *
4 */
5/* LINTLIBRARY */
6
7#include <stdio.h>
8#include "util.h"
9#include "array.h"
10
11#define INIT_SIZE       3
12
13int unsigned array_global_index;
14int array_global_insert;
15
16array_t *
17array_do_alloc(int size, int number)
18{
19    array_t *array;
20
21    array = ALLOC(array_t, 1);
22    if (array == NIL(array_t)) {
23        return NIL(array_t);
24    }
25    array->num = 0;
26    array->n_size = MAX(number, INIT_SIZE);
27    array->obj_size = size;
28    array->index = -size;
29    array->space = ALLOC(char, array->n_size * array->obj_size);
30    if (array->space == NIL(char)) {
31        return NIL(array_t);
32    }
33    (void) memset(array->space, 0, array->n_size * array->obj_size);
34    return array;
35}
36
37
38void
39array_free(array_t *array)
40{
41    if (array == NIL(array_t)) return;
42    if (array->index >= 0) array_abort(array,4);
43    FREE(array->space);
44    FREE(array);
45}
46
47
48array_t *
49array_dup(array_t *old)
50{
51    array_t *newa;
52
53    newa = ALLOC(array_t, 1);
54    if (newa == NIL(array_t)) {
55        return NIL(array_t);
56    }
57    newa->num = old->num;
58    newa->n_size = old->num;
59    newa->obj_size = old->obj_size;
60    newa->index = -newa->obj_size;
61    newa->space = ALLOC(char, newa->n_size * newa->obj_size);
62    if (newa->space == NIL(char)) {
63        FREE(newa);
64        return NIL(array_t);
65    }
66    (void) memcpy(newa->space, old->space, old->num * old->obj_size);
67    return newa;
68}
69
70array_t *
71array_partial_dup(array_t *old, int i)
72{
73    array_t *newa;
74
75    newa = ALLOC(array_t, 1);
76    if (newa == NIL(array_t)) {
77        return NIL(array_t);
78    }
79    newa->num = old->num - 1;
80    newa->n_size = old->num - 1;
81    newa->obj_size = old->obj_size;
82    newa->index = -newa->obj_size;
83    newa->space = ALLOC(char, newa->n_size * newa->obj_size);
84    if (newa->space == NIL(char)) {
85        FREE(newa);
86        return NIL(array_t);
87    }
88    if (i > 0)
89      (void) memcpy(newa->space, old->space, i * old->obj_size);
90    if (i < old->num - 1)
91      (void) memcpy(newa->space + ((i) * old->obj_size), 
92                    old->space + ((i+1) * old->obj_size), (old->num - (i + 1)) * old->obj_size);
93    return newa;
94}
95
96
97/* append the elements of array2 to the end of array1 */
98int
99array_append(array_t *array1, array_t *array2)
100{
101    char *pos;
102
103    if (array1->index >= 0) array_abort(array1,4);
104    if (array1->obj_size != array2->obj_size) {
105        array_abort(array1,2);
106        /* NOTREACHED */
107    }
108
109    /* make sure array1 has enough room */
110    if (array1->n_size < array1->num + array2->num) {
111        if (array_resize(array1, array1->num + array2->num) == ARRAY_OUT_OF_MEM) {
112            return ARRAY_OUT_OF_MEM;
113        }
114    }
115    pos = array1->space + array1->num * array1->obj_size;
116    (void) memcpy(pos, array2->space, array2->num * array2->obj_size);
117    array1->num += array2->num;
118
119    return 1;
120}
121
122
123/* join array1 and array2, returning a new array */
124array_t *
125array_join(array_t *array1, array_t *array2)
126{
127    array_t *array;
128    char *pos;
129
130    if (array1->obj_size != array2->obj_size) {
131        array_abort(array1,3);
132        fail("array: join not defined for arrays of different sizes\n");
133        /* NOTREACHED */
134    }
135    array = ALLOC(array_t, 1);
136    if (array == NIL(array_t)) {
137        return NIL(array_t);
138    }
139    array->num = array1->num + array2->num;
140    array->n_size = array->num;
141    array->obj_size = array1->obj_size;
142    array->index = -array->obj_size;
143    array->space = ALLOC(char, array->n_size * array->obj_size);
144    if (array->space == NIL(char)) {
145        FREE(array);
146        return NIL(array_t);
147    }
148    (void) memcpy(array->space, array1->space, array1->num * array1->obj_size);
149    pos = array->space + array1->num * array1->obj_size;
150    (void) memcpy(pos, array2->space, array2->num * array2->obj_size);
151    return array;
152}
153
154char *
155array_do_data(array_t *array)
156{
157    char *data;
158
159    data = ALLOC(char, array->num * array->obj_size);
160    if (data == NIL(char)) {
161        return NIL(char);
162    }
163    (void) memcpy(data, array->space, array->num * array->obj_size);
164    return data;
165}
166
167
168int                     /* would like to be void, except for macro's */
169array_resize(array_t *array, int new_size)
170{
171    int old_size;
172    char *pos, *newspace;
173
174    /* Note that this is not an exported function, and does not check if
175       the array is locked since that is already done by the caller. */
176    old_size = array->n_size;
177    array->n_size = MAX(array->n_size * 2, new_size);
178    newspace = REALLOC(char, array->space, array->n_size * array->obj_size);
179    if (newspace == NIL(char)) {
180        array->n_size = old_size;
181        return ARRAY_OUT_OF_MEM;
182    } else {
183        array->space = newspace;
184    }
185    pos = array->space + old_size * array->obj_size;
186    (void) memset(pos, 0, (array->n_size - old_size)*array->obj_size);
187    return 1;
188}
189
190void
191array_sort(array_t *array, int (*compare)(const void *, const void *))
192{
193    qsort((void *)array->space, array->num, array->obj_size, compare);
194}
195
196
197void
198array_uniq(array_t *array, int (*compare)(char **, char **), void (*free_func)(char *))
199{
200    int i, last;
201    char *dest, *obj1, *obj2;
202
203    dest = array->space;
204    obj1 = array->space;
205    obj2 = array->space + array->obj_size;
206    last = array->num;
207
208    for(i = 1; i < last; i++) {
209        if ((*compare)((char **) obj1, (char **) obj2) != 0) {
210            if (dest != obj1) {
211                (void) memcpy(dest, obj1, array->obj_size);
212            }
213            dest += array->obj_size;
214        } else {
215            if (free_func != 0) (*free_func)(obj1);
216            array->num--;
217        }
218        obj1 += array->obj_size;
219        obj2 += array->obj_size;
220    }
221    if (dest != obj1) {
222        (void) memcpy(dest, obj1, array->obj_size);
223    }
224}
225
226int                     /* would like to be void, except for macro's */
227array_abort(array_t *a, int i)
228{
229    fputs("array: ",stderr);
230
231    switch (i) {
232
233      case 0:           /* index error on insert */
234        fprintf(stderr,"insert of %d\n",a->index);
235        break;
236
237      case 1:           /* index error on fetch */
238        fprintf(stderr,"fetch index %d not in [0,%d]\n",
239                array_global_index,a->num-1);
240        break;
241
242      case 2:           /* append with different element sizes */
243        fprintf(stderr,"append undefined for arrays of different sizes\n");
244        break;
245
246      case 3:           /* join with different element sizes */
247        fprintf(stderr,"join not defined for arrays of different sizes\n");
248        break;
249
250      case 4:           /* size error or locked error */
251        if (a->index >= 0) {
252            /* Since array_insert is a macro, it is not allowed to nest a
253               call to any routine which might move the array space through
254               a realloc or free inside an array_insert call. */
255            fprintf(stderr,"nested insert, append, remove, or free operations\n");
256        } else {
257            fprintf(stderr,"object size mismatch\n");
258        }
259        break;
260    case 5: /* attempt to remove last item from empty array */
261      fprintf(stderr, "attempt to remove from empty array");
262      break;
263    default:
264        fputs("unknown error\n", stderr);
265        break;
266    }
267
268    fail("array package error");
269    return 0;  /* never reached */
270}
Note: See TracBrowser for help on using the repository browser.