# 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

Reply via email to