00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include "util.h"
00009 #include "array.h"
00010
00011 #define INIT_SIZE 3
00012
00013 int unsigned array_global_index;
00014 int array_global_insert;
00015
00016 array_t *
00017 array_do_alloc(int size, int number)
00018 {
00019 array_t *array;
00020
00021 array = ALLOC(array_t, 1);
00022 if (array == NIL(array_t)) {
00023 return NIL(array_t);
00024 }
00025 array->num = 0;
00026 array->n_size = MAX(number, INIT_SIZE);
00027 array->obj_size = size;
00028 array->index = -size;
00029 array->space = ALLOC(char, array->n_size * array->obj_size);
00030 if (array->space == NIL(char)) {
00031 return NIL(array_t);
00032 }
00033 (void) memset(array->space, 0, array->n_size * array->obj_size);
00034 return array;
00035 }
00036
00037
00038 void
00039 array_free(array_t *array)
00040 {
00041 if (array == NIL(array_t)) return;
00042 if (array->index >= 0) array_abort(array,4);
00043 FREE(array->space);
00044 FREE(array);
00045 }
00046
00047
00048 array_t *
00049 array_dup(array_t *old)
00050 {
00051 array_t *newa;
00052
00053 newa = ALLOC(array_t, 1);
00054 if (newa == NIL(array_t)) {
00055 return NIL(array_t);
00056 }
00057 newa->num = old->num;
00058 newa->n_size = old->num;
00059 newa->obj_size = old->obj_size;
00060 newa->index = -newa->obj_size;
00061 newa->space = ALLOC(char, newa->n_size * newa->obj_size);
00062 if (newa->space == NIL(char)) {
00063 FREE(newa);
00064 return NIL(array_t);
00065 }
00066 (void) memcpy(newa->space, old->space, old->num * old->obj_size);
00067 return newa;
00068 }
00069
00070
00071
00072 int
00073 array_append(array_t *array1, array_t *array2)
00074 {
00075 char *pos;
00076
00077 if (array1->index >= 0) array_abort(array1,4);
00078 if (array1->obj_size != array2->obj_size) {
00079 array_abort(array1,2);
00080
00081 }
00082
00083
00084 if (array1->n_size < array1->num + array2->num) {
00085 if (array_resize(array1, array1->num + array2->num) == ARRAY_OUT_OF_MEM) {
00086 return ARRAY_OUT_OF_MEM;
00087 }
00088 }
00089 pos = array1->space + array1->num * array1->obj_size;
00090 (void) memcpy(pos, array2->space, array2->num * array2->obj_size);
00091 array1->num += array2->num;
00092
00093 return 1;
00094 }
00095
00096
00097
00098 array_t *
00099 array_join(array_t *array1, array_t *array2)
00100 {
00101 array_t *array;
00102 char *pos;
00103
00104 if (array1->obj_size != array2->obj_size) {
00105 array_abort(array1,3);
00106 fail("array: join not defined for arrays of different sizes\n");
00107
00108 }
00109 array = ALLOC(array_t, 1);
00110 if (array == NIL(array_t)) {
00111 return NIL(array_t);
00112 }
00113 array->num = array1->num + array2->num;
00114 array->n_size = array->num;
00115 array->obj_size = array1->obj_size;
00116 array->index = -array->obj_size;
00117 array->space = ALLOC(char, array->n_size * array->obj_size);
00118 if (array->space == NIL(char)) {
00119 FREE(array);
00120 return NIL(array_t);
00121 }
00122 (void) memcpy(array->space, array1->space, array1->num * array1->obj_size);
00123 pos = array->space + array1->num * array1->obj_size;
00124 (void) memcpy(pos, array2->space, array2->num * array2->obj_size);
00125 return array;
00126 }
00127
00128 char *
00129 array_do_data(array_t *array)
00130 {
00131 char *data;
00132
00133 data = ALLOC(char, array->num * array->obj_size);
00134 if (data == NIL(char)) {
00135 return NIL(char);
00136 }
00137 (void) memcpy(data, array->space, array->num * array->obj_size);
00138 return data;
00139 }
00140
00141
00142 int
00143 array_resize(array_t *array, int new_size)
00144 {
00145 int old_size;
00146 char *pos, *newspace;
00147
00148
00149
00150 old_size = array->n_size;
00151 array->n_size = MAX(array->n_size * 2, new_size);
00152 newspace = REALLOC(char, array->space, array->n_size * array->obj_size);
00153 if (newspace == NIL(char)) {
00154 array->n_size = old_size;
00155 return ARRAY_OUT_OF_MEM;
00156 } else {
00157 array->space = newspace;
00158 }
00159 pos = array->space + old_size * array->obj_size;
00160 (void) memset(pos, 0, (array->n_size - old_size)*array->obj_size);
00161 return 1;
00162 }
00163
00164 void
00165 array_sort(array_t *array, int (*compare)(const void *, const void *))
00166 {
00167 qsort((void *)array->space, array->num, array->obj_size, compare);
00168 }
00169
00170
00171 void
00172 array_uniq(array_t *array, int (*compare)(char **, char **), void (*free_func)(char *))
00173 {
00174 int i, last;
00175 char *dest, *obj1, *obj2;
00176
00177 dest = array->space;
00178 obj1 = array->space;
00179 obj2 = array->space + array->obj_size;
00180 last = array->num;
00181
00182 for(i = 1; i < last; i++) {
00183 if ((*compare)((char **) obj1, (char **) obj2) != 0) {
00184 if (dest != obj1) {
00185 (void) memcpy(dest, obj1, array->obj_size);
00186 }
00187 dest += array->obj_size;
00188 } else {
00189 if (free_func != 0) (*free_func)(obj1);
00190 array->num--;
00191 }
00192 obj1 += array->obj_size;
00193 obj2 += array->obj_size;
00194 }
00195 if (dest != obj1) {
00196 (void) memcpy(dest, obj1, array->obj_size);
00197 }
00198 }
00199
00200 int
00201 array_abort(array_t *a, int i)
00202 {
00203 fputs("array: ",stderr);
00204
00205 switch (i) {
00206
00207 case 0:
00208 fprintf(stderr,"insert of %d\n",a->index);
00209 break;
00210
00211 case 1:
00212 fprintf(stderr,"fetch index %d not in [0,%d]\n",
00213 array_global_index,a->num-1);
00214 break;
00215
00216 case 2:
00217 fprintf(stderr,"append undefined for arrays of different sizes\n");
00218 break;
00219
00220 case 3:
00221 fprintf(stderr,"join not defined for arrays of different sizes\n");
00222 break;
00223
00224 case 4:
00225 if (a->index >= 0) {
00226
00227
00228
00229 fprintf(stderr,"nested insert, append, remove, or free operations\n");
00230 } else {
00231 fprintf(stderr,"object size mismatch\n");
00232 }
00233 break;
00234 case 5:
00235 fprintf(stderr, "attempt to remove from empty array");
00236 break;
00237 default:
00238 fputs("unknown error\n", stderr);
00239 break;
00240 }
00241
00242 fail("array package error");
00243 return 0;
00244 }