1POE::Filter(3) User Contributed Perl Documentation POE::Filter(3)
2
3
4
6 POE::Filter - protocol abstractions for POE::Wheel and standalone use
7
9 To use with POE::Wheel classes, pass a POE::Filter object to one of the
10 "...Filter" constructor parameters:
11
12 #!perl
13
14 use POE qw(Filter::Line Wheel::FollowTail);
15
16 POE::Session->create(
17 inline_states => {
18 _start => sub {
19 $_[HEAP]{tailor} = POE::Wheel::FollowTail->new(
20 Filename => "/var/log/system.log",
21 InputEvent => "got_log_line",
22 Filter => POE::Filter::Line->new(),
23 );
24 },
25 got_log_line => sub {
26 print "Log: $_[ARG0]\n";
27 }
28 }
29 );
30
31 POE::Kernel->run();
32 exit;
33
34 Standalone use without POE:
35
36 #!perl
37
38 use warnings;
39 use strict;
40 use POE::Filter::Line;
41
42 my $filter = POE::Filter::Line->new( Literal => "\n" );
43
44 # Prints three lines: one, two three.
45
46 $filter->get_one_start(["one\ntwo\nthr", "ee\nfour"]);
47 while (1) {
48 my $line = $filter->get_one();
49 last unless @$line;
50 print $line->[0], "\n";
51 }
52
53 # Prints two lines: four, five.
54
55 $filter->get_one_start(["\nfive\n"]);
56 while (1) {
57 my $line = $filter->get_one();
58 last unless @$line;
59 print $line->[0], "\n";
60 }
61
63 POE::Filter objects plug into the wheels and define how the data will
64 be serialized for writing and parsed after reading. POE::Wheel objects
65 are responsible for moving data, and POE::Filter objects define how the
66 data should look.
67
68 POE::Filter objects are simple by design. They do not use POE
69 internally, so they are limited to serialization and parsing. This may
70 complicate implementation of certain protocols (like HTTP 1.x), but it
71 allows filters to be used in stand-alone programs.
72
73 Stand-alone use is very important. It allows application developers to
74 create lightweight blocking libraries that may be used as simple
75 clients for POE servers. POE::Component::IKC::ClientLite is a notable
76 example. This lightweight, blocking event-passing client supports thin
77 clients for gridded POE applications. The canonical use case is to
78 inject events into an IKC application or grid from CGI interfaces,
79 which require lightweight resource use.
80
81 POE filters and drivers pass data in array references. This is
82 slightly awkward, but it minimizes the amount of data that must be
83 copied on Perl's stack.
84
86 All POE::Filter classes must support the minimal interface, defined
87 here. Specific filters may implement and document additional methods.
88
89 new PARAMETERS
90 new() creates and initializes a new filter. Constructor parameters
91 vary from one POE::Filter subclass to the next, so please consult the
92 documentation for your desired filter.
93
94 clone
95 clone() creates and initializes a new filter based on the constructor
96 parameters of the existing one. The new filter is a near-identical
97 copy, except that its buffers are empty.
98
99 Certain components, such as POE::Component::Server::TCP, use clone().
100 These components accept a master or template filter at creation time,
101 then clone() that filter for each new connection.
102
103 my $new_filter = $old_filter->clone();
104
105 get_one_start ARRAYREF
106 get_one_start() accepts an array reference containing unprocessed
107 stream chunks. The chunks are added to the filter's internal buffer
108 for parsing by get_one().
109
110 The "SYNOPSIS" shows get_one_start() in use.
111
112 get_one
113 get_one() parses zero or one complete item from the filter's internal
114 buffer. The data is returned as an ARRAYREF suitable for passing to
115 another filter or a POE::Wheel object. Filters will return empty
116 ARRAYREFs if they don't have enough raw data to build a complete item.
117
118 get_one() is the lazy form of get(). It only parses only one item at a
119 time from the filter's buffer. This is vital for applications that may
120 switch filters in mid-stream, as it ensures that the right filter is in
121 use at any given time.
122
123 The "SYNOPSIS" shows get_one() in use. Note how it assumes the return
124 is always an ARRAYREF, and it implicitly handles empty ones.
125
126 get ARRAYREF
127 get() is the greedy form of get_one(). It accepts an array reference
128 containing unprocessed stream chunks, and it adds that data to the
129 filter's internal buffer. It then parses as many full items as
130 possible from the buffer and returns them in another array reference.
131 Any unprocessed data remains in the filter's buffer for the next call.
132
133 As with get_one(), get() will return an empty array reference if the
134 filter doesn't contain enough raw data to build a complete item.
135
136 In fact, get() is implemented in POE::Filter in terms of
137 get_one_start() and get_one().
138
139 Here's the get() form of the SYNOPSIS stand-alone example:
140
141 #!perl
142
143 use warnings;
144 use strict;
145 use POE::Filter::Line;
146
147 my $filter = POE::Filter::Line->new( Literal => "\n" );
148
149 # Prints three lines: one, two three.
150
151 my $lines = $filter->get(["one\ntwo\nthr", "ee\nfour"]);
152 foreach my $line (@$lines) {
153 print "$line\n";
154 }
155
156 # Prints two lines: four, five.
157
158 $lines = $filter->get(["\nfive\n"]);
159 foreach my $line (@$lines) {
160 print "$line\n";
161 }
162
163 get() should not be used with wheels that support filter switching.
164 Its greedy nature means that it often parses streams well in advance of
165 a wheel's events. By the time an application changes the wheel's
166 filter, it's too late: The old filter has already parsed the rest of
167 the received data.
168
169 Consider a stream of letters, numbers, and periods. The periods signal
170 when to switch filters from one that parses letters to one that parses
171 numbers.
172
173 In our hypothetical application, letters must be handled one at a time,
174 but numbers may be handled in chunks. We'll use POE::Filter::Block
175 with a BlockSize of 1 to parse letters, and POE::FIlter::Line with a
176 Literal terminator of "." to handle numbers.
177
178 Here's the sample stream:
179
180 abcdefg.1234567.hijklmnop.890.q
181
182 We'll start with a ReadWrite wheel configured to parse characters.
183
184 $_[HEAP]{wheel} = POE::Wheel::ReadWrite->new(
185 Filter => POE::Filter::Block->new( BlockSize => 1 ),
186 Handle => $socket,
187 InputEvent => "got_letter",
188 );
189
190 The "got_letter" handler will be called 8 times. One for each letter
191 from a through g, and once for the period following g. Upon receiving
192 the period, it will switch the wheel into number mode.
193
194 sub handle_letter {
195 my $letter = $_[ARG0];
196 if ($letter eq ".") {
197 $_[HEAP]{wheel}->set_filter(
198 POE::Filter::Line->new( Literal => "." )
199 );
200 $_[HEAP]{wheel}->event( InputEvent => "got_number" );
201 }
202 else {
203 print "Got letter: $letter\n";
204 }
205 }
206
207 If the greedy get() were used, the entire input stream would have been
208 parsed as characters in advance of the first handle_letter() call. The
209 set_filter() call would have been moot, since there would be no data
210 left to be parsed.
211
212 The "got_number" handler receives contiguous runs of digits as period-
213 terminated lines. The greedy get() would cause a similar problem as
214 above.
215
216 sub handle_numbers {
217 my $numbers = $_[ARG0];
218 print "Got number(s): $numbers\n";
219 $_[HEAP]->{wheel}->set_filter(
220 POE::Filter::Block->new( BlockSize => 1 )
221 );
222 $_[HEAP]->{wheel}->event( InputEvent => "got_letter" );
223 }
224
225 So don't do it!
226
227 put ARRAYREF
228 put() serializes items into a stream of octets that may be written to a
229 file or sent across a socket. It accepts a reference to a list of
230 items, and it returns a reference to a list of marshalled stream
231 chunks. The number of output chunks is not necessarily related to the
232 number of input items.
233
234 In stand-alone use, put()'s output may be sent directly:
235
236 my $line_filter = POE::Filter::Line->new();
237 my $lines = $line_filter->put(\@list_of_things);
238 foreach my $line (@$lines) {
239 print $line;
240 }
241
242 The list reference it returns may be passed directly to a driver or
243 filter. Drivers and filters deliberately share the same put()
244 interface so that things like this are possible:
245
246 $driver->put(
247 $transfer_encoding_filter->put(
248 $content_encoding_filter->put(
249 \@items
250 )
251 )
252 );
253
254 1 while $driver->flush(\*STDOUT);
255
256 get_pending
257 get_pending() returns any data remaining in a filter's input buffer.
258 The filter's input buffer is not cleared, however. get_pending()
259 returns a list reference if there's any data, or undef if the filter
260 was empty.
261
262 POE::Wheel objects use get_pending() during filter switching.
263 Unprocessed data is fetched from the old filter with get_pending() and
264 injected into the new filter with get_one_start().
265
266 use POE::Filter::Line;
267 use POE::Filter::Stream;
268
269 my $line_filter = POE::Filter::Line->new();
270 $line_filter->get_one_start([ "not a complete line" ]);
271
272 my $stream_filter = POE::Filter::Stream->new();
273 my $line_buffer = $line_filter->get_pending();
274 $stream_filter->get_one_start($line_buffer) if $line_buffer;
275
276 print "Stream: $_\n" foreach (@{ $stream_filter->get_one });
277
278 Full items are serialized whole, so there is no corresponding "put"
279 buffer or accessor.
280
282 The SEE ALSO section in POE contains a table of contents covering the
283 entire POE distribution.
284
285 POE is bundled with the following filters:
286
287 POE::Filter::Block POE::Filter::Grep POE::Filter::HTTPD
288 POE::Filter::Line POE::Filter::Map POE::Filter::RecordBlock
289 POE::Filter::Reference POE::Filter::Stackable POE::Filter::Stream
290
292 In theory, filters should be interchangeable. In practice, stream and
293 block protocols tend to be incompatible.
294
296 Please see POE for more information about authors and contributors.
297
298
299
300perl v5.32.0 2020-07-28 POE::Filter(3)