1# 2001/01/25 shizukesa@pobox.com 2 3package POE::Filter::RecordBlock; 4 5use strict; 6use POE::Filter; 7 8use vars qw($VERSION @ISA); 9$VERSION = '1.368'; # NOTE - Should be #.### (three decimal places) 10@ISA = qw(POE::Filter); 11 12use Carp qw(croak); 13 14sub BLOCKSIZE () { 0 }; 15sub GETBUFFER () { 1 }; 16sub PUTBUFFER () { 2 }; 17sub CHECKPUT () { 3 }; 18sub FIRST_UNUSED () { 4 } 19 20use base 'Exporter'; 21our @EXPORT_OK = qw( FIRST_UNUSED ); 22 23 24#------------------------------------------------------------------------------ 25 26sub new { 27 my $type = shift; 28 29 croak "$type must be given an even number of parameters" if @_ & 1; 30 my %params = @_; 31 32 # Block size 33 croak "BlockSize must be greater than 0" unless ( 34 defined($params{BlockSize}) && ($params{BlockSize} > 0) 35 ); 36 my $block_size = $params{BlockSize}; 37 38 # check put 39 my $check_put = $params{CheckPut}; 40 41 delete @params{ qw( BlockSize CheckPut ) }; 42 carp("$type ignores unknown parameters: ", join(', ', sort keys %params)) 43 if scalar keys %params; 44 45 my $self = bless [ 46 $block_size, # BLOCKSIZE 47 [], # GETBUFFER 48 [], # PUTBUFFER 49 $check_put # CHECKPUT 50 ], $type; 51} 52 53sub clone { 54 my $self = shift; 55 my $clone = bless [ 56 $self->[0], # BLOCKSIZE 57 [], # GETBUFFER 58 [], # PUTBUFFER 59 $self->[3] # CHECKPUT 60 ], ref $self; 61 $clone; 62} 63 64#------------------------------------------------------------------------------ 65# get() is inherited from POE::Filter. 66 67#------------------------------------------------------------------------------ 68# 2001-07-27 RCC: Add get_one_start() and get_one() to correct filter 69# changing and make input flow control possible. 70 71sub get_one_start { 72 my ($self, $data) = @_; 73 push @{$self->[GETBUFFER]}, @$data; 74} 75 76sub get_one { 77 my $self = shift; 78 79 return [ ] unless @{$self->[GETBUFFER]} >= $self->[BLOCKSIZE]; 80 return [ [ splice @{$self->[GETBUFFER]}, 0, $self->[BLOCKSIZE] ] ]; 81} 82 83#------------------------------------------------------------------------------ 84 85sub put { 86 my ($self, $data) = @_; 87 my @result; 88 89 if ($self->[CHECKPUT]) { 90 foreach (@$data) { 91 push @{$self->[PUTBUFFER]}, @$_; 92 } 93 while (@{$self->[PUTBUFFER]} >= $self->[BLOCKSIZE]) { 94 push @result, splice @{$self->[PUTBUFFER]}, 0, $self->[BLOCKSIZE]; 95 } 96 } 97 else { 98 push @result, splice(@{$self->[PUTBUFFER]}, 0); 99 foreach (@$data) { 100 push @result, @$_; 101 } 102 } 103 \@result; 104} 105 106#------------------------------------------------------------------------------ 107 108sub get_pending { 109 my $self = shift; 110 return undef unless @{$self->[GETBUFFER]}; 111 return [ @{$self->[GETBUFFER]} ]; 112} 113 114#------------------------------------------------------------------------------ 115 116sub put_pending { 117 my ($self) = @_; 118 return undef unless $self->[CHECKPUT]; 119 return undef unless @{$self->[PUTBUFFER]}; 120 return [ @{$self->[PUTBUFFER]} ]; 121} 122 123#------------------------------------------------------------------------------ 124 125sub blocksize { 126 my ($self, $size) = @_; 127 if (defined($size) && ($size > 0)) { 128 $self->[BLOCKSIZE] = $size; 129 } 130 $self->[BLOCKSIZE]; 131} 132 133#------------------------------------------------------------------------------ 134 135sub checkput { 136 my ($self, $val) = @_; 137 if (defined($val)) { 138 $self->[CHECKPUT] = $val; 139 } 140 $self->[CHECKPUT]; 141} 142 1431; 144 145__END__ 146 147=head1 NAME 148 149POE::Filter::RecordBlock - translate between discrete records and blocks of them 150 151=head1 SYNOPSIS 152 153Hello, dear reader. This SYNOPSIS does not contain a fully 154functioning sample program because your humble documenter cannot come 155up with a short, reasonable use case for this module. Please contact 156the maintainer if this module is useful to you. Otherwise you may wake 157up one morning to discover that it has been deprecated. 158 159 $filter = new POE::Filter::RecordBlock( BlockSize => 4 ); 160 $arrayref_of_arrayrefs = $filter->get($arrayref_of_raw_data); 161 $arrayref_of_raw_chunks = $filter->put($arrayref_of_arrayrefs); 162 $arrayref_of_raw_chunks = $filter->put($single_arrayref); 163 $arrayref_of_leftovers = $filter->get_pending; 164 $arrayref_of_leftovers = $filter->put_pending; 165 166=head1 DESCRIPTION 167 168On input, POE::Filter::RecordBlock translates a stream of discrete 169items into a "block" of them. It does this by collecting items until 170it has BlockSize of them, then returning the lot of them in an array 171reference. 172 173On output, this module flattens array references. 174 175This module may be deprecated in the future. Please contact the 176maintainer if this module is useful to you. 177 178=head1 PUBLIC FILTER METHODS 179 180In addition to the usual POE::Filter methods, POE::Filter::RecordBlock 181supports the following. 182 183=head2 new 184 185new() takes at least one mandatory argument, BlockSize, which must be 186defined and greater than zero. new() also accepts a CheckPut Boolean 187parameter that indicates whether put() should check for the proper 188BlockSize before allowing data to be serialized. 189 190Using CheckPut is not recommended, as it enables a write buffer in the 191filter, therefore breaking put() for normal use. 192 193=head2 put_pending 194 195put_pending() returns an arrayref of any records that are waiting to 196be sent. It is the outbound equivalent of POE::Filter's get_pending() 197accessor. put_pending() is not part of the canonical POE::Filter API, 198so nothing will use it. It's up to applications to handle pending 199output, whenever it's appropriate to do so. 200 201=head2 blocksize 202 203blocksize() is an accessor/mutator for POE::Filter::RecordBlock's 204BlockSize value. 205 206=head2 checkput 207 208checkput() is an accessor/mutator for POE::Filter::RecordBlock's 209CheckPut flag. 210 211=head1 SEE ALSO 212 213L<POE::Filter> for more information about filters in general. 214 215L<POE::Filter::Stackable> for more details on stacking filters. 216 217=head1 BUGS 218 219This filter may maintain an output buffer that no other part of POE 220will know about. 221 222This filter implements a highly specialized and seemingly not 223generally useful feature. 224 225Does anyone use this filter? This filter may be deprecated if nobody 226speaks up. 227 228=head1 AUTHORS & COPYRIGHTS 229 230The RecordBlock filter was contributed by Dieter Pearcey. 231Documentation is provided by Rocco Caputo. 232 233Please see the L<POE> manpage for more information about authors and 234contributors. 235 236=cut 237 238# rocco // vim: ts=2 sw=2 expandtab 239# TODO - Edit. 240