All POE::Filter classes must support the minimal interface, defined here. Specific filters may implement
and document additional methods.
newPARAMETERSnew() 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.
cloneclone() 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_startARRAYREFget_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_oneget_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.
getARRAYREFget() 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!
putARRAYREFput() 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_pendingget_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.