]> git.imager.perl.org - imager.git/blame - io.c
tga.c should now support reading/writing all variants of targa files. XS needs
[imager.git] / io.c
CommitLineData
02d1d628
AMH
1#include "io.h"
2#include <stdlib.h>
3#ifndef _MSC_VER
4#include <unistd.h>
5#endif
6
7
8/* FIXME: make allocation dynamic */
9
10
11#ifdef IMAGER_DEBUG_MALLOC
12
2ff8ed30 13#define MAXMAL 102400
02d1d628
AMH
14#define MAXDESC 65
15
a743c0a6
AMH
16#define UNDRRNVAL 10
17#define OVERRNVAL 10
02d1d628
AMH
18
19#define PADBYTE 0xaa
20
21
22static int malloc_need_init = 1;
23
24typedef struct {
fe6163bf 25 void* ptr;
02d1d628 26 size_t size;
fe6163bf 27 char comm[MAXDESC];
02d1d628
AMH
28} malloc_entry;
29
30malloc_entry malloc_pointers[MAXMAL];
31
fe6163bf
AMH
32
33
34
35/* Utility functions */
36
37
38static
39void
40malloc_init() {
41 int i;
42 for(i=0; i<MAXMAL; i++) malloc_pointers[i].ptr = NULL;
43 malloc_need_init = 0;
44 atexit(malloc_state);
45}
46
47
48static
49int
50find_ptr(void *p) {
51 int i;
52 for(i=0;i<MAXMAL;i++)
53 if (malloc_pointers[i].ptr == p)
54 return i;
55 return -1;
56}
57
58
59/* Takes a pointer to real start of array,
60 * sets the entries in the table, returns
61 * the offset corrected pointer */
62
63static
64void *
65set_entry(int i, char *buf, size_t size, char *file, int line) {
66 memset( buf, PADBYTE, UNDRRNVAL );
67 memset( &buf[UNDRRNVAL+size], PADBYTE, OVERRNVAL );
68 buf += UNDRRNVAL;
69 malloc_pointers[i].ptr = buf;
70 malloc_pointers[i].size = size;
71 sprintf(malloc_pointers[i].comm,"%s (%d)", file, line);
72 return buf;
73}
74
75
02d1d628
AMH
76
77
78void
79malloc_state() {
fe6163bf
AMH
80 int i, total = 0;
81
02d1d628
AMH
82 mm_log((0,"malloc_state()\n"));
83 bndcheck_all();
fe6163bf
AMH
84 for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr != NULL) {
85 mm_log((0,"%d: %d (0x%x) : %s\n", i, malloc_pointers[i].size, malloc_pointers[i].ptr, malloc_pointers[i].comm));
86 total += malloc_pointers[i].size;
02d1d628 87 }
fe6163bf
AMH
88 if (total == 0) mm_log((0,"No memory currently used!\n"))
89 else mm_log((0,"total: %d\n",total));
02d1d628
AMH
90}
91
92
fe6163bf 93
02d1d628 94void*
fe6163bf 95mymalloc_file_line(size_t size, char* file, int line) {
02d1d628
AMH
96 char *buf;
97 int i;
fe6163bf
AMH
98 if (malloc_need_init) malloc_init();
99
100 /* bndcheck_all(); Uncomment for LOTS OF THRASHING */
101
102 if ( (i = find_ptr(NULL)) < 0 ) {
103 mm_log((0,"more than %d segments allocated at %s (%d)\n", MAXMAL, file, line));
104 exit(3);
02d1d628
AMH
105 }
106
fe6163bf
AMH
107 if ( (buf = malloc(size+UNDRRNVAL+OVERRNVAL)) == NULL ) {
108 mm_log((1,"Unable to allocate %i for %s (%i)\n", size, file, line));
109 exit(3);
02d1d628
AMH
110 }
111
fe6163bf
AMH
112 buf = set_entry(i, buf, size, file, line);
113 mm_log((1,"mymalloc_file_line: slot <%d> %d bytes allocated at %p for %s (%d)\n", i, size, buf, file, line));
114 return buf;
02d1d628
AMH
115}
116
117
118
119
02d1d628 120
fe6163bf
AMH
121
122
02d1d628 123void*
fe6163bf
AMH
124myrealloc_file_line(void *ptr, size_t newsize, char* file, int line) {
125 char *buf;
02d1d628 126 int i;
fe6163bf
AMH
127
128 if (malloc_need_init) malloc_init();
129 /* bndcheck_all(); ACTIVATE FOR LOTS OF THRASHING */
130
131 if (!ptr) {
132 mm_log((1, "realloc called with ptr = NULL, sending request to malloc\n"));
133 return mymalloc_file_line(newsize, file, line);
02d1d628
AMH
134 }
135
fe6163bf
AMH
136 if (!newsize) {
137 mm_log((1, "newsize = 0, sending request to free\n"));
138 myfree_file_line(ptr, file, line);
139 return NULL;
140 }
02d1d628 141
fe6163bf
AMH
142 if ( (i = find_ptr(ptr)) == -1) {
143 mm_log((0, "Unable to find %p in realloc for %s (%i)\n", ptr, file, line));
144 exit(3);
145 }
146
76ff75b8 147 if ( (buf = realloc(ptr-UNDRRNVAL, UNDRRNVAL+OVERRNVAL+newsize)) == NULL ) {
fe6163bf
AMH
148 mm_log((1,"Unable to reallocate %i bytes at %p for %s (%i)\n", newsize, ptr, file, line));
149 exit(3);
02d1d628 150 }
fe6163bf
AMH
151
152 buf = set_entry(i, buf, newsize, file, line);
153 mm_log((1,"realloc_file_line: slot <%d> %d bytes allocated at %p for %s (%d)\n", i, newsize, buf, file, line));
154 return buf;
02d1d628 155}
fe6163bf
AMH
156
157
158
02d1d628
AMH
159
160static
161void
162bndcheck(int idx) {
163 int i;
164 size_t s = malloc_pointers[idx].size;
fe6163bf 165 unsigned char *pp = malloc_pointers[idx].ptr;
02d1d628
AMH
166 if (!pp) {
167 mm_log((1, "bndcheck: No pointer in slot %d\n", idx));
168 return;
169 }
170
171 for(i=0;i<UNDRRNVAL;i++)
fe6163bf
AMH
172 if (pp[-(1+i)] != PADBYTE)
173 mm_log((1,"bndcheck: UNDERRUN OF %d bytes detected: slot = %d, point = %p, size = %d\n", i+1, idx, pp, s ));
02d1d628 174
fe6163bf 175 for(i=0;i<OVERRNVAL;i++)
02d1d628
AMH
176 if (pp[s+i] != PADBYTE)
177 mm_log((1,"bndcheck: OVERRUN OF %d bytes detected: slot = %d, point = %p, size = %d\n", i+1, idx, pp, s ));
178}
179
180void
181bndcheck_all() {
182 int idx;
183 mm_log((1, "bndcheck_all()\n"));
76ff75b8 184 for(idx=0; idx<MAXMAL; idx++)
fe6163bf 185 if (malloc_pointers[idx].ptr)
02d1d628
AMH
186 bndcheck(idx);
187}
188
189
190
191
192
193void
194myfree_file_line(void *p, char *file, int line) {
195 char *pp = p;
196 int match = 0;
197 int i;
198
fe6163bf 199 for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr == p) {
02d1d628
AMH
200 mm_log((1,"myfree_file_line: pointer %i (%s) freed at %s (%i)\n", i, malloc_pointers[i].comm, file, line));
201 bndcheck(i);
fe6163bf 202 malloc_pointers[i].ptr = NULL;
02d1d628
AMH
203 match++;
204 }
205
206 if (match != 1) {
f1ac5027 207 mm_log((1, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line));
02d1d628
AMH
208 }
209
210 mm_log((1, "myfree_file_line: freeing address %p\n", pp-UNDRRNVAL));
211
212 free(pp-UNDRRNVAL);
213}
214
215#else
216
217#define malloc_comm(a,b) (mymalloc(a))
218
219void
220malloc_state() {
221 printf("malloc_state: not in debug mode\n");
222}
223
224void*
225mymalloc(int size) {
226 void *buf;
227
a743c0a6 228 if ( (buf = malloc(size)) == NULL ) {
faa9b3e7 229 mm_log((1, "mymalloc: unable to malloc %d\n", size));
cc6483e0 230 fprintf(stderr,"Unable to malloc %d.\n", size); exit(3);
02d1d628 231 }
f1ac5027 232 mm_log((1, "mymalloc(size %d) -> %p\n", size, buf));
02d1d628
AMH
233 return buf;
234}
235
236void
237myfree(void *p) {
dd55acc8 238 mm_log((1, "myfree(p %p)\n", p));
02d1d628
AMH
239 free(p);
240}
241
faa9b3e7
TC
242void *
243myrealloc(void *block, size_t size) {
244 void *result;
245
246 mm_log((1, "myrealloc(block %p, size %u)\n", block, size));
247 if ((result = realloc(block, size)) == NULL) {
248 mm_log((1, "myrealloc: out of memory\n"));
249 fprintf(stderr, "Out of memory.\n");
250 exit(3);
251 }
252 return result;
253}
254
02d1d628
AMH
255#endif /* IMAGER_MALLOC_DEBUG */
256
257
258
259
260
261
262
263
264#undef min
265#undef max
266
267int
268min(int a,int b) {
269 if (a<b) return a; else return b;
270}
271
272int
273max(int a,int b) {
274 if (a>b) return a; else return b;
275}
276
277int
278myread(int fd,void *buf,int len) {
279 unsigned char* bufc;
280 int bc,rc;
281 bufc = (unsigned char*)buf;
282 bc=0;
283 while( ((rc=read(fd,bufc+bc,len-bc))>0 ) && (bc!=len) ) bc+=rc;
284 if ( rc < 0 ) return rc;
285 else return bc;
286}
287
288int
289mywrite(int fd,void *buf,int len) {
290 unsigned char* bufc;
291 int bc,rc;
292 bufc=(unsigned char*)buf;
293 bc=0;
294 while(((rc=write(fd,bufc+bc,len-bc))>0) && (bc!=len)) bc+=rc;
295 if (rc<0) return rc;
296 else return bc;
297}
298
299void
300interleave(unsigned char *inbuffer,unsigned char *outbuffer,int rowsize,int channels) {
301 int ch,ind,i;
302 i=0;
303 if ( inbuffer==outbuffer ) return; /* Check if data is already in interleaved format */
304 for( ind=0; ind<rowsize; ind++) for (ch=0; ch<channels; ch++) outbuffer[i++] = inbuffer[rowsize*ch+ind];
305}
306
307