Here's a patch (for discussion, but I'll apply it if there are no objections) 
to add a stringy IO layer and to fix a few typos.

This or a similar feature is (eventually) necessary for HLLs that don't 
necessarily quite always want to let their output escape into the world, 
instead preferring to think it over before hitting send.

It'll also help with the embedded version of Parrot::Test.  That's my 
immediate goal.

Use it as you would any other IO layer.  The test patch offers a very slender 
example.

--- cage cleaners bait starts here ---

NB that you have to touch a lot of files to add a new IO layer.  This could be 
easier.

The documentation of certain functions is far out of date.  For example, try 
to figure out how "read $P0, $I0" translates into the arguments passed into 
PIO_xxx_read.

I have a vague sense of how layers work now and can look over the 
documentation in more detail, but here's a section of the code that could use 
some cleaning.

--- signature and patch follow ---

-- c
=== MANIFEST
==================================================================
--- MANIFEST	(revision 19621)
+++ MANIFEST	(local)
@@ -342,6 +342,7 @@
 src/io/io_layers.c                                []
 src/io/io_private.h                               []
 src/io/io_stdio.c                                 []
+src/io/io_string.c                                []
 src/io/io_win32.c                                 []
 src/io/io_unix.c                                  []
 src/io/io_utf8.c                                  []
=== config/gen/makefiles/root.in
==================================================================
--- config/gen/makefiles/root.in	(revision 19621)
+++ config/gen/makefiles/root.in	(local)
@@ -394,6 +394,7 @@
     $(IO_DIR)/io_mmap$(O) \
     $(IO_DIR)/io_win32$(O) \
     $(IO_DIR)/io_stdio$(O) \
+    $(IO_DIR)/io_string$(O) \
     $(IO_DIR)/io_passdown$(O)
 
 INTERP_O_FILES = \
@@ -1053,6 +1054,8 @@
 
 $(IO_DIR)/io_stdio$(O) : $(GENERAL_H_FILES) $(IO_DIR)/io_private.h
 
+$(IO_DIR)/io_string$(O) : $(GENERAL_H_FILES) $(IO_DIR)/io_private.h
+
 $(IO_DIR)/io_passdown$(O) : $(GENERAL_H_FILES) $(IO_DIR)/io_private.h
 
 $(SRC_DIR)/memory$(O) : $(GENERAL_H_FILES)
=== include/parrot/io.h
==================================================================
--- include/parrot/io.h	(revision 19621)
+++ include/parrot/io.h	(local)
@@ -136,6 +136,7 @@
 #endif
 extern ParrotIOLayer pio_buf_layer;
 extern ParrotIOLayer pio_mmap_layer;
+extern ParrotIOLayer pio_string_layer;
 
 
 
 The return value of this function can be void or a pointer type.
=== src/io/io.c
==================================================================
--- src/io/io.c	(revision 19621)
+++ src/io/io.c	(local)
@@ -408,7 +408,7 @@
 
     fill = 0;
     if (!pio_registered_layers) {
-        n = 4;  /* 2 default layers for now + utf8, mmap */
+        n = 5;  /* 2 default layers for now + utf8, mmap, string */
         pio_registered_layers = mem_sys_allocate(
                 sizeof(ParrotIOLayer *) * (n + 1));
         fill = 1;
@@ -446,7 +446,8 @@
         assert(pio_registered_layers[2] == NULL);
         pio_registered_layers[2] = PIO_utf8_register_layer();
         pio_registered_layers[3] = PIO_mmap_register_layer();
-        pio_registered_layers[4] = NULL;
+        pio_registered_layers[4] = PIO_string_register_layer();
+        pio_registered_layers[5] = NULL;
     }
 
     return 0;
=== src/io/io_layers.c
==================================================================
--- src/io/io_layers.c	(revision 19621)
+++ src/io/io_layers.c	(local)
@@ -26,7 +26,7 @@
 PIO_base_new_layer(ParrotIOLayer *proto)>
 
 The default IO layer constructor. Creates and returns a new
-C<ParrotIOLayer>. If a prototype C<*proto> is supplied then it's values
+C<ParrotIOLayer>. If a prototype C<*proto> is supplied then its values
 will be copied to the new instance.
 
 =cut
=== src/io/io_private.h
==================================================================
--- src/io/io_private.h	(revision 19621)
+++ src/io/io_private.h	(local)
@@ -269,6 +269,7 @@
 
 ParrotIOLayer * PIO_utf8_register_layer(void);
 ParrotIOLayer * PIO_mmap_register_layer(void);
+ParrotIOLayer * PIO_string_register_layer(void);
 
 void PIO_push_layer_str(Interp *interpreter, PMC *pmc, STRING *ls);
 STRING* PIO_pop_layer_str(Interp *interpreter, PMC *pmc);
