# New Ticket Created by Cory Spencer # Please include the string: [perl #25265] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=25265 >
'peek' implements an opcode which can look ahead at an arbitrary number of bytes in a IO stream, but does not remove the bytes from the stream in the process. The proposed format is: peek(out STR, in INT) where $1 contains up to $2 peek'ed bytes from STDIN, and peek(out STR, in PMC, in INT) where $1 contains up to $2 peek'ed bytes from $3 This patch touches the following file: include/parrot/io.h io/io.c io/io_buf.c io/io_passdown.c io/io_private.h If the patch is located in the base parrot directory, it can be applied as: ~$ patch -p1 < peek-opcode.patch
Only in parrot-2/: CFLAGS Only in parrot-2/: Makefile Only in parrot-2/classes: Makefile Only in parrot-2/docs: Makefile Only in parrot-2/dynclasses: Makefile Only in parrot-2/dynoplibs: Makefile Only in parrot-2/imcc: Makefile Only in parrot-2/include/parrot: charclass.h Only in parrot-2/include/parrot: config.h Only in parrot-2/include/parrot: core_pmcs.h Only in parrot-2/include/parrot: exec_dep.h Only in parrot-2/include/parrot: feature.h Only in parrot-2/include/parrot: has_header.h diff -ru parrot-1/include/parrot/io.h parrot-2/include/parrot/io.h --- parrot-1/include/parrot/io.h 2003-11-19 05:29:35.000000000 -0800 +++ parrot-2/include/parrot/io.h 2004-01-25 09:50:41.000000000 -0800 @@ -190,6 +190,8 @@ DummyCodeRef *); INTVAL (*Flush)(theINTERP, ParrotIOLayer * layer, ParrotIO * io); + size_t (*Peek)(theINTERP, ParrotIOLayer * layer, + ParrotIO * io, void * buf, size_t len); PIOOFF_T (*Seek)(theINTERP, ParrotIOLayer * layer, ParrotIO * io, PIOOFF_T offset, INTVAL whence); PIOOFF_T (*Tell)(theINTERP, ParrotIOLayer * layer, @@ -269,6 +271,7 @@ extern INTVAL PIO_setbuf(theINTERP, PMC *, size_t); extern INTVAL PIO_setlinebuf(theINTERP, PMC *); extern INTVAL PIO_puts(theINTERP, PMC *, const char *); +extern INTVAL PIO_peek(theINTERP, PMC *, void *, size_t); extern PIOOFF_T PIO_seek(theINTERP, PMC *, PIOOFF_T offset, INTVAL whence); extern INTVAL PIO_eof(theINTERP, PMC *); extern INTVAL PIO_pioctl(theINTERP, PMC *, INTVAL cmd, INTVAL arg); Only in parrot-2/include/parrot: platform.h Only in parrot-2/include/parrot: platform_interface.h diff -ru parrot-1/io/io.c parrot-2/io/io.c --- parrot-1/io/io.c 2004-01-25 08:32:51.000000000 -0800 +++ parrot-2/io/io.c 2004-01-25 09:46:49.000000000 -0800 @@ -670,6 +670,21 @@ /* + * Iterate down the stack to the first layer implementing "Peek" API + */ +INTVAL +PIO_peek(theINTERP, PMC *pmc, void *buffer, size_t len) +{ + ParrotIOLayer *l = pmc->cache.struct_val; + ParrotIO *io = PMC_data(pmc); + if(!io) + return -1; + + return PIO_peek_down(interpreter, l, io, buffer, len); +} + + +/* * Iterate down the stack to the first layer implementing "Seek" API */ PIOOFF_T diff -ru parrot-1/io/io_buf.c parrot-2/io/io_buf.c --- parrot-1/io/io_buf.c 2004-01-25 08:32:51.000000000 -0800 +++ parrot-2/io/io_buf.c 2004-01-25 09:48:03.000000000 -0800 @@ -46,6 +46,8 @@ ParrotIO *io, void *buffer, size_t len); static size_t PIO_buf_write(theINTERP, ParrotIOLayer *l, ParrotIO *io, const void *buffer, size_t len); +static size_t PIO_buf_peek(theINTERP, ParrotIOLayer *l, + ParrotIO *io, void *buffer, size_t len); static PIOOFF_T PIO_buf_seek(theINTERP, ParrotIOLayer *l, ParrotIO *io, PIOOFF_T offset, INTVAL whence); static PIOOFF_T PIO_buf_tell(theINTERP, ParrotIOLayer *l, ParrotIO *io); @@ -357,6 +359,55 @@ static size_t +PIO_buf_peek(theINTERP, ParrotIOLayer *layer, ParrotIO *io, + void *buffer, size_t len) +{ + ParrotIOLayer *l = layer; + ParrotIOBuf *b; + unsigned 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 = avail < len ? avail : len; + memcpy(out_buf, b->next, current); + + 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; + + got = PIO_buf_fill_readbuf(interpreter, l, io, b); + + len = len < got ? len : got; + } + + /* read from the read_buffer */ + memcpy(out_buf, io->b.next, len); + + return current + len; +} + + +static size_t PIO_buf_readline(theINTERP, ParrotIOLayer *layer, ParrotIO *io, void *buffer, size_t len) { @@ -533,6 +584,7 @@ PIO_buf_read, PIO_null_read_async, PIO_buf_flush, + PIO_buf_peek, PIO_buf_seek, PIO_buf_tell, PIO_buf_setbuf, diff -ru parrot-1/io/io_passdown.c parrot-2/io/io_passdown.c --- parrot-1/io/io_passdown.c 2003-10-11 06:15:30.000000000 -0700 +++ parrot-2/io/io_passdown.c 2004-01-25 09:55:07.000000000 -0800 @@ -143,6 +143,19 @@ return 0; } +size_t +PIO_peek_down(theINTERP, ParrotIOLayer * layer, ParrotIO * io, void * buf, + size_t len) +{ + while (layer) { + if (layer->api->Peek) { + return layer->api->Peek(interpreter, layer, io, buf, len); + } + layer = PIO_DOWNLAYER(layer); + } + /* No layer found */ + return 0; +} INTVAL PIO_flush_down(theINTERP, ParrotIOLayer * layer, ParrotIO * io) diff -ru parrot-1/io/io_private.h parrot-2/io/io_private.h --- parrot-1/io/io_private.h 2003-10-11 06:15:30.000000000 -0700 +++ parrot-2/io/io_private.h 2004-01-25 09:45:58.000000000 -0800 @@ -122,6 +122,8 @@ size_t PIO_read_async_down(theINTERP, ParrotIOLayer * layer, ParrotIO * io, void * buf, size_t len, DummyCodeRef *); INTVAL PIO_flush_down(theINTERP, ParrotIOLayer * layer, ParrotIO * io); +size_t PIO_peek_down(theINTERP, ParrotIOLayer * layer, ParrotIO * io, + void * buf, size_t len); PIOOFF_T PIO_seek_down(theINTERP, ParrotIOLayer * layer, ParrotIO * io, PIOOFF_T offset, INTVAL whence); PIOOFF_T PIO_tell_down(theINTERP, ParrotIOLayer * layer, ParrotIO * io); Only in parrot-2/languages: Makefile Only in parrot-2/languages/befunge: Makefile Only in parrot-2/languages/bf: Makefile Only in parrot-2/languages/jako: Makefile Only in parrot-2/languages/m4: Makefile Only in parrot-2/languages/miniperl: Makefile Only in parrot-2/languages/ook: Makefile Only in parrot-2/languages/perl6: Makefile Only in parrot-2/languages/scheme: Makefile Only in parrot-2/languages/tcl: Makefile Only in parrot-2/languages/urm: Makefile Only in parrot-2/lib/Parrot: Config.pm Only in parrot-2/lib/Parrot: PMC.pm Only in parrot-2/: libparrot.def Only in parrot-2/: myconfig Only in parrot-2/ops: core_ops.c Only in parrot-2/ops: core_ops_prederef.c Only in parrot-2/ops: core_ops_switch.c diff -ru parrot-1/ops/io.ops parrot-2/ops/io.ops --- parrot-1/ops/io.ops 2003-11-07 04:12:33.000000000 -0800 +++ parrot-2/ops/io.ops 2004-01-25 09:44:55.000000000 -0800 @@ -404,6 +404,55 @@ ########################################## +=item B<peek>(out STR, in INT) + +Reads up to N bytes from standard input, but does not +remove them from the stream. + +=item B<peek>(out STR, in PMC, in INT) + +Reads up to N bytes from an IO PMC, but does not +remove them from the stream. + +=cut + +op peek(out STR, in INT) { + UINTVAL n; + INTVAL nr; + if($2 >= 65535) + n = 65535; + else + n = $2; + $1 = string_make(interpreter, NULL, n, NULL, 0, NULL); + memset(($1)->strstart, 0, n); + nr = PIO_peek(interpreter, PIO_STDIN(interpreter), + ($1)->strstart, (size_t)n); + if(nr > 0) + ($1)->strlen = ($1)->bufused = nr; + else + ($1)->strlen = ($1)->bufused = 0; + goto NEXT(); +} + +op peek(out STR, in PMC, in INT) { + UINTVAL n; + INTVAL nr; + if($3 >= 65535) + n = 65535; + else + n = $3; + $1 = string_make(interpreter, NULL, n, NULL, 0, NULL); + memset(($1)->strstart, 0, n); + nr = PIO_peek(interpreter, $2, ($1)->strstart, (size_t)n); + if(nr > 0) + ($1)->strlen = ($1)->bufused = nr; + else + ($1)->strlen = ($1)->bufused = 0; + goto NEXT(); +} + +########################################## + =item B<seek>(in PMC, in INT, in INT) seek: Only in parrot-2/runtime/parrot/include: chartypes.pasm Only in parrot-2/runtime/parrot/include: datatypes.pasm Only in parrot-2/runtime/parrot/include: encodings.pasm Only in parrot-2/runtime/parrot/include: except_severity.pasm Only in parrot-2/runtime/parrot/include: except_types.pasm Only in parrot-2/runtime/parrot/include: iglobals.pasm Only in parrot-2/runtime/parrot/include: interpcores.pasm Only in parrot-2/runtime/parrot/include: interpflags.pasm Only in parrot-2/runtime/parrot/include: interpinfo.pasm Only in parrot-2/runtime/parrot/include: iotypes.pasm Only in parrot-2/runtime/parrot/include: iterator.pasm Only in parrot-2/runtime/parrot/include: longopt.pasm Only in parrot-2/runtime/parrot/include: pmctypes.pasm Only in parrot-2/runtime/parrot/include: signal.pasm Only in parrot-2/runtime/parrot/include: stdio.pasm Only in parrot-2/runtime/parrot/include: stringinfo.pasm Only in parrot-2/runtime/parrot/include: sysinfo.pasm Only in parrot-2/runtime/parrot/include: timer.pasm Only in parrot-2/runtime/parrot/include: vtable_methods.pasm Only in parrot-2/runtime/parrot/include: warnings.pasm Only in parrot-2/src: core_pmcs.c Only in parrot-2/src: platform.c