]> git.imager.perl.org - imager.git/blob - iolayer.c
[rt #73359] draw non-AA text using FT2 in normal mode
[imager.git] / iolayer.c
1 #define IMAGER_NO_CONTEXT
2 #include "imager.h"
3 #include "iolayer.h"
4 #include "imerror.h"
5 #include "log.h"
6 #include <stdlib.h>
7 #include <stdio.h>
8 #ifdef _MSC_VER
9 #include <io.h>
10 #endif
11 #include <string.h>
12 #include <errno.h>
13 #include "imageri.h"
14
15 #define IOL_DEB(x)
16 #define IOL_DEBs stderr
17
18 #define IO_BUF_SIZE 8192
19
20 char *io_type_names[] = { "FDSEEK", "FDNOSEEK", "BUFFER", "CBSEEK", "CBNOSEEK", "BUFCHAIN" };
21
22 typedef struct io_blink {
23   char buf[BBSIZ];
24   /* size_t cnt; */
25   size_t len;                   /* How large is this buffer = BBZIS for now */
26   struct io_blink *next;
27   struct io_blink *prev;
28 } io_blink;
29
30
31 typedef struct {
32   i_io_glue_t   base;
33   int           fd;
34 } io_fdseek;
35
36 typedef struct {
37   i_io_glue_t   base;
38   const char    *data;
39   size_t        len;
40   i_io_closebufp_t     closecb;        /* free memory mapped segment or decrement refcount */
41   void          *closedata;
42   off_t cpos;
43 } io_buffer;
44
45 typedef struct {
46   i_io_glue_t   base;
47   void          *p;             /* Callback data */
48   i_io_readl_t  readcb;
49   i_io_writel_t writecb;
50   i_io_seekl_t  seekcb;
51   i_io_closel_t closecb;
52   i_io_destroyl_t      destroycb;
53 } io_cb;
54
55 typedef struct {
56   off_t offset;                 /* Offset of the source - not used */
57   off_t length;                 /* Total length of chain in bytes */
58   io_blink *head;               /* Start of chain */
59   io_blink *tail;               /* End of chain */
60   off_t tfill;                  /* End of stream in last link */
61   io_blink *cp;                 /* Current element of list */
62   off_t cpos;                   /* Offset within the current */
63   off_t gpos;                   /* Global position in stream */
64 } io_ex_bchain;
65
66 /* turn current offset, file length, whence and offset into a new offset */
67 #define calc_seek_offset(curr_off, length, offset, whence) \
68   (((whence) == SEEK_SET) ? (offset) : \
69    ((whence) == SEEK_CUR) ? (curr_off) + (offset) : \
70    ((whence) == SEEK_END) ? (length) + (offset) : -1)
71
72 /*
73 =head1 NAME
74
75 iolayer.c - encapsulates different source of data into a single framework.
76
77 =head1 SYNOPSIS
78
79   io_glue *ig = io_new_fd( fileno(stdin) );
80   method = io_reqmeth( IOL_NOSEEK | IOL_MMAP ); // not implemented yet
81
82   switch (method) {
83   case IOL_NOSEEK:
84     code that uses ig->readcb()
85     to read data goes here.
86     break;
87   case IOL_MMAP:
88     code that uses ig->readcb()
89     to read data goes here.
90     break;
91   }  
92
93   io_glue_destroy(ig);
94   // and much more
95
96 =head1 DESCRIPTION
97
98 iolayer.c implements the basic functions to create and destroy io_glue
99 objects for Imager.  The typical usage pattern for data sources is:
100
101    1. Create the source (io_new_fd)
102    2. Define how you want to get data from it (io_reqmeth)
103    3. read from it using the interface requested (ig->readdb, ig->mmapcb)
104    4. Close the source, which 
105       shouldn't really close the underlying source. (io_glue DESTROY)
106
107 =head1 FUNCTION REFERENCE
108
109 Some of these functions are internal.
110
111 =over
112
113 =cut
114 */
115
116 static void
117 i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb,
118           i_io_writep_t writecb, i_io_seekp_t seekcb);
119
120 static ssize_t fd_read(io_glue *ig, void *buf, size_t count);
121 static ssize_t fd_write(io_glue *ig, const void *buf, size_t count);
122 static off_t fd_seek(io_glue *ig, off_t offset, int whence);
123 static int fd_close(io_glue *ig);
124 static ssize_t fd_size(io_glue *ig);
125 static const char *my_strerror(int err);
126 static void i_io_setup_buffer(io_glue *ig);
127 static void
128 i_io_start_write(io_glue *ig);
129 static int
130 i_io_read_fill(io_glue *ig, ssize_t needed);
131 static void
132 dump_data(unsigned char *start, unsigned char *end, int bias);
133 static ssize_t realseek_read(io_glue *igo, void *buf, size_t count);
134 static ssize_t realseek_write(io_glue *igo, const void *buf, size_t count);
135 static int realseek_close(io_glue *igo);
136 static off_t realseek_seek(io_glue *igo, off_t offset, int whence);
137 static void realseek_destroy(io_glue *igo);
138 static ssize_t buffer_read(io_glue *igo, void *buf, size_t count);
139 static ssize_t buffer_write(io_glue *ig, const void *buf, size_t count);
140 static int buffer_close(io_glue *ig);
141 static off_t buffer_seek(io_glue *igo, off_t offset, int whence);
142 static void buffer_destroy(io_glue *igo);
143 static io_blink*io_blink_new(void);
144 static void io_bchain_advance(io_ex_bchain *ieb);
145 static void io_destroy_bufchain(io_ex_bchain *ieb);
146 static ssize_t bufchain_read(io_glue *ig, void *buf, size_t count);
147 static ssize_t bufchain_write(io_glue *ig, const void *buf, size_t count);
148 static int bufchain_close(io_glue *ig);
149 static off_t bufchain_seek(io_glue *ig, off_t offset, int whence);
150 static void bufchain_destroy(io_glue *ig);
151
152 /*
153  * Methods for setting up data source
154  */
155
156 /*
157 =item im_io_new_bufchain(ctx)
158 X<im_io_new_bufchain API>X<i_io_new_bufchain API>
159 =order 10
160 =category I/O Layers
161
162 Returns a new io_glue object that has the 'empty' source and but can
163 be written to and read from later (like a pseudo file).
164
165 Also callable as C<io_new_bufchain()>.
166
167 =cut
168 */
169
170 io_glue *
171 im_io_new_bufchain(pIMCTX) {
172   io_glue *ig;
173   io_ex_bchain *ieb = mymalloc(sizeof(io_ex_bchain));
174
175   im_log((aIMCTX, 1, "io_new_bufchain()\n"));
176
177   ig = mymalloc(sizeof(io_glue));
178   memset(ig, 0, sizeof(*ig));
179   i_io_init(aIMCTX, ig, BUFCHAIN, bufchain_read, bufchain_write, bufchain_seek);
180
181   ieb->offset = 0;
182   ieb->length = 0;
183   ieb->cpos   = 0;
184   ieb->gpos   = 0;
185   ieb->tfill  = 0;
186   
187   ieb->head   = io_blink_new();
188   ieb->cp     = ieb->head;
189   ieb->tail   = ieb->head;
190   
191   ig->exdata    = ieb;
192   ig->closecb   = bufchain_close;
193   ig->destroycb = bufchain_destroy;
194
195   im_context_refinc(aIMCTX, "im_io_new_bufchain");
196
197   return ig;
198 }
199
200 /*
201 =item im_io_new_buffer(ctx, data, length)
202 X<im_io_new_buffer API>X<io_new_buffer API>
203 =order 10
204 =category I/O Layers
205
206 Returns a new io_glue object that has the source defined as reading
207 from specified buffer.  Note that the buffer is not copied.
208
209    ctx - an Imager context object
210    data - buffer to read from
211    length - length of buffer
212
213 Also callable as C<io_new_buffer(data, length>.
214
215 =cut
216 */
217
218 io_glue *
219 im_io_new_buffer(pIMCTX, const char *data, size_t len, i_io_closebufp_t closecb, void *closedata) {
220   io_buffer *ig;
221   
222   im_log((aIMCTX, 1, "io_new_buffer(data %p, len %ld, closecb %p, closedata %p)\n", data, (long)len, closecb, closedata));
223
224   ig = mymalloc(sizeof(io_buffer));
225   memset(ig, 0, sizeof(*ig));
226   i_io_init(aIMCTX, &ig->base, BUFFER, buffer_read, buffer_write, buffer_seek);
227   ig->data      = data;
228   ig->len       = len;
229   ig->closecb   = closecb;
230   ig->closedata = closedata;
231
232   ig->cpos   = 0;
233   
234   ig->base.closecb   = buffer_close;
235   ig->base.destroycb = buffer_destroy;
236
237   im_context_refinc(aIMCTX, "im_io_new_bufchain");
238
239   return (io_glue *)ig;
240 }
241
242
243 /*
244 =item im_io_new_fd(ctx, file)
245 X<io_new_fd API>X<im_io_new_fd API>
246 =order 10
247 =category I/O Layers
248
249 Returns a new io_glue object that has the source defined as reading
250 from specified file descriptor.  Note that the the interface to receiving
251 data from the io_glue callbacks hasn't been done yet.
252
253   ctx - and Imager context object
254   file - file descriptor to read/write from
255
256 Also callable as C<io_new_fd(file)>.
257
258 =cut
259 */
260
261 io_glue *
262 im_io_new_fd(pIMCTX, int fd) {
263   io_fdseek *ig;
264
265   im_log((aIMCTX, 1, "io_new_fd(fd %d)\n", fd));
266
267   ig = mymalloc(sizeof(io_fdseek));
268   memset(ig, 0, sizeof(*ig));
269   i_io_init(aIMCTX, &ig->base, FDSEEK, fd_read, fd_write, fd_seek);
270   ig->fd = fd;
271
272   ig->base.closecb   = fd_close;
273   ig->base.sizecb    = fd_size;
274   ig->base.destroycb = NULL;
275   im_context_refinc(aIMCTX, "im_io_new_bufchain");
276
277   im_log((aIMCTX, 1, "(%p) <- io_new_fd\n", ig));
278   return (io_glue *)ig;
279 }
280
281 /*
282 =item im_io_new_cb(ctx, p, read_cb, write_cb, seek_cb, close_cb, destroy_cb)
283 X<im_io_new_cb API>X<io_new_cb API>
284 =category I/O Layers
285 =order 10
286
287 Create a new I/O layer object that calls your supplied callbacks.
288
289 In general the callbacks should behave like the corresponding POSIX
290 primitives.
291
292 =over
293
294 =item *
295
296 C<read_cb>(p, buffer, length) should read up to C<length> bytes into
297 C<buffer> and return the number of bytes read.  At end of file, return
298 0.  On error, return -1.
299
300 =item *
301
302 C<write_cb>(p, buffer, length) should write up to C<length> bytes from
303 C<buffer> and return the number of bytes written.  A return value <= 0
304 will be treated as an error.
305
306 =item *
307
308 C<seekcb>(p, offset, whence) should seek and return the new offset.
309
310 =item *
311
312 C<close_cb>(p) should return 0 on success, -1 on failure.
313
314 =item *
315
316 C<destroy_cb>(p) should release any memory specific to your callback
317 handlers.
318
319 =back
320
321 Also callable as C<io_new_cb(p, readcb, writecb, seekcb, closecb,
322 destroycb)>.
323
324 =cut
325 */
326
327 io_glue *
328 im_io_new_cb(pIMCTX, void *p, i_io_readl_t readcb, i_io_writel_t writecb, 
329           i_io_seekl_t seekcb, i_io_closel_t closecb, 
330           i_io_destroyl_t destroycb) {
331   io_cb *ig;
332
333   im_log((aIMCTX, 1, "io_new_cb(p %p, readcb %p, writecb %p, seekcb %p, closecb %p, "
334           "destroycb %p)\n", p, readcb, writecb, seekcb, closecb, destroycb));
335   ig = mymalloc(sizeof(io_cb));
336   memset(ig, 0, sizeof(*ig));
337   i_io_init(aIMCTX, &ig->base, CBSEEK, realseek_read, realseek_write, realseek_seek);
338   im_log((aIMCTX, 1, "(%p) <- io_new_cb\n", ig));
339
340   ig->base.closecb   = realseek_close;
341   ig->base.destroycb = realseek_destroy;
342
343   ig->p         = p;
344   ig->readcb    = readcb;
345   ig->writecb   = writecb;
346   ig->seekcb    = seekcb;
347   ig->closecb   = closecb;
348   ig->destroycb = destroycb;
349   
350   im_context_refinc(aIMCTX, "im_io_new_bufchain");
351
352   return (io_glue *)ig;
353 }
354
355 /*
356 =item io_slurp(ig, c)
357 X<io_slurp API>
358 =category I/O Layers
359
360 Takes the source that the io_glue is bound to and allocates space for
361 a return buffer and returns the entire content in a single buffer.
362 Note: This only works for io_glue objects created by
363 io_new_bufchain().  It is useful for saving to scalars and such.
364
365    ig - io_glue object
366    c  - pointer to a pointer to where data should be copied to
367
368   char *data;
369   size_t size = io_slurp(ig, &data);
370   ... do something with the data ...
371   myfree(data);
372
373 io_slurp() will abort the program if the supplied I/O layer is not
374 from io_new_bufchain().
375
376 =cut
377 */
378
379 size_t
380 io_slurp(io_glue *ig, unsigned char **c) {
381   ssize_t rc;
382   off_t orgoff;
383   io_ex_bchain *ieb;
384   unsigned char *cc;
385   io_type inn = ig->type;
386   
387   if ( inn != BUFCHAIN ) {
388     dIMCTXio(ig);
389     im_fatal(aIMCTX, 0, "io_slurp: called on a source that is not from a bufchain\n");
390   }
391
392   ieb = ig->exdata;
393   cc = *c = mymalloc( ieb->length );
394   
395   orgoff = ieb->gpos;
396   
397   bufchain_seek(ig, 0, SEEK_SET);
398   
399   rc = bufchain_read(ig, cc, ieb->length);
400
401   if (rc != ieb->length) {
402     dIMCTXio(ig);
403     im_fatal(aIMCTX,1, "io_slurp: bufchain_read returned an incomplete read: rc = %d, request was %d\n", rc, ieb->length);
404   }
405
406   return rc;
407 }
408
409 /*
410 =item io_glue_destroy(ig)
411 X<io_glue_destroy API>
412 =category I/O Layers
413 =order 90
414 =synopsis io_glue_destroy(ig);
415
416 Destroy an io_glue objects.  Should clean up all related buffers.
417
418    ig - io_glue object to destroy.
419
420 =cut
421 */
422
423 void
424 io_glue_destroy(io_glue *ig) {
425   dIMCTXio(ig);
426   im_log((aIMCTX, 1, "io_glue_DESTROY(ig %p)\n", ig));
427
428   if (ig->destroycb)
429     ig->destroycb(ig);
430
431   if (ig->buffer)
432     myfree(ig->buffer);
433   
434   myfree(ig);
435
436   im_context_refdec(aIMCTX, "io_glue_destroy");
437 }
438
439 /*
440 =item i_io_getc(ig)
441 =category I/O Layers
442
443 A macro to read a single byte from a buffered I/O glue object.
444
445 Returns EOF on failure, or a byte.
446
447 =cut
448 */
449
450 int
451 i_io_getc_imp(io_glue *ig) {
452   if (ig->write_ptr)
453     return EOF;
454   
455   if (ig->error || ig->buf_eof)
456     return EOF;
457   
458   if (!ig->buffered) {
459     unsigned char buf;
460     ssize_t rc = i_io_raw_read(ig, &buf, 1);
461     if (rc > 0) {
462       return buf;
463     }
464     else if (rc == 0) {
465       ig->buf_eof = 1;
466       return EOF;
467     }
468     else {
469       ig->error = 1;
470       return EOF;
471     }
472   }
473
474   if (!ig->buffer)
475     i_io_setup_buffer(ig);
476   
477   if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
478     if (!i_io_read_fill(ig, 1))
479       return EOF;
480   }
481   
482   return *(ig->read_ptr++);
483 }
484
485 /*
486 =item i_io_peekc(ig)
487 =category I/O Layers
488
489 Read the next character from the stream without advancing the stream.
490
491 On error or end of file, return EOF.
492
493 For unbuffered streams a single character buffer will be setup.
494
495 =cut
496 */
497
498 int
499 i_io_peekc_imp(io_glue *ig) {
500   if (ig->write_ptr)
501     return EOF;
502
503   if (!ig->buffer)
504     i_io_setup_buffer(ig);
505
506   if (!ig->buffered) {
507     ssize_t rc = i_io_raw_read(ig, ig->buffer, 1);
508     if (rc > 0) {
509       ig->read_ptr = ig->buffer;
510       ig->read_end = ig->buffer + 1;
511       return *(ig->buffer);
512     }
513     else if (rc == 0) {
514       ig->buf_eof = 1;
515       return EOF;
516     }
517     else {
518       ig->error = 1;
519       return EOF;
520     }
521   }
522
523   if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
524     if (ig->error || ig->buf_eof)
525       return EOF;
526     
527     if (!i_io_read_fill(ig, 1))
528       return EOF;
529   }
530
531   return *(ig->read_ptr);
532 }
533
534 /*
535 =item i_io_peekn(ig, buffer, size)
536 =category I/O Layers
537 =synopsis ssize_t count = i_io_peekn(ig, buffer, sizeof(buffer));
538
539 Buffer at least C<size> (at most C<< ig->buf_size >> bytes of data
540 from the stream and return C<size> bytes of it to the caller in
541 C<buffer>.
542
543 This ignores the buffered state of the stream, and will always setup
544 buffering if needed.
545
546 If no C<type> parameter is provided to Imager::read() or
547 Imager::read_multi(), Imager will call C<i_io_peekn()> when probing
548 for the file format.
549
550 Returns -1 on error, 0 if there is no data before EOF, or the number
551 of bytes read into C<buffer>.
552
553 =cut
554 */
555
556 ssize_t
557 i_io_peekn(io_glue *ig, void *buf, size_t size) {
558   IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn(%p, %p, %d)\n", ig, buf, (int)size));
559
560   if (size == 0) {
561     dIMCTXio(ig);
562     i_push_error(0, "peekn size must be positive");
563     IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (zero size)\n"));
564     return -1;
565   }
566
567   if (ig->write_ptr) {
568     IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (write_ptr set)\n"));
569     return -1;
570   }
571
572   if (!ig->buffer)
573     i_io_setup_buffer(ig);
574
575   if ((!ig->read_ptr || size > ig->read_end - ig->read_ptr)
576       && !(ig->buf_eof || ig->error)) {
577     i_io_read_fill(ig, size);
578   }
579   
580   if (size > ig->read_end - ig->read_ptr)
581     size = ig->read_end - ig->read_ptr;
582
583   if (size)
584     memcpy(buf, ig->read_ptr, size);
585   else if (ig->buf_eof) {
586     IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => 0 (eof)\n"));
587     return 0;
588   }
589   else if (ig->error) {
590     IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (error)\n"));
591     return -1;
592   }
593   else {
594     IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() - size 0 but not eof or error!\n"));
595     return -1;
596   }
597
598   IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => %d\n", (int)size));
599
600   return size;
601 }
602
603 /*
604 =item i_io_putc(ig, c)
605 =category I/O Layers
606
607 Write a single character to the stream.
608
609 On success return c, on error returns EOF
610
611 =cut
612 */
613
614 int
615 i_io_putc_imp(io_glue *ig, int c) {
616   IOL_DEB(fprintf(IOL_DEBs, "i_io_putc_imp(%p, %d)\n", ig, c));
617
618   if (!ig->buffered) {
619     char buf = c;
620     ssize_t write_result;
621     int result = c;
622
623     if (ig->error)
624       return EOF;
625
626     write_result = i_io_raw_write(ig, &buf, 1);
627     if (write_result != 1) {
628       ig->error = 1;
629       result = EOF;
630       IOL_DEB(fprintf(IOL_DEBs, "  unbuffered putc() failed, setting error mode\n"));
631     }
632     IOL_DEB(fprintf(IOL_DEBs, "  unbuffered: result %d\n", result));
633
634     return result;
635   }
636
637   if (ig->read_ptr)
638     return EOF;
639
640   if (ig->error)
641     return EOF;
642
643   if (!ig->buffer)
644     i_io_setup_buffer(ig);
645
646   if (ig->write_ptr && ig->write_ptr == ig->write_end) {
647     if (!i_io_flush(ig))
648       return EOF;
649   }
650
651   i_io_start_write(ig);
652
653   *(ig->write_ptr)++ = c;
654
655   return (unsigned char)c;
656 }
657
658 /*
659 =item i_io_read(io, buffer, size)
660 =category I/O Layers
661
662 Read up to C<size> bytes from the stream C<io> into C<buffer>.
663
664 Returns the number of bytes read.  Returns 0 on end of file.  Returns
665 -1 on error.
666
667 =cut
668 */
669
670 ssize_t
671 i_io_read(io_glue *ig, void *buf, size_t size) {
672   unsigned char *pbuf = buf;
673   ssize_t read_total = 0;
674
675   IOL_DEB(fprintf(IOL_DEBs, "i_io_read(%p, %p, %u)\n", ig, buf, (unsigned)size));
676
677   if (ig->write_ptr) {
678     IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (write_ptr set)\n"));
679     return -1;
680   }
681
682   if (!ig->buffer && ig->buffered)
683     i_io_setup_buffer(ig);
684
685   if (ig->read_ptr && ig->read_ptr < ig->read_end) {
686     size_t alloc = ig->read_end - ig->read_ptr;
687     
688     if (alloc > size)
689       alloc = size;
690
691     memcpy(pbuf, ig->read_ptr, alloc);
692     ig->read_ptr += alloc;
693     pbuf += alloc;
694     size -= alloc;
695     read_total += alloc;
696   }
697
698   if (size > 0 && !(ig->error || ig->buf_eof)) {
699     if (!ig->buffered || size > ig->buf_size) {
700       ssize_t rc;
701       
702       while (size > 0 && (rc = i_io_raw_read(ig, pbuf, size)) > 0) {
703         size -= rc;
704         pbuf += rc;
705         read_total += rc;
706       }
707       
708       IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d (raw read)\n", (int)read_total));
709
710       if (rc < 0)
711         ig->error = 1;
712       else if (rc == 0)
713         ig->buf_eof = 1;
714
715       if (!read_total)
716         return rc;
717     }
718     else {
719       if (i_io_read_fill(ig, size)) {
720         size_t alloc = ig->read_end - ig->read_ptr;
721         if (alloc > size)
722           alloc = size;
723         
724         memcpy(pbuf, ig->read_ptr, alloc);
725         ig->read_ptr += alloc;
726         pbuf += alloc;
727         size -= alloc;
728         read_total += alloc;
729       }
730       else {
731         if (!read_total && ig->error) {
732           IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (fill failure)\n"));
733           return -1;
734         }
735       }
736     }
737   }
738
739   if (!read_total && ig->error)
740     read_total = -1;
741
742   IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d\n", (int)read_total));
743
744   return read_total;
745 }
746
747 /*
748 =item i_io_write(io, buffer, size)
749 =category I/O Layers
750 =synopsis ssize_t result = i_io_write(io, buffer, size)
751
752 Write to the given I/O stream.
753
754 Returns the number of bytes written.
755
756 =cut
757 */
758
759 ssize_t
760 i_io_write(io_glue *ig, const void *buf, size_t size) {
761   const unsigned char *pbuf = buf;
762   size_t write_count = 0;
763
764   IOL_DEB(fprintf(IOL_DEBs, "i_io_write(%p, %p, %u)\n", ig, buf, (unsigned)size));
765
766   if (!ig->buffered) {
767     ssize_t result;
768
769     if (ig->error) {
770       IOL_DEB(fprintf(IOL_DEBs, "  unbuffered, error state\n"));
771       return -1;
772     }
773
774     result = i_io_raw_write(ig, buf, size);
775
776     if (result != size) {
777       ig->error = 1;
778       IOL_DEB(fprintf(IOL_DEBs, "  unbuffered, setting error flag\n"));
779     }
780
781     IOL_DEB(fprintf(IOL_DEBs, "  unbuffered, result: %d\n", (int)result));
782
783     return result;
784   }
785
786   if (ig->read_ptr) {
787     IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (read_ptr set)\n"));
788     return -1;
789   }
790
791   if (ig->error) {
792     IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (error)\n"));
793     return -1;
794   }
795
796   if (!ig->buffer)
797     i_io_setup_buffer(ig);
798
799   if (!ig->write_ptr)
800     i_io_start_write(ig);
801
802   if (ig->write_ptr && ig->write_ptr + size <= ig->write_end) {
803     size_t alloc = ig->write_end - ig->write_ptr;
804     if (alloc > size)
805       alloc = size;
806     memcpy(ig->write_ptr, pbuf, alloc);
807     write_count += alloc;
808     size -= alloc;
809     pbuf += alloc;
810     ig->write_ptr += alloc;
811   }
812
813   if (size) {
814     if (!i_io_flush(ig)) {
815       IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d (i_io_flush failure)\n", (int)write_count));
816       return write_count ? write_count : -1;
817     }
818
819     i_io_start_write(ig);
820     
821     if (size > ig->buf_size) {
822       ssize_t rc;
823       while (size > 0 && (rc = i_io_raw_write(ig, pbuf, size)) > 0) {
824         write_count += rc;
825         pbuf += rc;
826         size -= rc;
827       }
828       if (rc <= 0) {
829         ig->error = 1;
830         if (!write_count) {
831           IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (direct write failure)\n"));
832           return -1;
833         }
834       }
835     }
836     else {
837       memcpy(ig->write_ptr, pbuf, size);
838       write_count += size;
839       ig->write_ptr += size;
840     }
841   }
842
843   IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d\n", (int)write_count));
844
845   return write_count;
846 }
847
848 /*
849 =item i_io_seek(io, offset, whence)
850 =category I/O Layers
851
852 Seek within the stream.
853
854 Acts like perl's seek.
855
856 =cut
857  */
858
859 off_t
860 i_io_seek(io_glue *ig, off_t offset, int whence) {
861   off_t new_off;
862
863   IOL_DEB(fprintf(IOL_DEBs, "i_io_seek(%p, %ld, %d)\n", ig, (long)offset, whence));
864
865   if (ig->write_ptr && ig->write_ptr != ig->write_end) {
866     if (!i_io_flush(ig))
867       return (off_t)(-1);
868   }
869
870   if (whence == SEEK_CUR && ig->read_ptr && ig->read_ptr != ig->read_end)
871     offset -= ig->read_end - ig->read_ptr;
872
873   ig->read_ptr = ig->read_end = NULL;
874   ig->write_ptr = ig->write_end = NULL;
875   ig->error = 0;
876   ig->buf_eof = 0;
877   
878   new_off = i_io_raw_seek(ig, offset, whence);
879   if (new_off < 0)
880     ig->error = 1;
881
882   IOL_DEB(fprintf(IOL_DEBs, "i_io_seek() => %ld\n", (long)new_off));
883
884   return new_off;
885 }
886
887 /*
888 =item i_io_flush(io)
889 =category I/O Layers
890
891 Flush any buffered output.
892
893 Returns true on success,
894
895 =cut
896 */
897
898 int
899 i_io_flush(io_glue *ig) {
900   unsigned char *bufp;
901
902   IOL_DEB(fprintf(IOL_DEBs, "i_io_flush(%p)\n", ig));
903
904   if (ig->error) {
905     IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (error set)\n", ig));
906     return 0;
907   }
908
909   /* nothing to do */
910   if (!ig->write_ptr)
911     return 1;
912
913   bufp = ig->buffer;
914   while (bufp < ig->write_ptr) {
915     ssize_t rc = i_io_raw_write(ig, bufp, ig->write_ptr - bufp);
916     if (rc <= 0) {
917       IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (write error)\n", ig));
918       ig->error = 1;
919       return 0;
920     }
921     
922     bufp += rc;
923   }
924
925   ig->write_ptr = ig->write_end = NULL;
926
927   IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 1\n", ig));
928
929   return 1;
930 }
931
932 /*
933 =item i_io_close(io)
934 =category I/O Layers
935
936 Flush any pending output and perform the close action for the stream.
937
938 Returns 0 on success.
939
940 =cut
941 */
942
943 int
944 i_io_close(io_glue *ig) {
945   int result = 0;
946
947   IOL_DEB(fprintf(IOL_DEBs, "i_io_close(%p)\n", ig));
948   if (ig->error)
949     result = -1;
950
951   if (ig->write_ptr && !i_io_flush(ig))
952     result = -1;
953
954   if (i_io_raw_close(ig))
955     result = -1;
956
957   IOL_DEB(fprintf(IOL_DEBs, "i_io_close() => %d\n", result));
958
959   return result;
960 }
961
962 /*
963 =item i_io_gets(ig, buffer, size, end_of_line)
964 =category I/O Layers
965 =synopsis char buffer[BUFSIZ]
966 =synopsis ssize_t len = i_io_gets(buffer, sizeof(buffer), '\n');
967
968 Read up to C<size>-1 bytes from the stream C<ig> into C<buffer>.
969
970 If the byte C<end_of_line> is seen then no further bytes will be read.
971
972 Returns the number of bytes read.
973
974 Always C<NUL> terminates the buffer.
975
976 =cut
977 */
978
979 ssize_t
980 i_io_gets(io_glue *ig, char *buffer, size_t size, int eol) {
981   ssize_t read_count = 0;
982   if (size < 2)
983     return 0;
984   --size; /* room for nul */
985   while (size > 0) {
986     int byte = i_io_getc(ig);
987     if (byte == EOF)
988       break;
989     *buffer++ = byte;
990     ++read_count;
991     if (byte == eol)
992       break;
993     --size;
994   }
995   *buffer++ = '\0';
996
997   return read_count;
998 }
999
1000 /*
1001 =item i_io_init(ig, readcb, writecb, seekcb)
1002
1003 Do common initialization for io_glue objects.
1004
1005 =cut
1006 */
1007
1008 static void
1009 i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
1010           i_io_seekp_t seekcb) {
1011   ig->type = type;
1012   ig->exdata = NULL;
1013   ig->readcb = readcb;
1014   ig->writecb = writecb;
1015   ig->seekcb = seekcb;
1016   ig->closecb = NULL;
1017   ig->sizecb = NULL;
1018   ig->destroycb = NULL;
1019   ig->context = aIMCTX;
1020
1021   ig->buffer = NULL;
1022   ig->read_ptr = NULL;
1023   ig->read_end = NULL;
1024   ig->write_ptr = NULL;
1025   ig->write_end = NULL;
1026   ig->buf_size = IO_BUF_SIZE;
1027   ig->buf_eof = 0;
1028   ig->error = 0;
1029   ig->buffered = 1;
1030 }
1031
1032 /*
1033 =item i_io_set_buffered(io, buffered)
1034 =category I/O Layers
1035
1036 Set the buffering mode of the stream.
1037
1038 If you switch buffering off on a stream with buffering on:
1039
1040 =over
1041
1042 =item *
1043
1044 any buffered output will be flushed.
1045
1046 =item *
1047
1048 any existing buffered input will be consumed before reads become
1049 unbuffered.
1050
1051 =back
1052
1053 Returns true on success.  This may fail if any buffered output cannot
1054 be flushed.
1055
1056 =cut
1057 */
1058
1059 int
1060 i_io_set_buffered(io_glue *ig, int buffered) {
1061   if (!buffered && ig->write_ptr) {
1062     if (!i_io_flush(ig)) {
1063       ig->error = 1;
1064       return 0;
1065     }
1066   }
1067   ig->buffered = buffered;
1068
1069   return 1;
1070 }
1071
1072 /*
1073 =item i_io_dump(ig)
1074
1075 Dump the base fields of an io_glue object to stdout.
1076
1077 =cut
1078 */
1079 void
1080 i_io_dump(io_glue *ig, int flags) {
1081   fprintf(IOL_DEBs, "ig %p:\n", ig);
1082   fprintf(IOL_DEBs, "  type: %d\n", ig->type);  
1083   fprintf(IOL_DEBs, "  exdata: %p\n", ig->exdata);
1084   if (flags & I_IO_DUMP_CALLBACKS) {
1085     fprintf(IOL_DEBs, "  readcb: %p\n", ig->readcb);
1086     fprintf(IOL_DEBs, "  writecb: %p\n", ig->writecb);
1087     fprintf(IOL_DEBs, "  seekcb: %p\n", ig->seekcb);
1088     fprintf(IOL_DEBs, "  closecb: %p\n", ig->closecb);
1089     fprintf(IOL_DEBs, "  sizecb: %p\n", ig->sizecb);
1090   }
1091   if (flags & I_IO_DUMP_BUFFER) {
1092     fprintf(IOL_DEBs, "  buffer: %p\n", ig->buffer);
1093     fprintf(IOL_DEBs, "  read_ptr: %p\n", ig->read_ptr);
1094     if (ig->read_ptr) {
1095       fprintf(IOL_DEBs, "    ");
1096       dump_data(ig->read_ptr, ig->read_end, 0);
1097       putc('\n', IOL_DEBs);
1098     }
1099     fprintf(IOL_DEBs, "  read_end: %p\n", ig->read_end);
1100     fprintf(IOL_DEBs, "  write_ptr: %p\n", ig->write_ptr);
1101     if (ig->write_ptr) {
1102       fprintf(IOL_DEBs, "    ");
1103       dump_data(ig->buffer, ig->write_ptr, 1);
1104       putc('\n', IOL_DEBs);
1105     }
1106     fprintf(IOL_DEBs, "  write_end: %p\n", ig->write_end);
1107     fprintf(IOL_DEBs, "  buf_size: %u\n", (unsigned)(ig->buf_size));
1108   }
1109   if (flags & I_IO_DUMP_STATUS) {
1110     fprintf(IOL_DEBs, "  buf_eof: %d\n", ig->buf_eof);
1111     fprintf(IOL_DEBs, "  error: %d\n", ig->error);
1112     fprintf(IOL_DEBs, "  buffered: %d\n", ig->buffered);
1113   }
1114 }
1115
1116 /*
1117 =back
1118
1119 =head1 INTERNAL FUNCTIONS
1120
1121 =over
1122
1123 =item my_strerror
1124
1125 Calls strerror() and ensures we don't return NULL.
1126
1127 On some platforms it's possible for strerror() to return NULL, this
1128 wrapper ensures we only get non-NULL values.
1129
1130 =cut
1131 */
1132
1133 static
1134 const char *my_strerror(int err) {
1135   const char *result = strerror(err);
1136   
1137   if (!result)
1138     result = "Unknown error";
1139   
1140   return result;
1141 }
1142
1143 static void
1144 i_io_setup_buffer(io_glue *ig) {
1145   ig->buffer = mymalloc(ig->buf_size);
1146 }
1147
1148 static void
1149 i_io_start_write(io_glue *ig) {
1150   ig->write_ptr = ig->buffer;
1151   ig->write_end = ig->buffer + ig->buf_size;
1152 }
1153
1154 static int
1155 i_io_read_fill(io_glue *ig, ssize_t needed) {
1156   unsigned char *buf_end = ig->buffer + ig->buf_size;
1157   unsigned char *buf_start = ig->buffer;
1158   unsigned char *work = ig->buffer;
1159   ssize_t rc;
1160   int good = 0;
1161
1162   IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%p, %d)\n", ig, (int)needed));
1163
1164   /* these conditions may be unused, callers should also be checking them */
1165   if (ig->error || ig->buf_eof)
1166     return 0;
1167
1168   if (needed > ig->buf_size)
1169     needed = ig->buf_size;
1170
1171   if (ig->read_ptr && ig->read_ptr < ig->read_end) {
1172     size_t kept = ig->read_end - ig->read_ptr;
1173
1174     if (needed < kept) {
1175       IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%u) -> 1 (already have enough)\n", (unsigned)needed));
1176       return 1;
1177     }
1178
1179     if (ig->read_ptr != ig->buffer)
1180       memmove(ig->buffer, ig->read_ptr, kept);
1181
1182     good = 1; /* we have *something* available to read */
1183     work = buf_start + kept;
1184     needed -= kept;
1185   }
1186   else {
1187     work = ig->buffer;
1188   }
1189
1190   /* there should always be buffer space the first time around, but
1191      avoid a compiler warning here */
1192   rc = -1;
1193   while (work < buf_end && (rc = i_io_raw_read(ig, work, buf_end - work)) > 0) {
1194     work += rc;
1195     good = 1;
1196     if (needed < rc)
1197       break;
1198
1199     needed -= rc;
1200   }
1201
1202   if (rc < 0) {
1203     ig->error = 1;
1204     IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc %d, setting error\n",
1205                     (int)rc));
1206   }
1207   else if (rc == 0) {
1208     ig->buf_eof = 1;
1209     IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc 0, setting eof\n"));
1210   }
1211
1212   if (good) {
1213     ig->read_ptr = buf_start;
1214     ig->read_end = work;
1215   }
1216   
1217   IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill => %d, %u buffered\n", good,
1218                   (unsigned)(ig->read_end - ig->read_ptr)));
1219   return good;
1220 }
1221
1222 /*
1223 =item dump_data(start, end, bias)
1224
1225 Hex dump the data between C<start> and C<end>.
1226
1227 If there is more than a pleasing amount of data, either dump the
1228 beginning (C<bias == 0>) or dump the end C(<bias != 0>) of the range.
1229
1230 =cut
1231 */
1232
1233 static void
1234 dump_data(unsigned char *start, unsigned char *end, int bias) {
1235   unsigned char *p;
1236   size_t count = end - start;
1237
1238   if (start == end) {
1239     fprintf(IOL_DEBs, "(empty)");
1240     return;
1241   }
1242
1243   if (count > 15) {
1244     if (bias) {
1245       fprintf(IOL_DEBs, "... ");
1246       start = end - 14;
1247     }
1248     else {
1249       end = start + 14;
1250     }
1251       
1252     for (p = start; p < end; ++p) {
1253       fprintf(IOL_DEBs, " %02x", *p);
1254     }
1255     putc(' ', IOL_DEBs);
1256     putc('<', IOL_DEBs);
1257     for (p = start; p < end; ++p) {
1258       if (*p < ' ' || *p > '~')
1259         putc('.', IOL_DEBs);
1260       else
1261         putc(*p, IOL_DEBs);
1262     }
1263     putc('>', IOL_DEBs);
1264     if (!bias)
1265       fprintf(IOL_DEBs, " ...");
1266   }
1267   else {
1268     for (p = start; p < end; ++p) {
1269       fprintf(IOL_DEBs, " %02x", *p);
1270     }
1271     putc(' ', IOL_DEBs);
1272     for (p = start; p < end; ++p) {
1273       if (*p < ' ' || *p > '~')
1274         putc('.', IOL_DEBs);
1275       else
1276         putc(*p, IOL_DEBs);
1277     }
1278   }
1279 }
1280
1281 /*
1282  * Callbacks for sources that cannot seek
1283  */
1284
1285 /*
1286  * Callbacks for sources that can seek 
1287  */
1288
1289 /*
1290 =item realseek_read(ig, buf, count)
1291
1292 Does the reading from a source that can be seeked on
1293
1294    ig    - io_glue object
1295    buf   - buffer to return data in
1296    count - number of bytes to read into buffer max
1297
1298 =cut
1299 */
1300
1301 static
1302 ssize_t 
1303 realseek_read(io_glue *igo, void *buf, size_t count) {
1304   io_cb        *ig = (io_cb *)igo;
1305   void *p          = ig->p;
1306   ssize_t       rc = 0;
1307
1308   IOL_DEB( fprintf(IOL_DEBs, "realseek_read:  buf = %p, count = %u\n", 
1309                    buf, (unsigned)count) );
1310   rc = ig->readcb(p,buf,count);
1311
1312   IOL_DEB( fprintf(IOL_DEBs, "realseek_read: rc = %d\n", (int)rc) );
1313
1314   return rc;
1315 }
1316
1317
1318 /*
1319 =item realseek_write(ig, buf, count)
1320
1321 Does the writing to a 'source' that can be seeked on
1322
1323    ig    - io_glue object
1324    buf   - buffer that contains data
1325    count - number of bytes to write
1326
1327 =cut
1328 */
1329
1330 static
1331 ssize_t 
1332 realseek_write(io_glue *igo, const void *buf, size_t count) {
1333   io_cb        *ig = (io_cb *)igo;
1334   void          *p = ig->p;
1335   ssize_t       rc = 0;
1336   size_t        bc = 0;
1337   char       *cbuf = (char*)buf; 
1338   
1339   IOL_DEB( fprintf(IOL_DEBs, "realseek_write: ig = %p, buf = %p, "
1340                    "count = %u\n", ig, buf, (unsigned)count) );
1341
1342   /* Is this a good idea? Would it be better to handle differently? 
1343      skip handling? */
1344   while( count!=bc && (rc = ig->writecb(p,cbuf+bc,count-bc))>0 ) {
1345     bc+=rc;
1346   }
1347
1348   IOL_DEB( fprintf(IOL_DEBs, "realseek_write: rc = %d, bc = %u\n", (int)rc, (unsigned)bc) );
1349   return rc < 0 ? rc : bc;
1350 }
1351
1352
1353 /*
1354 =item realseek_close(ig)
1355
1356 Closes a source that can be seeked on.  Not sure if this should be an
1357 actual close or not.  Does nothing for now.  Should be fixed.
1358
1359    ig - data source
1360
1361 =cut */
1362
1363 static
1364 int
1365 realseek_close(io_glue *igo) {
1366   io_cb *ig = (io_cb *)igo;
1367   dIMCTXio(igo);
1368
1369   IOL_DEB(fprintf(IOL_DEBs, "realseek_close(%p)\n", ig));
1370   im_log((aIMCTX,1, "realseek_close(ig %p)\n", ig));
1371   if (ig->closecb)
1372     return ig->closecb(ig->p);
1373   else
1374     return 0;
1375 }
1376
1377
1378 /*
1379 =item realseek_seek(ig, offset, whence)
1380
1381 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1382 have an offset into a file that is different from what the underlying library thinks.
1383
1384    ig     - data source
1385    offset - offset into stream
1386    whence - whence argument a la lseek
1387
1388 =cut
1389 */
1390
1391 static
1392 off_t
1393 realseek_seek(io_glue *igo, off_t offset, int whence) {
1394   io_cb *ig = (io_cb *)igo;
1395   void *p = ig->p;
1396   off_t rc;
1397   IOL_DEB( fprintf(IOL_DEBs, "realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1398   rc = ig->seekcb(p, offset, whence);
1399
1400   IOL_DEB( fprintf(IOL_DEBs, "realseek_seek: rc %ld\n", (long) rc) );
1401   return rc;
1402   /* FIXME: How about implementing this offset handling stuff? */
1403 }
1404
1405 static
1406 void
1407 realseek_destroy(io_glue *igo) {
1408   io_cb *ig = (io_cb *)igo;
1409
1410   if (ig->destroycb)
1411     ig->destroycb(ig->p);
1412 }
1413
1414 /*
1415  * Callbacks for sources that are a fixed size buffer
1416  */
1417
1418 /*
1419 =item buffer_read(ig, buf, count)
1420
1421 Does the reading from a buffer source
1422
1423    ig    - io_glue object
1424    buf   - buffer to return data in
1425    count - number of bytes to read into buffer max
1426
1427 =cut
1428 */
1429
1430 static
1431 ssize_t 
1432 buffer_read(io_glue *igo, void *buf, size_t count) {
1433   io_buffer *ig = (io_buffer *)igo;
1434
1435   IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
1436
1437   if ( ig->cpos+count > ig->len ) {
1438     dIMCTXio(igo);
1439     im_log((aIMCTX, 1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1440     count = ig->len - ig->cpos;
1441   }
1442   
1443   memcpy(buf, ig->data+ig->cpos, count);
1444   ig->cpos += count;
1445   IOL_DEB( fprintf(IOL_DEBs, "buffer_read: count = %ld\n", (long)count) );
1446   return count;
1447 }
1448
1449
1450 /*
1451 =item buffer_write(ig, buf, count)
1452
1453 Does nothing, returns -1
1454
1455    ig    - io_glue object
1456    buf   - buffer that contains data
1457    count - number of bytes to write
1458
1459 =cut
1460 */
1461
1462 static
1463 ssize_t 
1464 buffer_write(io_glue *ig, const void *buf, size_t count) {
1465   dIMCTXio(ig);
1466   im_log((aIMCTX, 1, "buffer_write called, this method should never be called.\n"));
1467   return -1;
1468 }
1469
1470
1471 /*
1472 =item buffer_close(ig)
1473
1474 Closes a source that can be seeked on.  Not sure if this should be an actual close
1475 or not.  Does nothing for now.  Should be fixed.
1476
1477    ig - data source
1478
1479 =cut
1480 */
1481
1482 static
1483 int
1484 buffer_close(io_glue *ig) {
1485   dIMCTXio(ig);
1486   im_log((aIMCTX, 1, "buffer_close(ig %p)\n", ig));
1487
1488   return 0;
1489 }
1490
1491
1492 /*
1493 =item buffer_seek(ig, offset, whence)
1494
1495 Implements seeking for a buffer source.
1496
1497    ig     - data source
1498    offset - offset into stream
1499    whence - whence argument a la lseek
1500
1501 =cut
1502 */
1503
1504 static
1505 off_t
1506 buffer_seek(io_glue *igo, off_t offset, int whence) {
1507   io_buffer *ig = (io_buffer *)igo;
1508   off_t reqpos = 
1509     calc_seek_offset(ig->cpos, ig->len, offset, whence);
1510   
1511   if (reqpos > ig->len) {
1512     dIMCTXio(igo);
1513     im_log((aIMCTX, 1, "seeking out of readable range\n"));
1514     return (off_t)-1;
1515   }
1516   if (reqpos < 0) {
1517     dIMCTXio(igo);
1518     i_push_error(0, "seek before beginning of file");
1519     return (off_t)-1;
1520   }
1521   
1522   ig->cpos = reqpos;
1523   IOL_DEB( fprintf(IOL_DEBs, "buffer_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1524
1525   return reqpos;
1526   /* FIXME: How about implementing this offset handling stuff? */
1527 }
1528
1529 static
1530 void
1531 buffer_destroy(io_glue *igo) {
1532   io_buffer *ig = (io_buffer *)igo;
1533
1534   if (ig->closecb) {
1535     dIMCTXio(igo);
1536     im_log((aIMCTX, 1,"calling close callback %p for io_buffer\n", 
1537             ig->closecb));
1538     ig->closecb(ig->closedata);
1539   }
1540 }
1541
1542
1543
1544 /*
1545  * Callbacks for sources that are a chain of variable sized buffers
1546  */
1547
1548
1549
1550 /* Helper functions for buffer chains */
1551
1552 static
1553 io_blink*
1554 io_blink_new(void) {
1555   io_blink *ib;
1556
1557 #if 0
1558   im_log((aIMCTX, 1, "io_blink_new()\n"));
1559 #endif
1560
1561   ib = mymalloc(sizeof(io_blink));
1562
1563   ib->next = NULL;
1564   ib->prev = NULL;
1565   ib->len  = BBSIZ;
1566
1567   memset(&ib->buf, 0, ib->len);
1568   return ib;
1569 }
1570
1571
1572
1573 /*
1574 =item io_bchain_advance(ieb)
1575
1576 Advances the buffer chain to the next link - extending if
1577 necessary.  Also adjusts the cpos and tfill counters as needed.
1578
1579    ieb   - buffer chain object
1580
1581 =cut
1582 */
1583
1584 static
1585 void
1586 io_bchain_advance(io_ex_bchain *ieb) {
1587   if (ieb->cp->next == NULL) {
1588     ieb->tail = io_blink_new();
1589     ieb->tail->prev = ieb->cp;
1590     ieb->cp->next   = ieb->tail;
1591
1592     ieb->tfill = 0; /* Only set this if we added a new slice */
1593   }
1594   ieb->cp    = ieb->cp->next;
1595   ieb->cpos  = 0;
1596 }
1597
1598
1599
1600 /*
1601 =item io_bchain_destroy()
1602
1603 frees all resources used by a buffer chain.
1604
1605 =cut
1606 */
1607
1608 static void
1609 io_destroy_bufchain(io_ex_bchain *ieb) {
1610   io_blink *cp;
1611 #if 0
1612   mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1613 #endif
1614   cp = ieb->head;
1615   
1616   while(cp) {
1617     io_blink *t = cp->next;
1618     myfree(cp);
1619     cp = t;
1620   }
1621 }
1622
1623
1624
1625
1626 /*
1627
1628 static
1629 void
1630 bufchain_dump(io_ex_bchain *ieb) {
1631   mm_log((1, "  buf_chain_dump(ieb %p)\n"));
1632   mm_log((1, "  buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1633   mm_log((1, "  buf_chain_dump: ieb->length = %d\n", ieb->length));
1634   mm_log((1, "  buf_chain_dump: ieb->head   = %p\n", ieb->head  ));
1635   mm_log((1, "  buf_chain_dump: ieb->tail   = %p\n", ieb->tail  ));
1636   mm_log((1, "  buf_chain_dump: ieb->tfill  = %d\n", ieb->tfill ));
1637   mm_log((1, "  buf_chain_dump: ieb->cp     = %p\n", ieb->cp    ));
1638   mm_log((1, "  buf_chain_dump: ieb->cpos   = %d\n", ieb->cpos  ));
1639   mm_log((1, "  buf_chain_dump: ieb->gpos   = %d\n", ieb->gpos  ));
1640 }
1641 */
1642
1643 /*
1644  * TRUE if lengths are NOT equal
1645  */
1646
1647 /*
1648 static
1649 void
1650 chainlencert( io_glue *ig ) {
1651   int clen;
1652   int cfl           = 0;
1653   size_t csize      = 0;
1654   size_t cpos       = 0;
1655   io_ex_bchain *ieb = ig->exdata;
1656   io_blink *cp      = ieb->head;
1657   
1658
1659   if (ieb->gpos > ieb->length) mm_log((1, "BBAR : ieb->gpos = %d, ieb->length = %d\n", ieb->gpos, ieb->length));
1660
1661   while(cp) {
1662     clen = (cp == ieb->tail) ? ieb->tfill : cp->len;
1663     if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1664     if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1665     
1666     if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1667     if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1668     
1669     if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1670     if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1671
1672     if (cp == ieb->cp) {
1673       cfl = 1;
1674       cpos += ieb->cpos;
1675     }
1676
1677     if (!cfl) cpos += clen;
1678
1679     csize += clen;
1680     cp     = cp->next;
1681   }
1682   if (( csize != ieb->length )) mm_log((1, "BAR : csize = %d, ieb->length = %d\n", csize, ieb->length));
1683   if (( cpos  != ieb->gpos   )) mm_log((1, "BAR : cpos  = %d, ieb->gpos   = %d\n", cpos,  ieb->gpos  ));
1684 }
1685
1686
1687 static
1688 void
1689 chaincert( io_glue *ig) {
1690   size_t csize   = 0;
1691   io_ex_bchain *ieb = ig->exdata;
1692   io_blink *cp   = ieb->head;
1693   
1694   mm_log((1, "Chain verification.\n"));
1695
1696   mm_log((1, "  buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1697   mm_log((1, "  buf_chain_dump: ieb->length = %d\n", ieb->length));
1698   mm_log((1, "  buf_chain_dump: ieb->head   = %p\n", ieb->head  ));
1699   mm_log((1, "  buf_chain_dump: ieb->tail   = %p\n", ieb->tail  ));
1700   mm_log((1, "  buf_chain_dump: ieb->tfill  = %d\n", ieb->tfill ));
1701   mm_log((1, "  buf_chain_dump: ieb->cp     = %p\n", ieb->cp    ));
1702   mm_log((1, "  buf_chain_dump: ieb->cpos   = %d\n", ieb->cpos  ));
1703   mm_log((1, "  buf_chain_dump: ieb->gpos   = %d\n", ieb->gpos  ));
1704
1705   while(cp) {
1706     int clen = cp == ieb->tail ? ieb->tfill : cp->len;
1707     mm_log((1, "link: %p <- %p -> %p\n", cp->prev, cp, cp->next));
1708     if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1709     if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1710     
1711     if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1712     if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1713     
1714     if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1715     if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1716
1717     csize += clen;
1718     cp     = cp->next;
1719   }
1720
1721   mm_log((1, "csize = %d %s ieb->length = %d\n", csize, csize == ieb->length ? "==" : "!=", ieb->length));
1722 }
1723 */
1724
1725 /*
1726 =item bufchain_read(ig, buf, count)
1727
1728 Does the reading from a source that can be seeked on
1729
1730    ig    - io_glue object
1731    buf   - buffer to return data in
1732    count - number of bytes to read into buffer max
1733
1734 =cut
1735 */
1736
1737 static
1738 ssize_t 
1739 bufchain_read(io_glue *ig, void *buf, size_t count) {
1740   io_ex_bchain *ieb = ig->exdata;
1741   size_t     scount = count;
1742   char        *cbuf = buf;
1743   size_t         sk;
1744   dIMCTXio(ig);
1745
1746   im_log((aIMCTX, 1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1747
1748   while( scount ) {
1749     int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1750     if (clen == ieb->cpos) {
1751       if (ieb->cp == ieb->tail) break; /* EOF */
1752       ieb->cp = ieb->cp->next;
1753       ieb->cpos = 0;
1754       clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1755     }
1756
1757     sk = clen - ieb->cpos;
1758     sk = sk > scount ? scount : sk;
1759
1760     memcpy(&cbuf[count-scount], &ieb->cp->buf[ieb->cpos], sk);
1761     scount    -= sk;
1762     ieb->cpos += sk;
1763     ieb->gpos += sk;
1764   }
1765
1766   im_log((aIMCTX, 1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1767   return count-scount;
1768 }
1769
1770
1771
1772
1773
1774 /*
1775 =item bufchain_write(ig, buf, count)
1776
1777 Does the writing to a 'source' that can be seeked on
1778
1779    ig    - io_glue object
1780    buf   - buffer that contains data
1781    count - number of bytes to write
1782
1783 =cut
1784 */
1785
1786 static
1787 ssize_t
1788 bufchain_write(io_glue *ig, const void *buf, size_t count) {
1789   char *cbuf = (char *)buf;
1790   io_ex_bchain *ieb = ig->exdata;
1791   size_t         ocount = count;
1792   size_t         sk;
1793   dIMCTXio(ig);
1794
1795   im_log((aIMCTX, 1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
1796
1797   IOL_DEB( fprintf(IOL_DEBs, "bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %ld\n", ig, (long) ieb->cpos, buf, (long)count) );
1798   
1799   while(count) {
1800     im_log((aIMCTX, 2, "bufchain_write: - looping - count = %ld\n", (long)count));
1801     if (ieb->cp->len == ieb->cpos) {
1802       im_log((aIMCTX, 1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1803       io_bchain_advance(ieb);
1804     }
1805
1806     sk = ieb->cp->len - ieb->cpos;
1807     sk = sk > count ? count : sk;
1808     memcpy(&ieb->cp->buf[ieb->cpos], &cbuf[ocount-count], sk);
1809
1810     if (ieb->cp == ieb->tail) {
1811       int extend = ieb->cpos + sk - ieb->tfill;
1812       im_log((aIMCTX, 2, "bufchain_write: extending tail by %d\n", extend));
1813       if (extend > 0) {
1814         ieb->length += extend;
1815         ieb->tfill  += extend;
1816       }
1817     }
1818
1819     ieb->cpos += sk;
1820     ieb->gpos += sk;
1821     count     -= sk;
1822   }
1823   return ocount;
1824 }
1825
1826 /*
1827 =item bufchain_close(ig)
1828
1829 Closes a source that can be seeked on.  Not sure if this should be an actual close
1830 or not.  Does nothing for now.  Should be fixed.
1831
1832    ig - data source
1833
1834 =cut
1835 */
1836
1837 static
1838 int
1839 bufchain_close(io_glue *ig) {
1840   dIMCTXio(ig);
1841   im_log((aIMCTX, 1, "bufchain_close(ig %p)\n",ig));
1842   IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
1843
1844   return 0;  
1845 }
1846
1847
1848 /*
1849 =item bufchain_seek(ig, offset, whence)
1850
1851 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1852 have an offset into a file that is different from what the underlying library thinks.
1853
1854    ig     - data source
1855    offset - offset into stream
1856    whence - whence argument a la lseek
1857
1858 =cut
1859 */
1860
1861 static
1862 off_t
1863 bufchain_seek(io_glue *ig, off_t offset, int whence) {
1864   io_ex_bchain *ieb = ig->exdata;
1865   int wrlen;
1866
1867   off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence);
1868   off_t sk;
1869   dIMCTXio(ig);
1870
1871   im_log((aIMCTX, 1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
1872
1873   if (scount < 0) {
1874     i_push_error(0, "invalid whence supplied or seek before start of file");
1875     return (off_t)-1;
1876   }
1877
1878   ieb->cp   = ieb->head;
1879   ieb->cpos = 0;
1880   ieb->gpos = 0;
1881   
1882   while( scount ) {
1883     int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1884     if (clen == ieb->cpos) {
1885       if (ieb->cp == ieb->tail) break; /* EOF */
1886       ieb->cp = ieb->cp->next;
1887       ieb->cpos = 0;
1888       clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1889     }
1890     
1891     sk = clen - ieb->cpos;
1892     sk = sk > scount ? scount : sk;
1893     
1894     scount    -= sk;
1895     ieb->cpos += sk;
1896     ieb->gpos += sk;
1897   }
1898   
1899   wrlen = scount;
1900
1901   if (wrlen > 0) { 
1902     /*
1903      * extending file - get ieb into consistent state and then
1904      * call write which will get it to the correct position 
1905      */
1906     char TB[BBSIZ];
1907     memset(TB, 0, BBSIZ);
1908     ieb->gpos = ieb->length;
1909     ieb->cpos = ieb->tfill;
1910     
1911     while(wrlen > 0) {
1912       ssize_t rc, wl = i_min(wrlen, BBSIZ);
1913       im_log((aIMCTX, 1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl));
1914       rc = bufchain_write( ig, TB, wl );
1915       if (rc != wl) im_fatal(aIMCTX, 0, "bufchain_seek: Unable to extend file\n");
1916       wrlen -= rc;
1917     }
1918   }
1919
1920   im_log((aIMCTX, 2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
1921   return ieb->gpos;
1922 }
1923
1924 static
1925 void
1926 bufchain_destroy(io_glue *ig) {
1927   io_ex_bchain *ieb = ig->exdata;
1928
1929   io_destroy_bufchain(ieb);
1930
1931   myfree(ieb);
1932 }
1933
1934 /*
1935 =item fd_read(ig, buf, count)
1936
1937 Read callback for file descriptor IO objects.
1938
1939 =cut
1940 */
1941 static ssize_t fd_read(io_glue *igo, void *buf, size_t count) {
1942   io_fdseek *ig = (io_fdseek *)igo;
1943   ssize_t result;
1944 #ifdef _MSC_VER
1945   result = _read(ig->fd, buf, count);
1946 #else
1947   result = read(ig->fd, buf, count);
1948 #endif
1949
1950   IOL_DEB(fprintf(IOL_DEBs, "fd_read(%p, %p, %u) => %d\n", ig, buf,
1951                   (unsigned)count, (int)result));
1952
1953   /* 0 is valid - means EOF */
1954   if (result < 0) {
1955     dIMCTXio(igo);
1956     im_push_errorf(aIMCTX, 0, "read() failure: %s (%d)", my_strerror(errno), errno);
1957   }
1958
1959   return result;
1960 }
1961
1962 static ssize_t fd_write(io_glue *igo, const void *buf, size_t count) {
1963   io_fdseek *ig = (io_fdseek *)igo;
1964   ssize_t result;
1965 #ifdef _MSC_VER
1966   result = _write(ig->fd, buf, count);
1967 #else
1968   result = write(ig->fd, buf, count);
1969 #endif
1970
1971   IOL_DEB(fprintf(IOL_DEBs, "fd_write(%p, %p, %u) => %d\n", ig, buf,
1972                   (unsigned)count, (int)result));
1973
1974   if (result <= 0) {
1975     dIMCTXio(igo);
1976     im_push_errorf(aIMCTX, errno, "write() failure: %s (%d)", my_strerror(errno), errno);
1977   }
1978
1979   return result;
1980 }
1981
1982 static off_t fd_seek(io_glue *igo, off_t offset, int whence) {
1983   io_fdseek *ig = (io_fdseek *)igo;
1984   off_t result;
1985 #ifdef _MSC_VER
1986   result = _lseek(ig->fd, offset, whence);
1987 #else
1988   result = lseek(ig->fd, offset, whence);
1989 #endif
1990
1991   if (result == (off_t)-1) {
1992     dIMCTXio(igo);
1993     im_push_errorf(aIMCTX, errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
1994   }
1995
1996   return result;
1997 }
1998
1999 static int fd_close(io_glue *ig) {
2000   /* no, we don't close it */
2001   return 0;
2002 }
2003
2004 static ssize_t fd_size(io_glue *ig) {
2005   dIMCTXio(ig);
2006   im_log((aIMCTX, 1, "fd_size(ig %p) unimplemented\n", ig));
2007   
2008   return -1;
2009 }
2010
2011
2012 /*
2013 =back
2014
2015 =head1 AUTHOR
2016
2017 Arnar M. Hrafnkelsson <addi@umich.edu>
2018
2019 =head1 SEE ALSO
2020
2021 Imager(3)
2022
2023 =cut
2024 */