Fix run length encoding of marked image, bump to version 0.8
[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 #else
101         printf("%s: failed to allocate memory\n", __func__);
102 #endif
103         return NULL;
104 }
105
106 /* free darray */
107 void darrayDestroy(darray_t *array)
108 {
109         darray_t **array_p;
110
111 #ifdef DEBUG_ARRAY
112         printf("darray: Destroying\n");
113         darrayInfo(array);
114 #endif
115         if (!array)
116                 return;
117         if (array->inuse != 0x08154711) {
118                 printf("darray: double free\n");
119                 darrayInfo(array);
120                 abort();
121         }
122
123         array_p = &array_start;
124         while (*array_p != array)
125                 array_p = &(*array_p)->next;
126         *array_p = array->next;
127 #ifdef DEBUG_ARRAY
128         arraycount--;
129         arraysize -= darrayGetSize(array);
130         CHECK_SIZE
131 #endif
132         array->inuse = 0x00000000;
133         free(array->dimension);
134         free(array->data);
135         free(array);
136 }
137
138 /* move array content to destination array. the source array is freed */
139 void darrayMove(darray_t *src, darray_t *dst)
140 {
141         darray_t **array_p, *temp;
142
143 #ifdef DEBUG_ARRAY
144         printf("darray: Moving\n");
145         darrayInfo(src);
146 #endif
147         if (!src || !dst)
148                 abort();
149         if (src->inuse != 0x08154711) {
150                 printf("darray: cannot move from already freed array\n");
151                 darrayInfo(src);
152                 abort();
153         }
154         if (dst->inuse != 0x08154711) {
155                 printf("darray: cannot move to already freed array\n");
156                 darrayInfo(dst);
157                 abort();
158         }
159         array_p = &array_start;
160         while (*array_p != src)
161                 array_p = &(*array_p)->next;
162         *array_p = src->next;
163         free(dst->dimension);
164         free(dst->data);
165         temp = dst->next; /* preserve dst->next */
166         memcpy(dst, src, sizeof(darray_t));
167         dst->next = temp; /* restore dst->next */
168 #ifdef DEBUG_ARRAY
169         arraycount--;
170         arraysize -= darrayGetSize(src);
171         CHECK_SIZE
172 #endif
173         src->inuse = 0x00000000;
174         free(src);
175 }
176
177 darray_t *darrayClone(darray_t *array)
178 {
179         darray_t *new;
180
181 #ifdef DEBUG_ARRAY
182         printf("darray: Cloning\n");
183         darrayInfo(array);
184 #endif
185         if (!array)
186                 return NULL;
187         if (array->inuse != 0x08154711) {
188                 printf("darray: cannot clone already freed array\n");
189                 darrayInfo(array);
190                 abort();
191         }
192         new = _darrayCreate(array->ndimensions, array->dimension, array->file, array->line);
193         if (!new)
194                 return NULL;
195         memcpy(new->data, array->data, darrayGetSize(array));
196
197         return new;
198 }
199
200 /* get info about darray */
201 void darrayInfo(const darray_t *array)
202 {
203         if (!array) {
204                 printf(" darray is NULL\n");
205                 return;
206         }
207         if (array->inuse != 0x08154711)
208                 printf(" darray was freed before\n");
209         printf(" darray was allocated in file %s, line %d\n", array->file, array->line);
210         int i;
211
212         for (i = 0; i < array->ndimensions; i++)
213                 printf("  Dimension %d: %d\n", i+1, array->dimension[i]);
214 }
215
216 void darrayDone(void)
217 {
218         darray_t *array = array_start;
219
220         while (array) {
221                 printf("darray: Leaking array!\n");
222                 darrayInfo(array);
223                 array = array->next;
224         }
225 #ifdef DEBUG_ARRAY
226         printf("darray: maximum memory usage was %lu Mbytes\n", arraysizemax/1024/1024);
227         arraysizemax = 0;
228
229 #endif
230 }
231
232 void darrayCheckList(void)
233 {
234         darray_t *array = array_start;
235
236         while (array) {
237                 if (array->inuse != 0x08154711) {
238                         printf("array's list is corrupt. this is the corrupt entry:\n");
239                         darrayInfo(array);
240                         exit(-1);
241                 }
242                 array = array->next;
243         }
244 }
245
246 #ifdef DARRAY_CHECK
247 void darrayCheckPr(const darray_t *array, const double *ptr, int num)
248 {
249         if (ptr < array->data) {
250                 printf("darrayCheckPr FALED: pointer access before array data\n");
251                 abort();
252         }
253         if (((unsigned char *)(array->data) + array->size) < ((unsigned char *)ptr + num*sizeof(double))) {
254                 printf("darrayCheckPr FALED: pointer access past array data\n");
255                 abort();
256         }
257 }
258 #endif
259