Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
POE::Filter(3)	      User Contributed Perl Documentation	POE::Filter(3)

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.

perl v5.42.0			  2022-03-23			POE::Filter(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=POE::Filter&manpath=FreeBSD+15.0-RELEASE+and+Ports.quarterly>

home | help