tagged release 0.6.4
[parrot.git] / src / io / io_buf.c
blobd4901974cd3a998bde4cb14d01330f8274479acc
1 /*
2 Copyright (C) 2001-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/io/io_buf.c - IO buffer layer
9 =head1 DESCRIPTION
11 The "buf" layer of Parrot IO. Buffering and all the fun stuff.
13 =head2 Functions
15 =over 4
17 =cut
21 #include "parrot/parrot.h"
22 #include "io_private.h"
24 /* HEADERIZER HFILE: none */
25 /* HEADERIZER BEGIN: static */
26 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
28 static INTVAL PIO_buf_close(PARROT_INTERP,
29 ARGIN_NULLOK(ParrotIOLayer *layer),
30 ARGMOD(ParrotIO *io))
31 __attribute__nonnull__(1)
32 __attribute__nonnull__(3)
33 FUNC_MODIFIES(*io);
35 PARROT_CAN_RETURN_NULL
36 PARROT_WARN_UNUSED_RESULT
37 static ParrotIO * PIO_buf_fdopen(PARROT_INTERP,
38 ARGIN_NULLOK(ParrotIOLayer *layer),
39 PIOHANDLE fd,
40 INTVAL flags)
41 __attribute__nonnull__(1);
43 static size_t PIO_buf_fill_readbuf(PARROT_INTERP,
44 ARGIN_NULLOK(ParrotIOLayer *layer),
45 ARGMOD(ParrotIO *io),
46 ARGMOD(ParrotIOBuf *b))
47 __attribute__nonnull__(1)
48 __attribute__nonnull__(3)
49 __attribute__nonnull__(4)
50 FUNC_MODIFIES(*io)
51 FUNC_MODIFIES(*b);
53 static INTVAL PIO_buf_flush(PARROT_INTERP,
54 ARGIN_NULLOK(ParrotIOLayer *layer),
55 ARGMOD(ParrotIO *io))
56 __attribute__nonnull__(1)
57 __attribute__nonnull__(3)
58 FUNC_MODIFIES(*io);
60 static INTVAL PIO_buf_init(PARROT_INTERP, ARGMOD(ParrotIOLayer *layer))
61 __attribute__nonnull__(1)
62 __attribute__nonnull__(2)
63 FUNC_MODIFIES(*layer);
65 PARROT_CAN_RETURN_NULL
66 static ParrotIO * PIO_buf_open(PARROT_INTERP,
67 ARGMOD(ParrotIOLayer *layer),
68 ARGIN(const char *path),
69 INTVAL flags)
70 __attribute__nonnull__(1)
71 __attribute__nonnull__(2)
72 __attribute__nonnull__(3)
73 FUNC_MODIFIES(*layer);
75 static size_t PIO_buf_peek(PARROT_INTERP,
76 ARGIN_NULLOK(ParrotIOLayer *layer),
77 ARGMOD(ParrotIO *io),
78 ARGOUT(STRING **buf))
79 __attribute__nonnull__(1)
80 __attribute__nonnull__(3)
81 __attribute__nonnull__(4)
82 FUNC_MODIFIES(*io)
83 FUNC_MODIFIES(*buf);
85 static size_t PIO_buf_read(PARROT_INTERP,
86 ARGIN_NULLOK(ParrotIOLayer *layer),
87 ARGMOD(ParrotIO *io),
88 ARGOUT(STRING **buf))
89 __attribute__nonnull__(1)
90 __attribute__nonnull__(3)
91 __attribute__nonnull__(4)
92 FUNC_MODIFIES(*io)
93 FUNC_MODIFIES(*buf);
95 static size_t PIO_buf_readline(PARROT_INTERP,
96 ARGIN_NULLOK(ParrotIOLayer *layer),
97 ARGMOD(ParrotIO *io),
98 ARGOUT(STRING **buf))
99 __attribute__nonnull__(1)
100 __attribute__nonnull__(3)
101 __attribute__nonnull__(4)
102 FUNC_MODIFIES(*io)
103 FUNC_MODIFIES(*buf);
105 static PIOOFF_T PIO_buf_seek(PARROT_INTERP,
106 ARGIN_NULLOK(ParrotIOLayer *l),
107 ARGMOD(ParrotIO *io),
108 PIOOFF_T offset,
109 INTVAL whence)
110 __attribute__nonnull__(1)
111 __attribute__nonnull__(3)
112 FUNC_MODIFIES(*io);
114 static INTVAL PIO_buf_setbuf(PARROT_INTERP,
115 ARGIN_NULLOK(ParrotIOLayer *layer),
116 ARGMOD(ParrotIO *io),
117 size_t bufsize)
118 __attribute__nonnull__(1)
119 __attribute__nonnull__(3)
120 FUNC_MODIFIES(*io);
122 static INTVAL PIO_buf_setlinebuf(PARROT_INTERP,
123 ARGIN_NULLOK(ParrotIOLayer *layer),
124 ARGMOD(ParrotIO *io))
125 __attribute__nonnull__(1)
126 __attribute__nonnull__(3)
127 FUNC_MODIFIES(*io);
129 static PIOOFF_T PIO_buf_tell(SHIM_INTERP,
130 SHIM(ParrotIOLayer *layer),
131 ARGIN(ParrotIO *io))
132 __attribute__nonnull__(3);
134 static size_t PIO_buf_write(PARROT_INTERP,
135 ARGMOD(ParrotIOLayer *layer),
136 ARGMOD(ParrotIO *io),
137 ARGIN(STRING *s))
138 __attribute__nonnull__(1)
139 __attribute__nonnull__(2)
140 __attribute__nonnull__(3)
141 __attribute__nonnull__(4)
142 FUNC_MODIFIES(*layer)
143 FUNC_MODIFIES(*io);
145 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
146 /* HEADERIZER END: static */
148 /* Defined at bottom */
149 extern const ParrotIOLayerAPI pio_buf_layer_api;
151 ParrotIOLayer pio_buf_layer = {
152 NULL,
153 "buf",
154 PIO_L_TERMINAL,
155 &pio_buf_layer_api,
156 0, 0
160 /* XXX: This is not portable */
161 #define DEFAULT_RECSEP '\n'
162 #define IS_EOL(io, c) ((io)->recsep == (*(c)))
164 #define IS_EOL(io, c) ((*(c)) == '\n')
170 =item C<static INTVAL PIO_buf_init>
172 The buffer layer's C<Init> function. Initializes buffering.
174 =cut
178 static INTVAL
179 PIO_buf_init(PARROT_INTERP, ARGMOD(ParrotIOLayer *layer))
181 if (PIO_STDOUT(interp))
182 PIO_buf_setlinebuf(interp, layer,
183 PMC_data_typed(PIO_STDOUT(interp), ParrotIO *));
185 if (PIO_STDIN(interp))
186 PIO_buf_setbuf(interp, layer,
187 PMC_data_typed(PIO_STDIN(interp), ParrotIO *), PIO_UNBOUND);
189 return 0;
194 =item C<static ParrotIO * PIO_buf_open>
196 The buffer layer's C<Open> function.
198 =cut
202 PARROT_CAN_RETURN_NULL
203 static ParrotIO *
204 PIO_buf_open(PARROT_INTERP, ARGMOD(ParrotIOLayer *layer),
205 ARGIN(const char *path), INTVAL flags)
207 ParrotIOLayer * const l = PIO_DOWNLAYER(layer);
208 ParrotIO * const io = PIO_open_down(interp, l, path, flags);
209 if (!io) {
210 /* error creating IO stream */
211 return NULL;
214 * We have an IO stream. Now setup stuff
215 * for our layer before returning it.
216 * XXX: Make default behaviour linebuffered?
218 /*PIO_buf_setlinebuf(interp, l, io);*/
219 PIO_buf_setbuf(interp, l, io, PIO_UNBOUND);
220 return io;
225 =item C<static INTVAL PIO_buf_setbuf>
227 The buffer layer's C<SetBuf> function.
229 Don't pass C<SetBuf> calls down the stack, top layer wins. This doesn't
230 mean other layers can't buffer, I just need to think about the mechanism
231 for buffer control or if it even makes sense this way. Most layers will
232 not implement C<SetBuf>.
234 =cut
238 static INTVAL
239 PIO_buf_setbuf(PARROT_INTERP, ARGIN_NULLOK(ParrotIOLayer *layer),
240 ARGMOD(ParrotIO *io), size_t bufsize)
242 ParrotIOLayer * const l = layer ? layer : io->stack;
243 ParrotIOBuf * const b = &io->b;
245 /* If there is a buffer, make sure we flush before
246 * dinking around with the buffer.
248 if (b->startb)
249 PIO_buf_flush(interp, l, io);
251 /* Choose an appropriate buffer size for caller */
252 switch (bufsize) {
253 case 0:
254 b->size = 0;
255 break;
256 case PIO_UNBOUND:
257 b->size = PIO_getblksize(io->fd);
258 break;
259 default:
260 b->size = (bufsize >= PIO_GRAIN ? bufsize : PIO_GRAIN);
261 break;
264 if (b->startb && (b->flags & PIO_BF_MALLOC)) {
265 mem_sys_free(b->startb);
266 b->startb = b->next = NULL;
269 if (b->size > 0) {
270 b->startb = b->next = (unsigned char *)mem_sys_allocate(b->size);
271 b->flags |= PIO_BF_MALLOC;
273 else
274 b->flags &= ~PIO_BF_MALLOC;
276 if (b->size != 0) {
277 io->flags &= ~PIO_F_LINEBUF;
278 io->flags |= PIO_F_BLKBUF;
280 else
281 io->flags &= ~(PIO_F_BLKBUF | PIO_F_LINEBUF);
283 return 0;
288 =item C<static INTVAL PIO_buf_setlinebuf>
290 The buffer layer's C<SetLineBuf> function.
292 =cut
296 static INTVAL
297 PIO_buf_setlinebuf(PARROT_INTERP, ARGIN_NULLOK(ParrotIOLayer *layer),
298 ARGMOD(ParrotIO *io))
300 int err;
301 ParrotIOLayer * const l = layer ? layer : io->stack;
303 /* already linebuffering */
304 if (io->flags & PIO_F_LINEBUF)
305 return 0;
307 /* Reuse setbuf call */
308 if ((err = PIO_buf_setbuf(interp, l, io, PIO_LINEBUFSIZE)) >= 0) {
309 /* Then switch to linebuf */
310 io->flags &= ~PIO_F_BLKBUF;
311 io->flags |= PIO_F_LINEBUF;
312 io->recsep = DEFAULT_RECSEP;
313 return 0;
315 return err;
320 =item C<static ParrotIO * PIO_buf_fdopen>
322 The buffer layer's C<FDOpen> function.
324 =cut
328 PARROT_CAN_RETURN_NULL
329 PARROT_WARN_UNUSED_RESULT
330 static ParrotIO *
331 PIO_buf_fdopen(PARROT_INTERP, ARGIN_NULLOK(ParrotIOLayer *layer), PIOHANDLE fd, INTVAL flags)
333 ParrotIOLayer * const l = PIO_DOWNLAYER(layer);
334 ParrotIO * const io = PIO_fdopen_down(interp, l, fd, flags);
336 if (io) {
337 if (io->flags & PIO_F_CONSOLE)
338 PIO_buf_setlinebuf(interp, l, io);
339 else
340 PIO_buf_setbuf(interp, l, io, PIO_UNBOUND);
343 return io;
348 =item C<static INTVAL PIO_buf_close>
350 The buffer layer's C<Close> function.
352 =cut
356 static INTVAL
357 PIO_buf_close(PARROT_INTERP, ARGIN_NULLOK(ParrotIOLayer *layer), ARGMOD(ParrotIO *io))
359 ParrotIOLayer * const l = PIO_DOWNLAYER(layer);
360 PIO_buf_flush(interp, layer, io);
362 return PIO_close_down(interp, l, io);
367 =item C<static INTVAL PIO_buf_flush>
369 The buffer layer's C<Flush> function.
371 =cut
375 static INTVAL
376 PIO_buf_flush(PARROT_INTERP, ARGIN_NULLOK(ParrotIOLayer *layer), ARGMOD(ParrotIO *io))
378 long wrote;
379 size_t to_write;
380 STRING fake;
382 * Either buffering is null, disabled, or empty.
384 if (!io->b.startb
385 || (io->flags & (PIO_F_BLKBUF | PIO_F_LINEBUF)) == 0
386 || (io->b.flags & (PIO_BF_WRITEBUF | PIO_BF_READBUF)) == 0)
387 return 0;
389 * Write flush
391 if (io->b.flags & PIO_BF_WRITEBUF) {
392 ParrotIOLayer * const l = layer;
393 to_write = io->b.next - io->b.startb;
395 /* Flush to next layer */
396 fake.strstart = (char *)io->b.startb;
397 fake.bufused = to_write;
398 wrote = PIO_write_down(interp, PIO_DOWNLAYER(l), io, &fake);
399 if (wrote == (long)to_write) {
400 io->b.next = io->b.startb;
401 /* Release buffer */
402 io->b.flags &= ~PIO_BF_WRITEBUF;
403 return 0;
405 else {
406 /* FIXME: I/O Error */
410 * Read flush
412 else if (io->b.flags & PIO_BF_READBUF) {
413 io->b.flags &= ~PIO_BF_READBUF;
414 io->b.next = io->b.startb;
416 return -1;
421 =item C<static size_t PIO_buf_fill_readbuf>
423 The buffer layer's C<Fill> function.
425 =cut
429 static size_t
430 PIO_buf_fill_readbuf(PARROT_INTERP, ARGIN_NULLOK(ParrotIOLayer *layer),
431 ARGMOD(ParrotIO *io), ARGMOD(ParrotIOBuf *b))
433 size_t got;
434 PIOOFF_T pos = io->fpos;
435 STRING fake, *s;
436 fake.strstart = (char *)b->startb;
437 fake.bufused = b->size;
438 s = &fake;
440 got = PIO_read_down(interp, PIO_DOWNLAYER(layer),
441 io, &s);
442 /* buffer-filling does not change fileposition */
443 io->fpos = pos;
445 /* nothing to get */
446 if (got == 0)
447 return 0;
449 b->endb = b->startb + got;
450 b->next = b->startb;
452 b->flags |= PIO_BF_READBUF;
454 return got;
459 =item C<static size_t PIO_buf_read>
461 The buffer layer's C<Read> function.
463 =cut
467 static size_t
468 PIO_buf_read(PARROT_INTERP, ARGIN_NULLOK(ParrotIOLayer *layer),
469 ARGMOD(ParrotIO *io), ARGOUT(STRING **buf))
471 ParrotIOLayer *l = layer;
472 ParrotIOBuf *b;
473 unsigned char *out_buf;
474 STRING *s;
475 size_t len;
476 size_t current = 0;
478 /* write buffer flush */
479 if (io->b.flags & PIO_BF_WRITEBUF) {
480 PIO_buf_flush(interp, layer, io);
483 b = &io->b;
485 /* line buffered read */
486 if (io->flags & PIO_F_LINEBUF) {
487 return PIO_buf_readline(interp, layer, io, buf);
490 if (*buf == NULL) {
491 *buf = new_string_header(interp, 0);
492 (*buf)->bufused = len = 2048;
494 s = *buf;
495 len = s->bufused;
496 if (!s->strstart) {
497 Parrot_allocate_string(interp, s, len);
499 out_buf = (unsigned char *)s->strstart;
500 /* read Data from buffer */
501 if (b->flags & PIO_BF_READBUF) {
502 const size_t avail = b->endb - b->next;
504 current = avail < len ? avail : len;
505 memcpy(out_buf, b->next, current);
506 b->next += current;
507 io->fpos += current;
509 /* buffer completed */
510 if (current == avail) {
511 io->b.flags &= ~PIO_BF_READBUF;
512 /* XXX: Is the reset of next and endb really necessary ? */
513 io->b.endb = NULL;
514 io->b.next = io->b.startb;
517 if (len == current) {
518 s->strlen = s->bufused = len;
519 return current;
521 else {
522 /* more data needed from downlayer */
523 out_buf += current;
524 len -= current;
528 /* (re)fill the readbuffer */
529 if (!(b->flags & PIO_BF_READBUF)) {
530 size_t got;
531 if (len >= io->b.size) {
532 STRING fake;
533 STRING *sf = &fake;
535 fake.strstart = (char *)out_buf;
536 fake.bufused = len;
537 got = PIO_read_down(interp, PIO_DOWNLAYER(l), io, &sf);
538 s->strlen = s->bufused = current + got;
539 io->fpos += got;
540 return current + got;
543 got = PIO_buf_fill_readbuf(interp, l, io, b);
545 len = len < got ? len : got;
548 /* read from the read_buffer */
549 memcpy(out_buf, io->b.next, len);
550 s->strlen = s->bufused = current + len;
551 io->b.next += len;
552 io->fpos += len;
554 /* is the buffer is completely empty ? */
555 if (io->b.next == io->b.endb) {
556 io->b.flags &= ~PIO_BF_READBUF;
557 /* XXX: Is the reset of next and encb really necessary ? */
558 io->b.endb = NULL;
559 io->b.next = io->b.startb;
561 return current + len;
566 =item C<static size_t PIO_buf_peek>
568 RT#48260: Not yet documented!!!
570 =cut
574 static size_t
575 PIO_buf_peek(PARROT_INTERP, ARGIN_NULLOK(ParrotIOLayer *layer),
576 ARGMOD(ParrotIO *io), ARGOUT(STRING **buf))
578 ParrotIOLayer *l = layer;
579 ParrotIOBuf *b;
580 size_t len = 1;
581 size_t avail = 0;
583 STRING * const s = PIO_make_io_string(interp, buf, 1);
585 /* write buffer flush */
586 if (io->b.flags & PIO_BF_WRITEBUF) {
587 PIO_buf_flush(interp, layer, io);
590 b = &io->b;
592 /* read Data from buffer */
593 if (b->flags & PIO_BF_READBUF) {
594 avail = b->endb - b->next;
596 /* if we have data available, copy out the next byte */
597 if (avail) {
598 ret_string:
599 memcpy(s->strstart, b->next, len);
600 s->bufused = s->strlen = len;
601 return len;
605 /* (re)fill the buffer */
606 if (! (b->flags & PIO_BF_READBUF)) {
607 size_t got;
608 /* exception if we're unbuffered */
609 if (io->b.size == 0)
610 real_exception(interp, NULL, PIO_ERROR, "Can't peek at unbuffered PIO");
612 got = PIO_buf_fill_readbuf(interp, l, io, b);
613 len = (len < got) ? len : got;
616 /* if we got any data, then copy out the next byte */
617 goto ret_string;
622 =item C<static size_t PIO_buf_readline>
624 This is called from C<PIO_buf_read()> to do line buffered reading if
625 that is what is required.
627 =cut
631 static size_t
632 PIO_buf_readline(PARROT_INTERP, ARGIN_NULLOK(ParrotIOLayer *layer),
633 ARGMOD(ParrotIO *io), ARGOUT(STRING **buf))
635 size_t l;
636 unsigned char *out_buf;
637 unsigned char *buf_start;
638 ParrotIOBuf * const b = &io->b;
639 size_t len;
640 STRING *s;
642 if (*buf == NULL) {
643 *buf = new_string_header(interp, 0);
645 s = *buf;
646 s->strlen = 0;
648 /* fill empty buffer */
649 if (!(b->flags & PIO_BF_READBUF)) {
650 if (PIO_buf_fill_readbuf(interp, layer, io, b) == 0)
651 return 0;
654 buf_start = b->next;
655 for (l = 0; b->next < b->endb;) {
656 l++;
657 if (IS_EOL(io, b->next++)) {
658 break;
660 /* if there is a buffer, readline is called by the read opcode
661 * - return just that part
663 if (s->bufused && l == s->bufused)
664 break;
665 /* buffer completed; copy out and refill */
666 if (b->next == b->endb) {
667 len = b->endb - buf_start;
668 if (s->bufused < l) {
669 if (s->strstart) {
670 Parrot_reallocate_string(interp, s, l);
672 else {
673 Parrot_allocate_string(interp, s, l);
676 out_buf = (unsigned char*)s->strstart + s->strlen;
677 memcpy(out_buf, buf_start, len);
678 s->strlen = s->bufused = l;
679 if (PIO_buf_fill_readbuf(interp, layer, io, b) == 0)
680 return l;
681 buf_start = b->startb;
684 if (s->bufused < l) {
685 if (s->strstart) {
686 Parrot_reallocate_string(interp, s, l);
688 else {
689 Parrot_allocate_string(interp, s, l);
692 out_buf = (unsigned char*)s->strstart + s->strlen;
693 len = b->next - buf_start;
694 memcpy(out_buf, buf_start, len);
695 s->strlen = s->bufused = l;
697 /* check if buffer is finished */
698 if (b->next == b->endb) {
699 b->next = b->startb;
700 b->endb = NULL;
701 b->flags &= ~PIO_BF_READBUF;
704 return l;
709 =item C<static size_t PIO_buf_write>
711 The buffer layer's C<Write> function.
713 =cut
717 static size_t
718 PIO_buf_write(PARROT_INTERP, ARGMOD(ParrotIOLayer *layer),
719 ARGMOD(ParrotIO *io), ARGIN(STRING *s))
721 size_t avail;
722 void * const buffer = s->strstart;
723 size_t len = s->bufused;
724 int need_flush;
726 if (len <= 0)
727 return 0;
728 if (io->b.flags & PIO_BF_WRITEBUF) {
729 avail = io->b.size - (io->b.next - io->b.startb);
731 else if (io->b.flags & PIO_BF_READBUF) {
732 io->b.flags &= ~PIO_BF_READBUF;
733 io->b.next = io->b.startb;
734 avail = io->b.size;
736 else {
737 avail = io->b.size;
739 /* If we are line buffered, check for newlines.
740 * If any, we should flush
742 need_flush = 0;
743 if (io->flags & PIO_F_LINEBUF) {
744 /* scan from end, it's likely that EOL is at end of string */
745 const char *p = (char*)buffer + len - 1;
746 size_t i;
747 for (i = 0; i < len; ++i, --p)
748 if (IS_EOL(io, p)) {
749 need_flush = 1;
750 break;
755 * Large writes (multiples of blocksize) should write
756 * through generally for best performance, else you are
757 * just doing extra memcpys.
758 * FIXME: This is badly optimized, will fixup later.
760 if (need_flush || len >= io->b.size) {
761 long wrote;
762 /* Write through, skip buffer. */
763 PIO_buf_flush(interp, layer, io);
764 wrote = PIO_write_down(interp, PIO_DOWNLAYER(layer), io, s);
765 if (wrote == (long)len) {
766 io->fpos += wrote;
767 return wrote;
769 else {
770 return (size_t)-1; /* Write error */
773 else if (avail > len) {
774 io->b.flags |= PIO_BF_WRITEBUF;
775 memcpy(io->b.next, buffer, len);
776 io->b.next += len;
777 io->fpos += len;
778 return len;
780 else {
781 const unsigned int diff = (int)(len - avail);
783 io->b.flags |= PIO_BF_WRITEBUF;
784 /* Fill remainder, flush, then try to buffer more */
785 memcpy(io->b.next, buffer, avail);
786 io->b.next += avail;
787 io->fpos += avail;
788 PIO_buf_flush(interp, layer, io);
789 memcpy(io->b.startb, ((const char *)buffer + avail), diff);
790 io->b.next += diff;
791 io->fpos += diff;
792 return len;
798 =item C<static PIOOFF_T PIO_buf_seek>
800 The buffer layer's C<Seek> function.
802 =cut
806 static PIOOFF_T
807 PIO_buf_seek(PARROT_INTERP, ARGIN_NULLOK(ParrotIOLayer *l),
808 ARGMOD(ParrotIO *io), PIOOFF_T offset, INTVAL whence)
810 PIOOFF_T newpos;
812 switch (whence) {
813 case SEEK_SET:
814 newpos = offset;
815 break;
816 case SEEK_CUR:
817 newpos = io->fpos + offset;
818 break;
819 case SEEK_END:
820 newpos = PIO_seek_down(interp, PIO_DOWNLAYER(l), io, offset,
821 whence);
822 if (newpos == -1)
823 return -1;
825 break;
826 default:
827 /* XXX: somehow report the illegal whence value */
828 return -1;
831 if ((newpos < io->fpos - (io->b.next - io->b.startb))
832 || (newpos >= io->fpos + (io->b.endb - io->b.next))) {
833 PIO_buf_flush(interp, l, io);
834 newpos = PIO_seek_down(interp, PIO_DOWNLAYER(l), io, newpos, SEEK_SET);
836 else {
837 io->b.next += newpos - io->fpos;
840 io->lpos = io->fpos;
841 io->fpos = newpos;
843 return io->fpos;
848 =item C<static PIOOFF_T PIO_buf_tell>
850 The buffer layer's C<Tell> function.
852 =cut
856 static PIOOFF_T
857 PIO_buf_tell(SHIM_INTERP, SHIM(ParrotIOLayer *layer), ARGIN(ParrotIO *io))
859 return io->fpos;
862 const ParrotIOLayerAPI pio_buf_layer_api = {
863 PIO_buf_init,
864 PIO_base_new_layer,
865 PIO_base_delete_layer,
866 PIO_null_push_layer,
867 PIO_null_pop_layer,
868 PIO_buf_open,
869 PIO_null_open2,
870 PIO_null_open3,
871 PIO_null_open_async,
872 PIO_buf_fdopen,
873 PIO_buf_close,
874 PIO_buf_write,
875 PIO_null_write_async,
876 PIO_buf_read,
877 PIO_null_read_async,
878 PIO_buf_flush,
879 PIO_buf_peek,
880 PIO_buf_seek,
881 PIO_buf_tell,
882 PIO_buf_setbuf,
883 PIO_buf_setlinebuf,
884 PIO_null_getcount,
885 PIO_null_fill,
886 PIO_null_eof,
887 0, /* no poll */
888 0, /* no socket */
889 0, /* no connect */
890 0, /* no send */
891 0, /* no recv */
892 0, /* no bind */
893 0, /* no listen */
894 0 /* no accept */
899 =back
901 =head1 SEE ALSO
903 F<src/io/io_passdown.c>,
904 F<src/io/io_stdio.c>,
905 F<src/io/io_unix.c>,
906 F<src/io/io_win32.c>,
907 F<src/io/io.c>,
908 F<src/io/io_private.h>.
910 =head1 HISTORY
912 Initially written by Melvin Smith.
914 Some ideas from AT&T SFIO.
916 =cut
922 * Local variables:
923 * c-file-style: "parrot"
924 * End:
925 * vim: expandtab shiftwidth=4: