# New Ticket Created by Jürgen Bömmels # Please include the string: [perl #21656] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=21656 >
Hello, Yet another step in PIO: Enabling read buffering. The first read will fill the buffer by calling the underlying read-function. Successive calls just take the data out of the read buffers. If there is not enough data in the buffer it will refill as necessary, but it will never call not call the underlying layer more than once (If the underlying layer cant fullfill the request how can the buffer-layer do). I also attach a test file, which was very helpful in writing this. You might add it to t/src/. But don't forget MANIFEST. bye boe -- attachment 1 ------------------------------------------------------ url: http://rt.perl.org/rt2/attach/53999/40674/872e54/io3.diff -- attachment 2 ------------------------------------------------------ url: http://rt.perl.org/rt2/attach/53999/40675/6a74eb/io.t
Index: io/io.c =================================================================== RCS file: /cvs/public/parrot/io/io.c,v retrieving revision 1.31 diff -u -r1.31 io.c --- io/io.c 14 Mar 2003 20:20:19 -0000 1.31 +++ io/io.c 23 Mar 2003 00:42:13 -0000 @@ -149,10 +149,8 @@ for (i = 0 ; i < PIO_NR_OPEN; i++) { if ( (io = GET_INTERP_IOD(interpreter)->table[i]) ) { -#if 0 PIO_flush(interpreter, io); PIO_close(interpreter, io); -#endif mem_sys_free(io); } } @@ -201,9 +199,7 @@ #ifdef PIO_OS_STDIO PIO_push_layer(interpreter, PIO_base_new_layer(&pio_stdio_layer), NULL); #endif -#if 0 PIO_push_layer(interpreter, PIO_base_new_layer(&pio_buf_layer), NULL); -#endif /* Note: All layer pushes should be done before init calls */ for (p = GET_INTERP_IO(interpreter); p; p = p->down) { Index: io/io_buf.c =================================================================== RCS file: /cvs/public/parrot/io/io_buf.c,v retrieving revision 1.2 diff -u -r1.2 io_buf.c --- io/io_buf.c 17 Mar 2003 16:19:20 -0000 1.2 +++ io/io_buf.c 23 Mar 2003 00:42:13 -0000 @@ -55,9 +55,11 @@ /* Local util functions */ size_t PIO_buf_writethru(theINTERP, ParrotIOLayer *layer, ParrotIO *io, const void *buffer, size_t len); +size_t PIO_buf_readthru(theINTERP, ParrotIOLayer *layer, + ParrotIO *io, void *buffer, size_t len); - - +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) INTVAL PIO_buf_init(theINTERP, ParrotIOLayer *layer) @@ -235,14 +237,95 @@ PIO_buf_read(theINTERP, ParrotIOLayer *layer, ParrotIO *io, void *buffer, size_t len) { - UNUSED(interpreter); - UNUSED(layer); - UNUSED(io); - UNUSED(buffer); - UNUSED(len); - return 0; + ParrotIOLayer *l = layer; + ParrotIOBuf *b; + char *out_buf = buffer; + size_t current = 0; + + /* write buffer flush */ + if (io->b.flags & PIO_BF_WRITEBUF) { + PIO_buf_flush(interpreter, layer, io); + } + + b = &io->b; + + /* read Data from buffer */ + if (b->flags & PIO_BF_READBUF) { + size_t avail = b->endb - b->next; + + current = MIN(avail, len); + memcpy(out_buf, b->next, current); + b->next += current; + + /* buffer completed */ + if (current == avail) { + io->b.flags &= ~PIO_BF_READBUF; + /* XXX: Is the reset of next and endb really necessary ? */ + io->b.endb = NULL; + io->b.next = io->b.startb; + } + + if (len == current) { + return current; + } + else { + /* more data needed from downlayer */ + out_buf += current; + len -= current; + } + } + + /* (re)fill the readbuffer */ + if (!(b->flags & PIO_BF_READBUF)) { + size_t got; + + if (len >= io->b.size) { + return current + PIO_buf_readthru(interpreter, l, io, buffer, len); + } + + got = PIO_buf_readthru(interpreter, l, io, b->startb, b->size); + b->endb = b->startb + got; + b->next = b->startb; + + io->b.flags |= PIO_BF_READBUF; + + len = MIN(len, got); + } + + /* read from the read_buffer */ + memcpy(out_buf, io->b.next, len); + io->b.next += len; + + /* is the buffer is completely empty ? */ + if (io->b.next == io->b.endb) { + io->b.flags &= ~PIO_BF_READBUF; + /* XXX: Is the reset of next and encb really necessary ? */ + io->b.endb = NULL; + io->b.next = io->b.startb; + } + return current + len; } +/* XXX: This function is not really io_buf specific */ +size_t +PIO_buf_readthru (theINTERP, ParrotIOLayer *layer, ParrotIO *io, + void *buffer, size_t len) +{ + ParrotIOLayer *l = layer; + + do { + l = PIO_DOWNLAYER(layer); + } while (l && !l->api->Read); + + if (l) { + return (l->api->Read)(interpreter, l, io, buffer, len); + } + else { + /* No underlying read implementation */ + /* XXX: Handle error here */ + return 0; + } +} size_t PIO_buf_write(theINTERP, ParrotIOLayer *layer, ParrotIO *io,
#! perl -w use Parrot::Test tests => 4; use Test::More; $/=undef; # slurp mode TODO: { local $TODO="t/src doesn't work on Windows" if $^O =~ /Win32/; $TODO=$TODO; #warnings c_output_is(<<'CODE', <<'OUTPUT', "hello world"); #include <parrot/parrot.h> #include <parrot/io.h> int main () { int dummy_var; struct Parrot_Interp *interpreter; interpreter = Parrot_new(); Parrot_init(interpreter, &dummy_var); PIO_printf(interpreter, "Hello, World!\n"); return 0; } CODE Hello, World! OUTPUT c_output_is(<<'CODE', <<'OUTPUT', "write"); #include <parrot/parrot.h> #include <parrot/io.h> int main () { int dummy_var; struct Parrot_Interp *interpreter; ParrotIO *io; char *p; interpreter = Parrot_new(); Parrot_init(interpreter, &dummy_var); io = PIO_STDOUT(interpreter); PIO_write(interpreter, io, "Hello, World!\n", 14); io = PIO_open(interpreter, "temp.file", ">"); for (p="Hello, World!\n"; *p; p++) { PIO_write (interpreter, io, p, 1); } PIO_close(interpreter, io); return 0; } CODE Hello, World! OUTPUT open FILE, "temp.file"; is(<FILE>, <<DATA, 'file content'); Hello, World! DATA close FILE; c_output_is(<<'CODE', <<'OUTPUT', 'read'); #include <parrot/parrot.h> #include <parrot/io.h> int main () { int dummy_var; struct Parrot_Interp *interpreter; ParrotIO *io; char buf[1024]; UINTVAL len; interpreter = Parrot_new(); Parrot_init(interpreter, &dummy_var); io = PIO_open(interpreter, "temp.file", "<"); len = PIO_read(interpreter, io, buf, sizeof(buf)); PIO_close(interpreter, io); buf[len] = '\0'; PIO_printf(interpreter, "%s", buf); io = PIO_open(interpreter, "temp.file", "<"); /* this is for testing buffers, not for performance */ PIO_setbuf(interpreter, io, 4); do { len = PIO_read(interpreter, io, buf, 3); buf[len] = '\0'; PIO_printf(interpreter, "%d: %s\n", len, buf); } while (len > 0); return 0; } CODE Hello, World! 3: Hel 3: lo, 3: Wo 3: rld 2: ! 0: OUTPUT } # TODO