Provided by: libpoe-perl_1.3700-1_all bug

NAME

       POE::Filter - protocol abstractions for POE::Wheel and standalone use

SYNOPSIS

       To use with POE::Wheel classes, pass a POE::Filter object to one of the "...Filter"
       constructor parameters:

         #!perl

         use POE qw(Filter::Line Wheel::FollowTail);

         POE::Session->create(
           inline_states => {
             _start => sub {
               $_[HEAP]{tailor} = POE::Wheel::FollowTail->new(
                 Filename => "/var/log/system.log",
                 InputEvent => "got_log_line",
                 Filter => POE::Filter::Line->new(),
               );
             },
             got_log_line => sub {
               print "Log: $_[ARG0]\n";
             }
           }
         );

         POE::Kernel->run();
         exit;

       Standalone use without POE:

         #!perl

         use warnings;
         use strict;
         use POE::Filter::Line;

         my $filter = POE::Filter::Line->new( Literal => "\n" );

         # Prints three lines: one, two three.

         $filter->get_one_start(["one\ntwo\nthr", "ee\nfour"]);
         while (1) {
           my $line = $filter->get_one();
           last unless @$line;
           print $line->[0], "\n";
         }

         # Prints two lines: four, five.

         $filter->get_one_start(["\nfive\n"]);
         while (1) {
           my $line = $filter->get_one();
           last unless @$line;
           print $line->[0], "\n";
         }

DESCRIPTION

       POE::Filter objects plug into the wheels and define how the data will be serialized for
       writing and parsed after reading.  POE::Wheel objects are responsible for moving data, and
       POE::Filter objects define how the data should look.

       POE::Filter objects are simple by design.  They do not use POE internally, so they are
       limited to serialization and parsing.  This may complicate implementation of certain
       protocols (like HTTP 1.x), but it allows filters to be used in stand-alone programs.

       Stand-alone use is very important.  It allows application developers to create lightweight
       blocking libraries that may be used as simple clients for POE servers.
       POE::Component::IKC::ClientLite is a notable example.  This lightweight, blocking event-
       passing client supports thin clients for gridded POE applications.  The canonical use case
       is to inject events into an IKC application or grid from CGI interfaces, which require
       lightweight resource use.

       POE filters and drivers pass data in array references.  This is slightly awkward, but it
       minimizes the amount of data that must be copied on Perl's stack.