=== src/io/io_string.c
==================================================================
--- src/io/io_string.c	(revision 19621)
+++ src/io/io_string.c	(local)
@@ -0,0 +1,139 @@
+/*
+Copyright (c) 2006, The Perl Foundation.
+$Id$
+
+=head1 NAME
+
+src/io/io_string.c - IO Layer for strings
+
+=head1 DESCRIPTION
+
+Capture output to a string PMC.
+
+*/
+
+/*
+
+=head2 String Layer Functions
+
+=over 4
+
+=cut
+
+*/
+
+#include "parrot/parrot.h"
+#include "io_private.h"
+
+/* Defined at bottom */
+static const ParrotIOLayerAPI pio_string_layer_api;
+
+ParrotIOLayer pio_string_layer = {
+    NULL,
+    "string",
+    0,
+    &pio_string_layer_api,
+    0, 0
+};
+
+ParrotIOLayer *
+PIO_string_register_layer(void)
+{
+    return &pio_string_layer;
+}
+
+static size_t
+PIO_string_read(theINTERP, ParrotIOLayer *l, ParrotIO *io, STRING **buf)
+{
+    UNUSED(io);
+    UNUSED(interpreter);
+
+    if (l->self == 0)
+        return 0;
+
+    *buf    = l->self;
+    l->self = 0;
+
+    return (*buf)->strlen;
+}
+
+static size_t
+PIO_string_write(theINTERP, ParrotIOLayer *l, ParrotIO *io, STRING *s)
+{
+    STRING * old_string;
+
+    UNUSED(io);
+    old_string = l->self;
+
+    if (old_string == 0) {
+        l->self = s;
+        return s->strlen;
+    }
+
+    l->self = string_append(interpreter, old_string, s, 0);
+    return string_length(interpreter, l->self);
+}
+
+static const ParrotIOLayerAPI pio_string_layer_api = {
+    PIO_null_init,
+    PIO_base_new_layer,
+    PIO_base_delete_layer,
+    PIO_null_push_layer,
+    PIO_null_pop_layer,
+    PIO_null_open,
+    PIO_null_open2,
+    PIO_null_open3,
+    PIO_null_open_async,
+    PIO_null_fdopen,
+    PIO_null_close,
+    PIO_string_write,
+    PIO_null_write_async,
+    PIO_string_read,
+    PIO_null_read_async,
+    PIO_null_flush,
+    PIO_null_peek,
+    PIO_null_seek,
+    PIO_null_tell,
+    PIO_null_setbuf,
+    PIO_null_setlinebuf,
+    PIO_null_getcount,
+    PIO_null_fill,
+    PIO_null_eof,
+    0, /* no poll */
+    0, /* no socket */
+    0, /* no connect */
+    0, /* no send */
+    0, /* no recv */
+    0, /* no bind */
+    0, /* no listen */
+    0  /* no accept */
+};
+
+/*
+
+=back
+
+=head1 SEE ALSO
+
+F<src/io/io_passdown.c>,
+F<src/io/io.c>,
+F<src/io/io_layers.c>,
+F<src/io/io_private.h>.
+
+=head1 HISTORY
+
+Initially written by chromatic.
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */
=== src/pmc/parrotio.pmc
==================================================================
--- src/pmc/parrotio.pmc	(revision 19621)
+++ src/pmc/parrotio.pmc	(local)
@@ -325,7 +325,7 @@
 
 Returns the name of the nth layer. B<n> >= 0 returns layer names up from the
 bottom.  If B<n> is negative, returns layer names from top down. For
-non-existant layers, returns an empty string.
+non-existent layers, returns an empty string.
 
 =cut
 
=== src/pmc/string.pmc
==================================================================
--- src/pmc/string.pmc	(revision 19621)
+++ src/pmc/string.pmc	(local)
@@ -632,7 +632,7 @@
 
 =item C<void replace(STRING* orig, STRING* new)>
 
-Replace every occurence of C<orig> with C<new>.
+Replace every occurrence of C<orig> with C<new>.
 
 =cut
 
=== t/pmc/io.t
==================================================================
--- t/pmc/io.t	(revision 19621)
+++ t/pmc/io.t	(local)
@@ -6,7 +6,7 @@
 use warnings;
 use lib qw( . lib ../lib ../../lib );
 use Test::More;
-use Parrot::Test tests => 35;
+use Parrot::Test tests => 36;
 
 =head1 NAME
 
@@ -711,4 +711,29 @@
 T\xf6tsch
 OUTPUT
 
+pir_output_is(<<'CODE', <<"OUTPUT", "string read/write layer");
+.sub main :main
+    .local pmc    pio
+	.local string greeting
+	.local string layer
+
+    pio = getstdout
+    push pio, "string"
+	print "Hello"
+	print ", "
+	print "world!"
+	print "\n"
+
+	greeting = read pio, 1024
+	pop layer, pio
+
+	print greeting
+	print layer
+	print "\n"
+.end
+CODE
+Hello, world!
+string
+OUTPUT
+
 unlink("temp.file");

Reply via email to