.\" 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::Stackable 3pm" .TH POE::Filter::Stackable 3pm "2020-02-07" "perl v5.30.0" "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::Stackable \- combine multiple POE::Filter objects .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& #!perl \& \& use POE qw( \& Wheel::FollowTail \& Filter::Line Filter::Grep Filter::Stackable \& ); \& \& POE::Session\->create( \& inline_states => { \& _start => sub { \& my $parse_input_as_lines = POE::Filter::Line\->new(); \& \& my $select_sudo_log_lines = POE::Filter::Grep\->new( \& Put => sub { 1 }, \& Get => sub { \& my $input = shift; \& return $input =~ /sudo\e[\ed+\e]/i; \& }, \& ); \& \& my $filter_stack = POE::Filter::Stackable\->new( \& Filters => [ \& $parse_input_as_lines, # first on get, last on put \& $select_sudo_log_lines, # first on put, last on get \& ] \& ); \& \& $_[HEAP]{tailor} = POE::Wheel::FollowTail\->new( \& Filename => "/var/log/system.log", \& InputEvent => "got_log_line", \& Filter => $filter_stack, \& ); \& }, \& got_log_line => sub { \& print "Log: $_[ARG0]\en"; \& } \& } \& ); \& \& POE::Kernel\->run(); \& exit; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" POE::Filter::Stackable combines multiple filters together in such a way that they appear to be a single filter. All the usual POE::Filter methods work, but data is secretly passed through the stacked filters before it is returned. POE::Wheel objects and stand-alone programs need no modifications to work with a filter stack. .PP In the \*(L"\s-1SYNOPSIS\*(R"\s0, POE::Filter::Line and POE::Filter::Grep are combined into one filter that only returns a particular kind of line. This can be more efficient than filtering lines in application space, as fewer events may need to be dispatched and handled. .PP Internally, filters are stored in an array. .PP Data added by \fBget_one_start()\fR will flow through the filter array in increasing index order. Filter #0 will have first crack at it, followed by filter #1 and so. The \fBget_one()\fR call will return an item after it has passed through the last filter. .PP \&\fBput()\fR passes data through the filters in descending index order. Data will go through the filter with the highest index first, and \fBput()\fR will return the results after data has passed through filter #0. .SH "PUBLIC FILTER METHODS" .IX Header "PUBLIC FILTER METHODS" In addition to the usual POE::Filter methods, POE::Filter::Stackable also supports the following. .SS "new" .IX Subsection "new" By default, \fBnew()\fR creates an empty filter stack that behaves like POE::Filter::Stream. It may be given optional parameters to initialize the stack with an array of filters. .PP .Vb 9 \& my $sudo_lines = POE::Filter::Stackable\->new( \& Filters => [ \& POE::Filter::Line\->new(), \& POE::Filter::Grep\->new( \& Put => sub { 1 }, # put all items \& Get => sub { shift() =~ /sudo\e[\ed+\e]/i }, \& ), \& ] \& ); .Ve .SS "pop" .IX Subsection "pop" Behaves like Perl's built-in \fBpop()\fR for the filter stack. The highest-indexed filter is removed from the stack and returned. Any data remaining in the filter's input buffer is lost, but an application may always call \*(L"get_pending\*(R" in POE::Filter on the returned filter. .PP .Vb 2 \& my $last_filter = $stackable\->pop(); \& my $last_buffer = $last_filter\->get_pending(); .Ve .SS "shift" .IX Subsection "shift" Behaves like Perl's built-in \fBshift()\fR for the filter stack. The 0th filter is removed from the stack and returned. Any data remaining in the filter's input buffer is passed to the new head of the stack, or it is lost if the stack becomes empty. An application may also call \&\*(L"get_pending\*(R" in POE::Filter on the returned filter to examine the filter's input buffer. .PP .Vb 2 \& my $first_filter = $stackable\->shift(); \& my $first_buffer = $first_filter\->get_pending(); .Ve .SS "push FILTER[, \s-1FILTER\s0]" .IX Subsection "push FILTER[, FILTER]" \&\fBpush()\fR adds one or more new FILTERs to the end of the stack. The newly pushed FILTERs will process input last, and they will handle output first. .PP .Vb 8 \& # Reverse data read through the stack. \& # rot13 encode data sent through the stack. \& $stackable\->push( \& POE::Filter::Map\->( \& Get => sub { return scalar reverse shift() }, \& Put => sub { local $_ = shift(); tr[a\-zA\-Z][n\-za\-mN\-ZA\-M]; $_ }, \& ) \& ); .Ve .SS "unshift FILTER[, \s-1FILTER\s0]" .IX Subsection "unshift FILTER[, FILTER]" \&\fBunshift()\fR adds one or more new FILTERs to the beginning of the stack. The newly unshifted FILTERs will process input first, and they will handle output last. .SS "filters" .IX Subsection "filters" \&\fBfilters()\fR returns a list of the filters inside the Stackable filter, in the stack's native order. .PP Calling \f(CW\*(C`$filter_stack\->filters()\*(C'\fR in the \*(L"\s-1SYNOPSIS\*(R"\s0 would return a list of two filter objects: .PP .Vb 2 \& POE::Filter::Line=ARRAY(0x8b5ee0) \& POE::Filter::Grep=ARRAY(0x8b5f7c) .Ve .SS "filter_types" .IX Subsection "filter_types" \&\fBfilter_types()\fR returns a list of class names for each filter in the stack, in the stack's native order. .PP Calling \f(CW\*(C`$filter_stack\->filter_types()\*(C'\fR in the \*(L"\s-1SYNOPSIS\*(R"\s0 would return a list of two class names: .PP .Vb 2 \& POE::FIlter::Line \& POE::Filter::Grep .Ve .PP It could easily be replaced by: .PP .Vb 1 \& my @filter_types = map { ref } $filter_stack\->filters; .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" POE::Filter for more information about filters in general. .PP Specific filters, amongst which are: POE::Filter::Block, POE::Filter::Grep, POE::Filter::HTTPD, POE::Filter::Line, POE::Filter::Map, POE::Filter::RecordBlock, POE::Filter::Reference, POE::Filter::Stream .SH "BUGS" .IX Header "BUGS" None currently known. .SH "AUTHORS & COPYRIGHTS" .IX Header "AUTHORS & COPYRIGHTS" The Stackable filter was contributed by Dieter Pearcey. Documentation provided by Rocco Caputo. .PP Please see the \s-1POE\s0 manpage for more information about authors and contributors.