PUBLIC INTERFACE

       All POE::Filter classes must support the minimal interface, defined here.  Specific
       filters may implement and document additional methods.

   new PARAMETERS
       new() creates and initializes a new filter.  Constructor parameters vary from one
       POE::Filter subclass to the next, so please consult the documentation for your desired
       filter.

   clone
       clone() creates and initializes a new filter based on the constructor parameters of the
       existing one.  The new filter is a near-identical copy, except that its buffers are empty.

       Certain components, such as POE::Component::Server::TCP, use clone().  These components
       accept a master or template filter at creation time, then clone() that filter for each new
       connection.

         my $new_filter = $old_filter->clone();

   get_one_start ARRAYREF
       get_one_start() accepts an array reference containing unprocessed stream chunks.  The
       chunks are added to the filter's internal buffer for parsing by get_one().

       The "SYNOPSIS" shows get_one_start() in use.

   get_one
       get_one() parses zero or one complete item from the filter's internal buffer.  The data is
       returned as an ARRAYREF suitable for passing to another filter or a POE::Wheel object.
       Filters will return empty ARRAYREFs if they don't have enough raw data to build a complete
       item.

       get_one() is the lazy form of get().  It only parses only one item at a time from the
       filter's buffer.  This is vital for applications that may switch filters in mid-stream, as
       it ensures that the right filter is in use at any given time.

       The "SYNOPSIS" shows get_one() in use.  Note how it assumes the return is always an
       ARRAYREF, and it implicitly handles empty ones.

   get ARRAYREF
       get() is the greedy form of get_one().  It accepts an array reference containing
       unprocessed stream chunks, and it adds that data to the filter's internal buffer.  It then
       parses as many full items as possible from the buffer and returns them in another array
       reference.  Any unprocessed data remains in the filter's buffer for the next call.

       As with get_one(), get() will return an empty array reference if the filter doesn't
       contain enough raw data to build a complete item.

       In fact, get() is implemented in POE::Filter in terms of get_one_start() and get_one().

       Here's the get() form of the SYNOPSIS stand-alone example:

         #!perl

         use warnings;
         use strict;
         use POE::Filter::Line;

         my $filter = POE::Filter::Line->new( Literal => "\n" );

         # Prints three lines: one, two three.

         my $lines = $filter->get(["one\ntwo\nthr", "ee\nfour"]);
         foreach my $line (@$lines) {
           print "$line\n";
         }

         # Prints two lines: four, five.

         $lines = $filter->get(["\nfive\n"]);
         foreach my $line (@$lines) {
           print "$line\n";
         }

       get() should not be used with wheels that support filter switching.  Its greedy nature
       means that it often parses streams well in advance of a wheel's events.  By the time an
       application changes the wheel's filter, it's too late: The old filter has already parsed
       the rest of the received data.

       Consider a stream of letters, numbers, and periods.  The periods signal when to switch
       filters from one that parses letters to one that parses numbers.

       In our hypothetical application, letters must be handled one at a time, but numbers may be
       handled in chunks.  We'll use POE::Filter::Block with a BlockSize of 1 to parse letters,
       and POE::FIlter::Line with a Literal terminator of "." to handle numbers.

       Here's the sample stream:

         abcdefg.1234567.hijklmnop.890.q

       We'll start with a ReadWrite wheel configured to parse characters.

         $_[HEAP]{wheel} = POE::Wheel::ReadWrite->new(
           Filter => POE::Filter::Block->new( BlockSize => 1 ),
           Handle => $socket,
           InputEvent => "got_letter",
         );

       The "got_letter" handler will be called 8 times.  One for each letter from a through g,
       and once for the period following g.  Upon receiving the period, it will switch the wheel
       into number mode.

         sub handle_letter {
           my $letter = $_[ARG0];
           if ($letter eq ".") {
             $_[HEAP]{wheel}->set_filter(
               POE::Filter::Line->new( Literal => "." )
             );
             $_[HEAP]{wheel}->event( InputEvent => "got_number" );
           }
           else {
             print "Got letter: $letter\n";
           }
         }

       If the greedy get() were used, the entire input stream would have been parsed as
       characters in advance of the first handle_letter() call.  The set_filter() call would have
       been moot, since there would be no data left to be parsed.

       The "got_number" handler receives contiguous runs of digits as period-terminated lines.
       The greedy get() would cause a similar problem as above.

         sub handle_numbers {
           my $numbers = $_[ARG0];
           print "Got number(s): $numbers\n";
           $_[HEAP]->{wheel}->set_filter(
             POE::Filter::Block->new( BlockSize => 1 )
           );
           $_[HEAP]->{wheel}->event( InputEvent => "got_letter" );
         }

       So don't do it!

   put ARRAYREF
       put() serializes items into a stream of octets that may be written to a file or sent
       across a socket.  It accepts a reference to a list of items, and it returns a reference to
       a list of marshalled stream chunks.  The number of output chunks is not necessarily
       related to the number of input items.

       In stand-alone use, put()'s output may be sent directly:

         my $line_filter = POE::Filter::Line->new();
         my $lines = $line_filter->put(\@list_of_things);
         foreach my $line (@$lines) {
           print $line;
         }

       The list reference it returns may be passed directly to a driver or filter.  Drivers and
       filters deliberately share the same put() interface so that things like this are possible:

         $driver->put(
           $transfer_encoding_filter->put(
             $content_encoding_filter->put(
               \@items
             )
           )
         );

         1 while $driver->flush(\*STDOUT);

   get_pending
       get_pending() returns any data remaining in a filter's input buffer.  The filter's input
       buffer is not cleared, however.  get_pending() returns a list reference if there's any
       data, or undef if the filter was empty.

       POE::Wheel objects use get_pending() during filter switching.  Unprocessed data is fetched
       from the old filter with get_pending() and injected into the new filter with
       get_one_start().

         use POE::Filter::Line;
         use POE::Filter::Stream;

         my $line_filter = POE::Filter::Line->new();
         $line_filter->get_one_start([ "not a complete line" ]);

         my $stream_filter = POE::Filter::Stream->new();
         my $line_buffer = $line_filter->get_pending();
         $stream_filter->get_one_start($line_buffer) if $line_buffer;

         print "Stream: $_\n" foreach (@{ $stream_filter->get_one });

       Full items are serialized whole, so there is no corresponding "put" buffer or accessor.

SEE ALSO

       The SEE ALSO section in POE contains a table of contents covering the entire POE
       distribution.

       POE is bundled with the following filters:

       POE::Filter::Block POE::Filter::Grep POE::Filter::HTTPD POE::Filter::Line POE::Filter::Map
       POE::Filter::RecordBlock POE::Filter::Reference POE::Filter::Stackable POE::Filter::Stream

BUGS

       In theory, filters should be interchangeable.  In practice, stream and block protocols
       tend to be incompatible.

AUTHORS & COPYRIGHTS

       Please see POE for more information about authors and contributors.