Show "unchanged color" as checkered pattern
[colorize.git] / lib / darray.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <math.h>
6 #include <unistd.h>
7 #include "darray.h"
8
9 /* file format:
10  * <dimensions>
11  * <dimension 1>
12  * <dimension 2>
13  * ...
14  * <dimension n>
15  * <binary data of array, if any>
16  */
17
18 //#define DEBUG_ARRAY
19
20 #ifdef DEBUG_ARRAY
21 int arraycount = 0;
22 unsigned long arraysize = 0, arraysizemax = 0;
23 #define CHECK_SIZE \
24 { \
25         printf("darray: %d arrays (%lu bytes/%lu Mbytes) exist\n", arraycount, arraysize, arraysize/1024/1024); \
26         if (arraycount < 0) { \
27                 printf("darray error: more arrays freed than allocated\n"); \
28                 abort(); \
29         } \
30         if (arraysize < 0) { \
31                 printf("darray error: more array data freed than allocated\n"); \
32                 abort(); \
33         } \
34 }
35 #endif
36
37 static darray_t *array_start = NULL;
38
39 unsigned long darrayGetSize(const darray_t *array)
40 {
41         unsigned long size = sizeof(double), i;
42
43         for (i = 0; i < array->ndimensions; i++)
44                 size *= array->dimension[i];
45
46         return size;
47 }
48
49 /* create darray */
50 darray_t *_darrayCreate(int ndimensions, int *dimension, const char *file, int line)
51 {
52         darray_t *array;
53         unsigned long size;
54
55         array = (darray_t *)malloc(sizeof(darray_t));
56         if (!array)
57                 goto error;
58         array->file = file;
59         array->line = line;
60         array->ndimensions = ndimensions;
61         array->inuse = 0x00000000;
62         if (ndimensions) {
63                 array->dimension = (int *)malloc(ndimensions * sizeof(int));
64                 if (!array->dimension) {
65                         free(array);
66                         goto error;
67                 }
68                 memcpy(array->dimension, dimension, ndimensions * sizeof(int));
69         }
70         size = darrayGetSize(array);
71         if (size) {
72                 array->data = (double *)malloc(size);
73                 if (!array->data) {
74                         free(array->dimension);
75                         free(array);
76                         goto error;
77                 }
78                 memset(array->data, 0, size);
79         } else
80                 array->data = NULL;
81         array->size = size;
82         array->next = array_start;
83         array_start = array;
84         array->inuse = 0x08154711;
85 #ifdef DEBUG_ARRAY
86         printf("darray: Creating\n");
87         darrayInfo(array);
88         arraycount++;
89         arraysize += darrayGetSize(array);
90         if (arraysize > arraysizemax)
91                 arraysizemax = arraysize;
92         CHECK_SIZE
93 #endif
94         return array;
95
96 error:
97 #ifdef DEBUG_ARRAY
98         printf("darray: No memory to allocate (used %lu Mbytes)\n", arraysize/1024/1024);
99         sleep(2);
100 #endif
101         return NULL;
102 }
103
104 /* free darray */
105 void darrayDestroy(darray_t *array)
106 {
107         darray_t **array_p;
108
109 #ifdef DEBUG_ARRAY
110         printf("darray: Destroying\n");
111         darrayInfo(array);
112 #endif
113         if (!array)
114                 return;
115         if (array->inuse != 0x08154711) {
116                 printf("darray: double free\n");
117                 darrayInfo(array);
118                 abort();
119         }
120
121         array_p = &array_start;
122         while (*array_p != array)
123                 array_p = &(*array_p)->next;
124         *array_p = array->next;
125 #ifdef DEBUG_ARRAY
126         arraycount--;
127         arraysize -= darrayGetSize(array);
128         CHECK_SIZE
129 #endif
130         array->inuse = 0x00000000;
131         free(array->dimension);
132         free(array->data);
133         free(array);
134 }
135
136 /* move array content to destination array. the source array is freed */
137 void darrayMove(darray_t *src, darray_t *dst)
138 {
139         darray_t **array_p, *temp;
140
141 #ifdef DEBUG_ARRAY
142         printf("darray: Moving\n");
143         darrayInfo(src);
144 #endif
145         if (!src || !dst)
146                 abort();
147         if (src->inuse != 0x08154711) {
148                 printf("darray: cannot move from already freed array\n");
149                 darrayInfo(src);
150                 abort();
151         }
152         if (dst->inuse != 0x08154711) {
153                 printf("darray: cannot move to already freed array\n");
154                 darrayInfo(dst);
155                 abort();
156         }
157         array_p = &array_start;
158         while (*array_p != src)
159                 array_p = &(*array_p)->next;
160         *array_p = src->next;
161         free(dst->dimension);
162         free(dst->data);
163         temp = dst->next; /* preserve dst->next */
164         memcpy(dst, src, sizeof(darray_t));
165         dst->next = temp; /* restore dst->next */
166 #ifdef DEBUG_ARRAY
167         arraycount--;
168         arraysize -= darrayGetSize(src);
169         CHECK_SIZE
170 #endif
171         src->inuse = 0x00000000;
172         free(src);
173 }
174
175 darray_t *darrayClone(darray_t *array)
176 {
177         darray_t *new;
178
179 #ifdef DEBUG_ARRAY
180         printf("darray: Cloning\n");
181         darrayInfo(array);
182 #endif
183         if (!array)
184                 return NULL;
185         if (array->inuse != 0x08154711) {
186                 printf("darray: cannot clone already freed array\n");
187                 darrayInfo(array);
188                 abort();
189         }
190         new = _darrayCreate(array->ndimensions, array->dimension, array->file, array->line);
191         if (!new)
192                 return NULL;
193         memcpy(new->data, array->data, darrayGetSize(array));
194
195         return new;
196 }
197
198 /* get info about darray */
199 void darrayInfo(const darray_t *array)
200 {
201         if (!array) {
202                 printf(" darray is NULL\n");
203                 return;
204         }
205         if (array->inuse != 0x08154711)
206                 printf(" darray was freed before\n");
207         printf(" darray was allocated in file %s, line %d\n", array->file, array->line);
208         int i;
209
210         for (i = 0; i < array->ndimensions; i++)
211                 printf("  Dimension %d: %d\n", i+1, array->dimension[i]);
212 }
213
214 void darrayDone(void)
215 {
216         darray_t *array = array_start;
217
218         while (array) {
219                 printf("darray: Leaking array!\n");
220                 darrayInfo(array);
221                 array = array->next;
222         }
223 #ifdef DEBUG_ARRAY
224         printf("darray: maximum memory usage was %lu Mbytes\n", arraysizemax/1024/1024);
225         arraysizemax = 0;
226
227 #endif
228 }
229
230 void darrayCheckList(void)
231 {
232         darray_t *array = array_start;
233
234         while (array) {
235                 if (array->inuse != 0x08154711) {
236                         printf("array's list is corrupt. this is the corrupt entry:\n");
237                         darrayInfo(array);
238                         exit(-1);
239                 }
240                 array = array->next;
241         }
242 }
243
244 #ifdef DARRAY_CHECK
245 void darrayCheckPr(const darray_t *array, const double *ptr, int num)
246 {
247         if (ptr < array->data) {
248                 printf("darrayCheckPr FALED: pointer access before array data\n");
249                 abort();
250         }
251         if (((unsigned char *)(array->data) + array->size) < ((unsigned char *)ptr + num*sizeof(double))) {
252                 printf("darrayCheckPr FALED: pointer access past array data\n");
253                 abort();
254         }
255 }
256 #endif
257