2 Copyright (C) 2001-2008, The Perl Foundation.
7 src/io/io_buf.c - IO buffer layer
11 The "buf" layer of Parrot IO. Buffering and all the fun stuff.
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
),
31 __attribute__nonnull__(1)
32 __attribute__nonnull__(3)
35 PARROT_CAN_RETURN_NULL
36 PARROT_WARN_UNUSED_RESULT
37 static ParrotIO
* PIO_buf_fdopen(PARROT_INTERP
,
38 ARGIN_NULLOK(ParrotIOLayer
*layer
),
41 __attribute__nonnull__(1);
43 static size_t PIO_buf_fill_readbuf(PARROT_INTERP
,
44 ARGIN_NULLOK(ParrotIOLayer
*layer
),
46 ARGMOD(ParrotIOBuf
*b
))
47 __attribute__nonnull__(1)
48 __attribute__nonnull__(3)
49 __attribute__nonnull__(4)
53 static INTVAL
PIO_buf_flush(PARROT_INTERP
,
54 ARGIN_NULLOK(ParrotIOLayer
*layer
),
56 __attribute__nonnull__(1)
57 __attribute__nonnull__(3)
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
),
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
),
79 __attribute__nonnull__(1)
80 __attribute__nonnull__(3)
81 __attribute__nonnull__(4)
85 static size_t PIO_buf_read(PARROT_INTERP
,
86 ARGIN_NULLOK(ParrotIOLayer
*layer
),
89 __attribute__nonnull__(1)
90 __attribute__nonnull__(3)
91 __attribute__nonnull__(4)
95 static size_t PIO_buf_readline(PARROT_INTERP
,
96 ARGIN_NULLOK(ParrotIOLayer
*layer
),
99 __attribute__nonnull__(1)
100 __attribute__nonnull__(3)
101 __attribute__nonnull__(4)
105 static PIOOFF_T
PIO_buf_seek(PARROT_INTERP
,
106 ARGIN_NULLOK(ParrotIOLayer
*l
),
107 ARGMOD(ParrotIO
*io
),
110 __attribute__nonnull__(1)
111 __attribute__nonnull__(3)
114 static INTVAL
PIO_buf_setbuf(PARROT_INTERP
,
115 ARGIN_NULLOK(ParrotIOLayer
*layer
),
116 ARGMOD(ParrotIO
*io
),
118 __attribute__nonnull__(1)
119 __attribute__nonnull__(3)
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)
129 static PIOOFF_T
PIO_buf_tell(SHIM_INTERP
,
130 SHIM(ParrotIOLayer
*layer
),
132 __attribute__nonnull__(3);
134 static size_t PIO_buf_write(PARROT_INTERP
,
135 ARGMOD(ParrotIOLayer
*layer
),
136 ARGMOD(ParrotIO
*io
),
138 __attribute__nonnull__(1)
139 __attribute__nonnull__(2)
140 __attribute__nonnull__(3)
141 __attribute__nonnull__(4)
142 FUNC_MODIFIES(*layer
)
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
= {
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.
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
);
194 =item C<static ParrotIO * PIO_buf_open>
196 The buffer layer's C<Open> function.
202 PARROT_CAN_RETURN_NULL
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
);
210 /* error creating IO stream */
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
);
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>.
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.
249 PIO_buf_flush(interp
, l
, io
);
251 /* Choose an appropriate buffer size for caller */
257 b
->size
= PIO_getblksize(io
->fd
);
260 b
->size
= (bufsize
>= PIO_GRAIN
? bufsize
: PIO_GRAIN
);
264 if (b
->startb
&& (b
->flags
& PIO_BF_MALLOC
)) {
265 mem_sys_free(b
->startb
);
266 b
->startb
= b
->next
= NULL
;
270 b
->startb
= b
->next
= (unsigned char *)mem_sys_allocate(b
->size
);
271 b
->flags
|= PIO_BF_MALLOC
;
274 b
->flags
&= ~PIO_BF_MALLOC
;
277 io
->flags
&= ~PIO_F_LINEBUF
;
278 io
->flags
|= PIO_F_BLKBUF
;
281 io
->flags
&= ~(PIO_F_BLKBUF
| PIO_F_LINEBUF
);
288 =item C<static INTVAL PIO_buf_setlinebuf>
290 The buffer layer's C<SetLineBuf> function.
297 PIO_buf_setlinebuf(PARROT_INTERP
, ARGIN_NULLOK(ParrotIOLayer
*layer
),
298 ARGMOD(ParrotIO
*io
))
301 ParrotIOLayer
* const l
= layer
? layer
: io
->stack
;
303 /* already linebuffering */
304 if (io
->flags
& PIO_F_LINEBUF
)
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
;
320 =item C<static ParrotIO * PIO_buf_fdopen>
322 The buffer layer's C<FDOpen> function.
328 PARROT_CAN_RETURN_NULL
329 PARROT_WARN_UNUSED_RESULT
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
);
337 if (io
->flags
& PIO_F_CONSOLE
)
338 PIO_buf_setlinebuf(interp
, l
, io
);
340 PIO_buf_setbuf(interp
, l
, io
, PIO_UNBOUND
);
348 =item C<static INTVAL PIO_buf_close>
350 The buffer layer's C<Close> function.
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.
376 PIO_buf_flush(PARROT_INTERP
, ARGIN_NULLOK(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
))
382 * Either buffering is null, disabled, or empty.
385 || (io
->flags
& (PIO_F_BLKBUF
| PIO_F_LINEBUF
)) == 0
386 || (io
->b
.flags
& (PIO_BF_WRITEBUF
| PIO_BF_READBUF
)) == 0)
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
;
402 io
->b
.flags
&= ~PIO_BF_WRITEBUF
;
406 /* FIXME: I/O Error */
412 else if (io
->b
.flags
& PIO_BF_READBUF
) {
413 io
->b
.flags
&= ~PIO_BF_READBUF
;
414 io
->b
.next
= io
->b
.startb
;
421 =item C<static size_t PIO_buf_fill_readbuf>
423 The buffer layer's C<Fill> function.
430 PIO_buf_fill_readbuf(PARROT_INTERP
, ARGIN_NULLOK(ParrotIOLayer
*layer
),
431 ARGMOD(ParrotIO
*io
), ARGMOD(ParrotIOBuf
*b
))
434 PIOOFF_T pos
= io
->fpos
;
436 fake
.strstart
= (char *)b
->startb
;
437 fake
.bufused
= b
->size
;
440 got
= PIO_read_down(interp
, PIO_DOWNLAYER(layer
),
442 /* buffer-filling does not change fileposition */
449 b
->endb
= b
->startb
+ got
;
452 b
->flags
|= PIO_BF_READBUF
;
459 =item C<static size_t PIO_buf_read>
461 The buffer layer's C<Read> function.
468 PIO_buf_read(PARROT_INTERP
, ARGIN_NULLOK(ParrotIOLayer
*layer
),
469 ARGMOD(ParrotIO
*io
), ARGOUT(STRING
**buf
))
471 ParrotIOLayer
*l
= layer
;
473 unsigned char *out_buf
;
478 /* write buffer flush */
479 if (io
->b
.flags
& PIO_BF_WRITEBUF
) {
480 PIO_buf_flush(interp
, layer
, io
);
485 /* line buffered read */
486 if (io
->flags
& PIO_F_LINEBUF
) {
487 return PIO_buf_readline(interp
, layer
, io
, buf
);
491 *buf
= new_string_header(interp
, 0);
492 (*buf
)->bufused
= len
= 2048;
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
);
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 ? */
514 io
->b
.next
= io
->b
.startb
;
517 if (len
== current
) {
518 s
->strlen
= s
->bufused
= len
;
522 /* more data needed from downlayer */
528 /* (re)fill the readbuffer */
529 if (!(b
->flags
& PIO_BF_READBUF
)) {
531 if (len
>= io
->b
.size
) {
535 fake
.strstart
= (char *)out_buf
;
537 got
= PIO_read_down(interp
, PIO_DOWNLAYER(l
), io
, &sf
);
538 s
->strlen
= s
->bufused
= current
+ 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
;
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 ? */
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!!!
575 PIO_buf_peek(PARROT_INTERP
, ARGIN_NULLOK(ParrotIOLayer
*layer
),
576 ARGMOD(ParrotIO
*io
), ARGOUT(STRING
**buf
))
578 ParrotIOLayer
*l
= layer
;
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
);
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 */
599 memcpy(s
->strstart
, b
->next
, len
);
600 s
->bufused
= s
->strlen
= len
;
605 /* (re)fill the buffer */
606 if (! (b
->flags
& PIO_BF_READBUF
)) {
608 /* exception if we're unbuffered */
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 */
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.
632 PIO_buf_readline(PARROT_INTERP
, ARGIN_NULLOK(ParrotIOLayer
*layer
),
633 ARGMOD(ParrotIO
*io
), ARGOUT(STRING
**buf
))
636 unsigned char *out_buf
;
637 unsigned char *buf_start
;
638 ParrotIOBuf
* const b
= &io
->b
;
643 *buf
= new_string_header(interp
, 0);
648 /* fill empty buffer */
649 if (!(b
->flags
& PIO_BF_READBUF
)) {
650 if (PIO_buf_fill_readbuf(interp
, layer
, io
, b
) == 0)
655 for (l
= 0; b
->next
< b
->endb
;) {
657 if (IS_EOL(io
, b
->next
++)) {
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
)
665 /* buffer completed; copy out and refill */
666 if (b
->next
== b
->endb
) {
667 len
= b
->endb
- buf_start
;
668 if (s
->bufused
< l
) {
670 Parrot_reallocate_string(interp
, s
, l
);
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)
681 buf_start
= b
->startb
;
684 if (s
->bufused
< l
) {
686 Parrot_reallocate_string(interp
, s
, l
);
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
) {
701 b
->flags
&= ~PIO_BF_READBUF
;
709 =item C<static size_t PIO_buf_write>
711 The buffer layer's C<Write> function.
718 PIO_buf_write(PARROT_INTERP
, ARGMOD(ParrotIOLayer
*layer
),
719 ARGMOD(ParrotIO
*io
), ARGIN(STRING
*s
))
722 void * const buffer
= s
->strstart
;
723 size_t len
= s
->bufused
;
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
;
739 /* If we are line buffered, check for newlines.
740 * If any, we should flush
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;
747 for (i
= 0; i
< len
; ++i
, --p
)
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
) {
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
) {
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
);
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
);
788 PIO_buf_flush(interp
, layer
, io
);
789 memcpy(io
->b
.startb
, ((const char *)buffer
+ avail
), diff
);
798 =item C<static PIOOFF_T PIO_buf_seek>
800 The buffer layer's C<Seek> function.
807 PIO_buf_seek(PARROT_INTERP
, ARGIN_NULLOK(ParrotIOLayer
*l
),
808 ARGMOD(ParrotIO
*io
), PIOOFF_T offset
, INTVAL whence
)
817 newpos
= io
->fpos
+ offset
;
820 newpos
= PIO_seek_down(interp
, PIO_DOWNLAYER(l
), io
, offset
,
827 /* XXX: somehow report the illegal whence value */
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
);
837 io
->b
.next
+= newpos
- io
->fpos
;
848 =item C<static PIOOFF_T PIO_buf_tell>
850 The buffer layer's C<Tell> function.
857 PIO_buf_tell(SHIM_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGIN(ParrotIO
*io
))
862 const ParrotIOLayerAPI pio_buf_layer_api
= {
865 PIO_base_delete_layer
,
875 PIO_null_write_async
,
903 F<src/io/io_passdown.c>,
904 F<src/io/io_stdio.c>,
906 F<src/io/io_win32.c>,
908 F<src/io/io_private.h>.
912 Initially written by Melvin Smith.
914 Some ideas from AT&T SFIO.
923 * c-file-style: "parrot"
925 * vim: expandtab shiftwidth=4: