AnyEvent-PacketReader
view release on metacpan or search on metacpan
lib/AnyEvent/PacketReader.pm view on Meta::CPAN
package AnyEvent::PacketReader;
our $VERSION = '0.01';
use strict;
use warnings;
use 5.010;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(packet_reader);
use AnyEvent;
use Carp;
use Errno qw(EPIPE EBADMSG EMSGSIZE EINTR EAGAIN EWOULDBLOCK);
our $MAX_TOTAL_LENGTH = 1e6;
our $debug;
my %header_length = ( n => 2,
v => 2,
N => 4,
V => 4,
W => 1,
S => 2,
L => 4,
Q => 8 );
for my $dir (qw(> <)) {
for my $t (qw(S L Q)) {
$header_length{"$t$dir"} = $header_length{$t};
}
}
my %short_templ = map { $_ => $_ } keys %header_length;
my %load_offset = %header_length;
my $good_packers = join '', keys %header_length;
use Data::Dumper;
$SIG{INT} = sub {
print Data::Dumper->Dump([\%short_templ, \%header_length, \%load_offset], [qw(%short_templ %header_length %load_offset)]);
exit 1;
};
sub packet_reader {
my $cb = pop;
my ($fh, $templ, $max_total_length) = @_;
croak 'Usage: packet_reader($fh, [$templ, [$max_total_length,]] $callback)'
unless defined $fh and defined $cb;
$max_total_length ||= $MAX_TOTAL_LENGTH;
my ($header_length, $load_offset, $short_templ);
if (defined $templ) {
unless (defined($short_templ = $short_templ{$templ})) {
$debug and warn "PR: examining template '$templ'\n";
my $load_offset;
if ($templ =~ /^(x+)(\d*)/g) {
$header_length = length($1) + (length $2 ? $2 - 1 : 0);
}
elsif ($templ =~ /^\@!(\d*)/g) {
$header_length = (length $1 ? $1 : 1);
}
else {
$header_length = 0;
}
$templ =~ /\G([$good_packers][<>]?)/go
or croak "bad header template '$templ'";
$header_length += ($header_length{$1} // die "Internal error: \$header_length{$1} is not defined");
$short_templ = substr $templ, 0, pos($templ);
if ($templ =~ /\G\@!(\d*)/g) {
$load_offset = (length $1 ? $1 : 1);
}
else {
$load_offset = $header_length;
if ($templ =~ /\G(x+)(\d*)/g) {
$load_offset += length $1 + (length $2 ? $2 - 1 : 0);
}
}
$templ =~ /\G$/g or croak "bad header template '$templ'";
$short_templ{$templ} = $short_templ;
$header_length{$templ} = $header_length;
$load_offset{$templ} = $load_offset;
$debug and warn "PR: template '$templ' examined, header_length: $header_length, load_offset: $load_offset\n";
}
$header_length = $header_length{$templ};
$load_offset = $load_offset{$templ};
}
else {
$debug and warn "PR: defaulting to template 'N'\n";
$templ = 'N';
$header_length = 4;
( run in 0.541 second using v1.01-cache-2.11-cpan-39bf76dae61 )