source: vis_dev/cusp-1.1/src/array/array.c @ 104

Last change on this file since 104 was 12, checked in by cecile, 13 years ago

cusp added

File size: 5.9 KB
Line 
1/*
2 * $Id: array.c,v 1.2 2009-04-13 11:07:36 hhkim 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
70
71/* append the elements of array2 to the end of array1 */
72int
73array_append(array_t *array1, array_t *array2)
74{
75    char *pos;
76
77    if (array1->index >= 0) array_abort(array1,4);
78    if (array1->obj_size != array2->obj_size) {
79        array_abort(array1,2);
80        /* NOTREACHED */
81    }
82
83    /* make sure array1 has enough room */
84    if (array1->n_size < array1->num + array2->num) {
85        if (array_resize(array1, array1->num + array2->num) == ARRAY_OUT_OF_MEM) {
86            return ARRAY_OUT_OF_MEM;
87        }
88    }
89    pos = array1->space + array1->num * array1->obj_size;
90    (void) memcpy(pos, array2->space, array2->num * array2->obj_size);
91    array1->num += array2->num;
92
93    return 1;
94}
95
96
97/* join array1 and array2, returning a new array */
98array_t *
99array_join(array_t *array1, array_t *array2)
100{
101    array_t *array;
102    char *pos;
103
104    if (array1->obj_size != array2->obj_size) {
105        array_abort(array1,3);
106        fail("array: join not defined for arrays of different sizes\n");
107        /* NOTREACHED */
108    }
109    array = ALLOC(array_t, 1);
110    if (array == NIL(array_t)) {
111        return NIL(array_t);
112    }
113    array->num = array1->num + array2->num;
114    array->n_size = array->num;
115    array->obj_size = array1->obj_size;
116    array->index = -array->obj_size;
117    array->space = ALLOC(char, array->n_size * array->obj_size);
118    if (array->space == NIL(char)) {
119        FREE(array);
120        return NIL(array_t);
121    }
122    (void) memcpy(array->space, array1->space, array1->num * array1->obj_size);
123    pos = array->space + array1->num * array1->obj_size;
124    (void) memcpy(pos, array2->space, array2->num * array2->obj_size);
125    return array;
126}
127
128char *
129array_do_data(array_t *array)
130{
131    char *data;
132
133    data = ALLOC(char, array->num * array->obj_size);
134    if (data == NIL(char)) {
135        return NIL(char);
136    }
137    (void) memcpy(data, array->space, array->num * array->obj_size);
138    return data;
139}
140
141
142int                     /* would like to be void, except for macro's */
143array_resize(array_t *array, int new_size)
144{
145    int old_size;
146    char *pos, *newspace;
147
148    /* Note that this is not an exported function, and does not check if
149       the array is locked since that is already done by the caller. */
150    old_size = array->n_size;
151    array->n_size = MAX(array->n_size * 2, new_size);
152    newspace = REALLOC(char, array->space, array->n_size * array->obj_size);
153    if (newspace == NIL(char)) {
154        array->n_size = old_size;
155        return ARRAY_OUT_OF_MEM;
156    } else {
157        array->space = newspace;
158    }
159    pos = array->space + old_size * array->obj_size;
160    (void) memset(pos, 0, (array->n_size - old_size)*array->obj_size);
161    return 1;
162}
163
164void
165array_sort(array_t *array, int (*compare)(const void *, const void *))
166{
167    qsort((void *)array->space, array->num, array->obj_size, compare);
168}
169
170
171void
172array_uniq(array_t *array, int (*compare)(char **, char **), void (*free_func)(char *))
173{
174    int i, last;
175    char *dest, *obj1, *obj2;
176
177    dest = array->space;
178    obj1 = array->space;
179    obj2 = array->space + array->obj_size;
180    last = array->num;
181
182    for(i = 1; i < last; i++) {
183        if ((*compare)((char **) obj1, (char **) obj2) != 0) {
184            if (dest != obj1) {
185                (void) memcpy(dest, obj1, array->obj_size);
186            }
187            dest += array->obj_size;
188        } else {
189            if (free_func != 0) (*free_func)(obj1);
190            array->num--;
191        }
192        obj1 += array->obj_size;
193        obj2 += array->obj_size;
194    }
195    if (dest != obj1) {
196        (void) memcpy(dest, obj1, array->obj_size);
197    }
198}
199
200int                     /* would like to be void, except for macro's */
201array_abort(array_t *a, int i)
202{
203    fputs("array: ",stderr);
204
205    switch (i) {
206
207      case 0:           /* index error on insert */
208        fprintf(stderr,"insert of %d\n",a->index);
209        break;
210
211      case 1:           /* index error on fetch */
212        fprintf(stderr,"fetch index %u not in [0,%d]\n",
213                array_global_index,a->num-1);
214        break;
215
216      case 2:           /* append with different element sizes */
217        fprintf(stderr,"append undefined for arrays of different sizes\n");
218        break;
219
220      case 3:           /* join with different element sizes */
221        fprintf(stderr,"join not defined for arrays of different sizes\n");
222        break;
223
224      case 4:           /* size error or locked error */
225        if (a->index >= 0) {
226            /* Since array_insert is a macro, it is not allowed to nest a
227               call to any routine which might move the array space through
228               a realloc or free inside an array_insert call. */
229            fprintf(stderr,"nested insert, append, remove, or free operations\n");
230        } else {
231            fprintf(stderr,"object size mismatch\n");
232        }
233        break;
234    case 5: /* attempt to remove last item from empty array */
235      fprintf(stderr, "attempt to remove from empty array");
236      break;
237    default:
238        fputs("unknown error\n", stderr);
239        break;
240    }
241
242    fail("array package error");
243    return 0;  /* never reached */
244}
Note: See TracBrowser for help on using the repository browser.