File Coverage

io.c
Criterion Covered Total %
statement 32 80 40.0
branch 9 34 26.4
condition n/a
subroutine n/a
pod n/a
total 41 114 35.9


line stmt bran cond sub pod time code
1             #include "imager.h"
2             #include "imageri.h"
3             #include
4             #ifndef _MSC_VER
5             #include
6             #endif
7              
8              
9             /* FIXME: make allocation dynamic */
10              
11              
12             #ifdef IMAGER_DEBUG_MALLOC
13              
14             #define MAXMAL 102400
15             #define MAXDESC 65
16              
17             #define UNDRRNVAL 10
18             #define OVERRNVAL 10
19              
20             #define PADBYTE 0xaa
21              
22              
23             static int malloc_need_init = 1;
24              
25             typedef struct {
26             void* ptr;
27             size_t size;
28             const char *file;
29             int line;
30             } malloc_entry;
31              
32             malloc_entry malloc_pointers[MAXMAL];
33              
34              
35              
36              
37             /* Utility functions */
38              
39              
40             static
41             void
42             malloc_init(void) {
43             int i;
44             for(i=0; i
45             malloc_need_init = 0;
46             atexit(malloc_state);
47             }
48              
49              
50             static
51             int
52             find_ptr(void *p) {
53             int i;
54             for(i=0;i
55             if (malloc_pointers[i].ptr == p)
56             return i;
57             return -1;
58             }
59              
60              
61             /* Takes a pointer to real start of array,
62             * sets the entries in the table, returns
63             * the offset corrected pointer */
64              
65             static
66             void *
67             set_entry(int i, char *buf, size_t size, char *file, int line) {
68             memset( buf, PADBYTE, UNDRRNVAL );
69             memset( &buf[UNDRRNVAL+size], PADBYTE, OVERRNVAL );
70             buf += UNDRRNVAL;
71             malloc_pointers[i].ptr = buf;
72             malloc_pointers[i].size = size;
73             malloc_pointers[i].file = file;
74             malloc_pointers[i].line = line;
75             return buf;
76             }
77              
78             void
79             malloc_state(void) {
80             int i;
81             size_t total = 0;
82              
83             i_clear_error();
84             mm_log((0,"malloc_state()\n"));
85             bndcheck_all();
86             for(i=0; i
87             mm_log((0,"%d: %lu (%p) : %s (%d)\n", i, (unsigned long)malloc_pointers[i].size, malloc_pointers[i].ptr, malloc_pointers[i].file, malloc_pointers[i].line));
88             total += malloc_pointers[i].size;
89             }
90             if (total == 0) mm_log((0,"No memory currently used!\n"))
91             else mm_log((0,"total: %lu\n", (unsigned long)total));
92             }
93              
94              
95              
96             void*
97             mymalloc_file_line(size_t size, char* file, int line) {
98             char *buf;
99             int i;
100             if (malloc_need_init) malloc_init();
101            
102             /* bndcheck_all(); Uncomment for LOTS OF THRASHING */
103            
104             if ( (i = find_ptr(NULL)) < 0 ) {
105             mm_log((0,"more than %d segments allocated at %s (%d)\n", MAXMAL, file, line));
106             exit(3);
107             }
108              
109             if ( (buf = malloc(size+UNDRRNVAL+OVERRNVAL)) == NULL ) {
110             mm_log((1,"Unable to allocate %ld for %s (%i)\n", (long)size, file, line));
111             exit(3);
112             }
113            
114             buf = set_entry(i, buf, size, file, line);
115             mm_log((1,"mymalloc_file_line: slot <%d> %ld bytes allocated at %p for %s (%d)\n", i, (long)size, buf, file, line));
116             return buf;
117             }
118              
119             void *
120             (mymalloc)(size_t size) {
121             return mymalloc_file_line(size, "unknown", 0);
122             }
123              
124             void*
125             myrealloc_file_line(void *ptr, size_t newsize, char* file, int line) {
126             char *buf;
127             int i;
128              
129             if (malloc_need_init) malloc_init();
130             /* bndcheck_all(); ACTIVATE FOR LOTS OF THRASHING */
131            
132             if (!ptr) {
133             mm_log((1, "realloc called with ptr = NULL, sending request to malloc\n"));
134             return mymalloc_file_line(newsize, file, line);
135             }
136            
137             if (!newsize) {
138             mm_log((1, "newsize = 0, sending request to free\n"));
139             myfree_file_line(ptr, file, line);
140             return NULL;
141             }
142              
143             if ( (i = find_ptr(ptr)) == -1) {
144             mm_log((0, "Unable to find %p in realloc for %s (%i)\n", ptr, file, line));
145             exit(3);
146             }
147            
148             if ( (buf = realloc(((char *)ptr)-UNDRRNVAL, UNDRRNVAL+OVERRNVAL+newsize)) == NULL ) {
149             mm_log((1,"Unable to reallocate %ld bytes at %p for %s (%i)\n", (long)
150             newsize, ptr, file, line));
151             exit(3);
152             }
153            
154             buf = set_entry(i, buf, newsize, file, line);
155             mm_log((1,"realloc_file_line: slot <%d> %ld bytes allocated at %p for %s (%d)\n", i, (long)newsize, buf, file, line));
156             return buf;
157             }
158              
159             void *
160             (myrealloc)(void *ptr, size_t newsize) {
161             return myrealloc_file_line(ptr, newsize, "unknown", 0);
162             }
163              
164             static
165             void
166             bndcheck(int idx) {
167             int i;
168             size_t s = malloc_pointers[idx].size;
169             unsigned char *pp = malloc_pointers[idx].ptr;
170             if (!pp) {
171             mm_log((1, "bndcheck: No pointer in slot %d\n", idx));
172             return;
173             }
174            
175             for(i=0;i
176             if (pp[-(1+i)] != PADBYTE)
177             mm_log((1,"bndcheck: UNDERRUN OF %d bytes detected: slot = %d, point = %p, size = %ld\n", i+1, idx, pp, (long)s ));
178             }
179            
180             for(i=0;i
181             if (pp[s+i] != PADBYTE)
182             mm_log((1,"bndcheck: OVERRUN OF %d bytes detected: slot = %d, point = %p, size = %ld\n", i+1, idx, pp, (long)s ));
183             }
184             }
185              
186             void
187             bndcheck_all() {
188             int idx;
189             mm_log((1, "bndcheck_all()\n"));
190             for(idx=0; idx
191             if (malloc_pointers[idx].ptr)
192             bndcheck(idx);
193             }
194              
195             void
196             myfree_file_line(void *p, char *file, int line) {
197             char *pp = p;
198             int match = 0;
199             int i;
200              
201             if (p == NULL)
202             return;
203            
204             for(i=0; i
205             mm_log((1,"myfree_file_line: pointer %i (%s (%d)) freed at %s (%i)\n", i, malloc_pointers[i].file, malloc_pointers[i].line, file, line));
206             bndcheck(i);
207             malloc_pointers[i].ptr = NULL;
208             match++;
209             }
210              
211             mm_log((1, "myfree_file_line: freeing address %p (real %p)\n", pp, pp-UNDRRNVAL));
212            
213             if (match != 1) {
214             mm_log((1, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line));
215             fprintf(stderr, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line);
216             exit(255);
217             }
218            
219            
220             free(pp-UNDRRNVAL);
221             }
222              
223             void
224             (myfree)(void *block) {
225             myfree_file_line(block, "unknown", 0);
226             }
227              
228             #else
229              
230             void
231 3           malloc_state() {
232 3           }
233              
234             void*
235 28307           mymalloc(size_t size) {
236             void *buf;
237              
238 28307 50         if ( (buf = malloc(size)) == NULL ) {
239 0           mm_log((1, "mymalloc: unable to malloc %ld\n", (long)size));
240 0           fprintf(stderr,"Unable to malloc %ld.\n", (long)size); exit(3);
241             }
242 28307           mm_log((1, "mymalloc(size %ld) -> %p\n", (long)size, buf));
243 28307           return buf;
244             }
245              
246             void *
247 0           mymalloc_file_line(size_t size, char *file, int line) {
248 0           return mymalloc(size);
249             }
250              
251             void
252 28316           myfree(void *p) {
253 28316           mm_log((1, "myfree(p %p)\n", p));
254 28316           free(p);
255 28316           }
256              
257             void
258 0           myfree_file_line(void *p, char *file, int line) {
259 0           myfree(p);
260 0           }
261              
262             void *
263 10           myrealloc(void *block, size_t size) {
264             void *result;
265              
266 10           mm_log((1, "myrealloc(block %p, size %ld)\n", block, (long)size));
267 10 50         if ((result = realloc(block, size)) == NULL) {
268 0           mm_log((1, "myrealloc: out of memory\n"));
269 0           fprintf(stderr, "Out of memory.\n");
270 0           exit(3);
271             }
272 10           return result;
273             }
274              
275             void *
276 0           myrealloc_file_line(void *block, size_t newsize, char *file, int size) {
277 0           return myrealloc(block, newsize);
278             }
279              
280             #endif /* IMAGER_MALLOC_DEBUG */
281              
282              
283              
284              
285             /* memory pool implementation */
286              
287             void
288 5           i_mempool_init(i_mempool *mp) {
289 5           mp->alloc = 10;
290 5           mp->used = 0;
291 5           mp->p = mymalloc(sizeof(void*)*mp->alloc);
292 5           }
293              
294             void
295 0           i_mempool_extend(i_mempool *mp) {
296 0           mp->p = myrealloc(mp->p, mp->alloc * 2);
297 0           mp->alloc *=2;
298 0           }
299              
300             void *
301 10           i_mempool_alloc(i_mempool *mp, size_t size) {
302 10 50         if (mp->used == mp->alloc) i_mempool_extend(mp);
303 10           mp->p[mp->used] = mymalloc(size);
304 10           mp->used++;
305 10           return mp->p[mp->used-1];
306             }
307              
308              
309             void
310 5           i_mempool_destroy(i_mempool *mp) {
311             unsigned int i;
312 15 100         for(i=0; iused; i++) myfree(mp->p[i]);
313 5           myfree(mp->p);
314 5           }
315              
316              
317              
318             /* Should these really be here? */
319              
320             #undef min
321             #undef max
322              
323             i_img_dim
324 173919           i_minx(i_img_dim a, i_img_dim b) {
325 173919 100         if (a
326             }
327              
328             i_img_dim
329 35871           i_maxx(i_img_dim a, i_img_dim b) {
330 35871 100         if (a>b) return a; else return b;
331             }
332              
333              
334             struct utf8_size {
335             int mask, expect;
336             int size;
337             };
338              
339             struct utf8_size utf8_sizes[] =
340             {
341             { 0x80, 0x00, 1 },
342             { 0xE0, 0xC0, 2 },
343             { 0xF0, 0xE0, 3 },
344             { 0xF8, 0xF0, 4 },
345             };
346              
347             /*
348             =item i_utf8_advance(char **p, size_t *len)
349              
350             Retrieve a C character from the stream.
351              
352             Modifies *p and *len to indicate the consumed characters.
353              
354             This doesn't support the extended C encoding used by later
355             versions of Perl. Since this is typically used to implement text
356             output by font drivers, the strings supplied shouldn't have such out
357             of range characters.
358              
359             This doesn't check that the C character is using the shortest
360             possible representation.
361              
362             Returns ~0UL on failure.
363              
364             =cut
365             */
366              
367             unsigned long
368 0           i_utf8_advance(char const **p, size_t *len) {
369             unsigned char c;
370 0           int i, ci, clen = 0;
371             unsigned char codes[3];
372 0 0         if (*len == 0)
373 0           return ~0UL;
374 0           c = *(*p)++; --*len;
375              
376 0 0         for (i = 0; i < sizeof(utf8_sizes)/sizeof(*utf8_sizes); ++i) {
377 0 0         if ((c & utf8_sizes[i].mask) == utf8_sizes[i].expect) {
378 0           clen = utf8_sizes[i].size;
379 0           break;
380             }
381             }
382 0 0         if (clen == 0 || *len < clen-1) {
    0          
383 0           --*p; ++*len;
384 0           return ~0UL;
385             }
386              
387             /* check that each character is well formed */
388 0           i = 1;
389 0           ci = 0;
390 0 0         while (i < clen) {
391 0 0         if (((*p)[ci] & 0xC0) != 0x80) {
392 0           --*p; ++*len;
393 0           return ~0UL;
394             }
395 0           codes[ci] = (*p)[ci];
396 0           ++ci; ++i;
397             }
398 0           *p += clen-1; *len -= clen-1;
399 0 0         if (c & 0x80) {
400 0 0         if ((c & 0xE0) == 0xC0) {
401 0           return ((c & 0x1F) << 6) + (codes[0] & 0x3F);
402             }
403 0 0         else if ((c & 0xF0) == 0xE0) {
404 0           return ((c & 0x0F) << 12) | ((codes[0] & 0x3F) << 6) | (codes[1] & 0x3f);
405             }
406 0 0         else if ((c & 0xF8) == 0xF0) {
407 0           return ((c & 0x07) << 18) | ((codes[0] & 0x3F) << 12)
408 0           | ((codes[1] & 0x3F) << 6) | (codes[2] & 0x3F);
409             }
410             else {
411 0           *p -= clen; *len += clen;
412 0           return ~0UL;
413             }
414             }
415             else {
416 0           return c;
417             }
418             }
419