Current File : //usr/local/share/man/man3/POE::Filter.3pm |
.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
. ds C`
. ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
. if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. if !\nF==2 \{\
. nr % 0
. nr F 2
. \}
. \}
.\}
.rr rF
.\" ========================================================================
.\"
.IX Title "POE::Filter 3"
.TH POE::Filter 3 "2022-03-23" "perl v5.26.3" "User Contributed Perl Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
POE::Filter \- protocol abstractions for POE::Wheel and standalone use
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
To use with POE::Wheel classes, pass a POE::Filter object to one of
the \*(L"...Filter\*(R" constructor parameters:
.PP
.Vb 1
\& #!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]\en";
\& }
\& }
\& );
\&
\& POE::Kernel\->run();
\& exit;
.Ve
.PP
Standalone use without \s-1POE:\s0
.PP
.Vb 1
\& #!perl
\&
\& use warnings;
\& use strict;
\& use POE::Filter::Line;
\&
\& my $filter = POE::Filter::Line\->new( Literal => "\en" );
\&
\& # Prints three lines: one, two three.
\&
\& $filter\->get_one_start(["one\entwo\enthr", "ee\enfour"]);
\& while (1) {
\& my $line = $filter\->get_one();
\& last unless @$line;
\& print $line\->[0], "\en";
\& }
\&
\& # Prints two lines: four, five.
\&
\& $filter\->get_one_start(["\enfive\en"]);
\& while (1) {
\& my $line = $filter\->get_one();
\& last unless @$line;
\& print $line\->[0], "\en";
\& }
.Ve
.SH "DESCRIPTION"
.IX Header "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.
.PP
POE::Filter objects are simple by design. They do not use \s-1POE\s0
internally, so they are limited to serialization and parsing. This
may complicate implementation of certain protocols (like \s-1HTTP 1\s0.x),
but it allows filters to be used in stand-alone programs.
.PP
Stand-alone use is very important. It allows application developers
to create lightweight blocking libraries that may be used as simple
clients for \s-1POE\s0 servers. POE::Component::IKC::ClientLite is a notable
example. This lightweight, blocking event-passing client supports
thin clients for gridded \s-1POE\s0 applications. The canonical use case is
to inject events into an \s-1IKC\s0 application or grid from \s-1CGI\s0 interfaces,
which require lightweight resource use.
.PP
\&\s-1POE\s0 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.
.SH "PUBLIC INTERFACE"
.IX Header "PUBLIC INTERFACE"
All POE::Filter classes must support the minimal interface, defined
here. Specific filters may implement and document additional methods.
.SS "new \s-1PARAMETERS\s0"
.IX Subsection "new PARAMETERS"
\&\fBnew()\fR 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.
.SS "clone"
.IX Subsection "clone"
\&\fBclone()\fR 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.
.PP
Certain components, such as POE::Component::Server::TCP, use \fBclone()\fR.
These components accept a master or template filter at creation time,
then \fBclone()\fR that filter for each new connection.
.PP
.Vb 1
\& my $new_filter = $old_filter\->clone();
.Ve
.SS "get_one_start \s-1ARRAYREF\s0"
.IX Subsection "get_one_start ARRAYREF"
\&\fBget_one_start()\fR accepts an array reference containing unprocessed
stream chunks. The chunks are added to the filter's internal buffer
for parsing by \fBget_one()\fR.
.PP
The \*(L"\s-1SYNOPSIS\*(R"\s0 shows \fBget_one_start()\fR in use.
.SS "get_one"
.IX Subsection "get_one"
\&\fBget_one()\fR parses zero or one complete item from the filter's internal
buffer. The data is returned as an \s-1ARRAYREF\s0 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.
.PP
\&\fBget_one()\fR is the lazy form of \fBget()\fR. 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.
.PP
The \*(L"\s-1SYNOPSIS\*(R"\s0 shows \fBget_one()\fR in use. Note how it assumes the
return is always an \s-1ARRAYREF,\s0 and it implicitly handles empty ones.
.SS "get \s-1ARRAYREF\s0"
.IX Subsection "get ARRAYREF"
\&\fBget()\fR is the greedy form of \fBget_one()\fR. 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.
.PP
As with \fBget_one()\fR, \fBget()\fR will return an empty array reference if the
filter doesn't contain enough raw data to build a complete item.
.PP
In fact, \fBget()\fR is implemented in POE::Filter in terms of
\&\fBget_one_start()\fR and \fBget_one()\fR.
.PP
Here's the \fBget()\fR form of the \s-1SYNOPSIS\s0 stand-alone example:
.PP
.Vb 1
\& #!perl
\&
\& use warnings;
\& use strict;
\& use POE::Filter::Line;
\&
\& my $filter = POE::Filter::Line\->new( Literal => "\en" );
\&
\& # Prints three lines: one, two three.
\&
\& my $lines = $filter\->get(["one\entwo\enthr", "ee\enfour"]);
\& foreach my $line (@$lines) {
\& print "$line\en";
\& }
\&
\& # Prints two lines: four, five.
\&
\& $lines = $filter\->get(["\enfive\en"]);
\& foreach my $line (@$lines) {
\& print "$line\en";
\& }
.Ve
.PP
\&\fBget()\fR 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.
.PP
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.
.PP
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 \*(L".\*(R" to handle numbers.
.PP
Here's the sample stream:
.PP
.Vb 1
\& abcdefg.1234567.hijklmnop.890.q
.Ve
.PP
We'll start with a ReadWrite wheel configured to parse characters.
.PP
.Vb 5
\& $_[HEAP]{wheel} = POE::Wheel::ReadWrite\->new(
\& Filter => POE::Filter::Block\->new( BlockSize => 1 ),
\& Handle => $socket,
\& InputEvent => "got_letter",
\& );
.Ve
.PP
The \*(L"got_letter\*(R" 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.
.PP
.Vb 12
\& 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\en";
\& }
\& }
.Ve
.PP
If the greedy \fBget()\fR were used, the entire input stream would have been
parsed as characters in advance of the first \fBhandle_letter()\fR call.
The \fBset_filter()\fR call would have been moot, since there would be no
data left to be parsed.
.PP
The \*(L"got_number\*(R" handler receives contiguous runs of digits as
period-terminated lines. The greedy \fBget()\fR would cause a similar
problem as above.
.PP
.Vb 8
\& sub handle_numbers {
\& my $numbers = $_[ARG0];
\& print "Got number(s): $numbers\en";
\& $_[HEAP]\->{wheel}\->set_filter(
\& POE::Filter::Block\->new( BlockSize => 1 )
\& );
\& $_[HEAP]\->{wheel}\->event( InputEvent => "got_letter" );
\& }
.Ve
.PP
So don't do it!
.SS "put \s-1ARRAYREF\s0"
.IX Subsection "put ARRAYREF"
\&\fBput()\fR 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.
.PP
In stand-alone use, \fBput()\fR's output may be sent directly:
.PP
.Vb 5
\& my $line_filter = POE::Filter::Line\->new();
\& my $lines = $line_filter\->put(\e@list_of_things);
\& foreach my $line (@$lines) {
\& print $line;
\& }
.Ve
.PP
The list reference it returns may be passed directly to a driver or
filter. Drivers and filters deliberately share the same \fBput()\fR
interface so that things like this are possible:
.PP
.Vb 7
\& $driver\->put(
\& $transfer_encoding_filter\->put(
\& $content_encoding_filter\->put(
\& \e@items
\& )
\& )
\& );
\&
\& 1 while $driver\->flush(\e*STDOUT);
.Ve
.SS "get_pending"
.IX Subsection "get_pending"
\&\fBget_pending()\fR returns any data remaining in a filter's input buffer.
The filter's input buffer is not cleared, however. \fBget_pending()\fR
returns a list reference if there's any data, or undef if the filter
was empty.
.PP
POE::Wheel objects use \fBget_pending()\fR during filter switching.
Unprocessed data is fetched from the old filter with \fBget_pending()\fR and
injected into the new filter with \fBget_one_start()\fR.
.PP
.Vb 2
\& 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: $_\en" foreach (@{ $stream_filter\->get_one });
.Ve
.PP
Full items are serialized whole, so there is no corresponding \*(L"put\*(R"
buffer or accessor.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
The \s-1SEE ALSO\s0 section in \s-1POE\s0 contains a table of contents covering
the entire \s-1POE\s0 distribution.
.PP
\&\s-1POE\s0 is bundled with the following filters:
.PP
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
.SH "BUGS"
.IX Header "BUGS"
In theory, filters should be interchangeable. In practice, stream and
block protocols tend to be incompatible.
.SH "AUTHORS & COPYRIGHTS"
.IX Header "AUTHORS & COPYRIGHTS"
Please see \s-1POE\s0 for more information about authors and contributors.