X-Git-Url: http://git.shiar.nl/wormy.git/blobdiff_plain/aac9f02cab2d03379669c2f278d62330151d44e0..6d64bb2aa29809c9c24fb5ee036766440b62bf4a:/Parse/Binary/Nested.pm diff --git a/Parse/Binary/Nested.pm b/Parse/Binary/Nested.pm deleted file mode 100644 index 9bac394..0000000 --- a/Parse/Binary/Nested.pm +++ /dev/null @@ -1,129 +0,0 @@ -package Parse::Binary::Nested; - -use strict; -use warnings; - -use Carp; - -our $VERSION = '1.00'; - -sub new { - my ($class, $format) = @_; - ref $format eq 'ARRAY' - or croak "Invalid Parse::Binary::Nested format: should be an array ref"; - bless $format, $class; -} - -sub template { - my ($self, $format) = @_; - # total (flattened) unpack template from nested format definitions - return join '', map { - my $value = $format->[-($_ << 1) - 1]; - if (ref $value eq 'ARRAY') { - my $count = $value->[0]; - $value = $self->template($value); - $value = $count =~ s/^([*\d]+)// ? "$count($value)$1" - : $count."X[$count]$count/($value)"; - } - else { - $value =~ s/^C(a)(\d+)/$1 . ($2 + 1)/e; # length prefix - } - $value; - } reverse 0 .. ($#$format - 1) >> 1; -} - -sub convert { - my ($self, $format, $data) = @_; - # map flat results into a named and nested hash - my %res; - while (my ($field, $template) = splice @$format, 0, 2) { - if (ref $template eq 'ARRAY') { - my ($count, @subformat) = @$template; - my $max = $count =~ s/^(\d+)// ? $1 : 0; - $count = !$count ? $max - : $count eq '*' ? $res{levelcount}->{total} : shift @$data; - $res{$field}->[$_] = $self->convert([@subformat], $data) for 0 .. ($max || $count)-1; - splice @{ $res{$field} }, $count if $max > $count; - $res{$field} = $res{$field}->[0] if $max == 1; - next; - } - elsif ($template =~ /^Ca/) { - $data->[0] = unpack 'C/a', $data->[0]; - } - elsif ($template =~ /^(?:[xX]\d*)*$/) { - next; # no values - } - $res{$field} = shift @$data; - } - return \%res; -} - -sub unpackf { - my ($self, $input) = @_; - my @data = unpack $self->template($self), $input; - return $self->convert([@$self], \@data); -} - -1; - -=head1 NAME - -Parse::Binary::Nested - Structured unpack - -=head1 SYNOPSIS - - use Parse::Binary::Nested; - my $parser = Parser::Binary::Nested->new([ - foos => [ - 'C', # count - message => 'Z*', - period => 'C', - ], - trail => 'a*', - ]); - - my $data = $parser->unpackf("\1foo\0.rest"); - print $data->{foos}->[0]->{message}; - -=head1 DESCRIPTION - -Converts a string into a hash of values, just like C -except that it allows you to name and nest the resulting elements. - -Format declarations are simalar to C templates, -with the following additions: - -=over - -=item * - -An array ref groups additional declarations, -with the first value specifying a repetition. If this count is variable, -the resulting value will be an array ref of hashes. - - repeat => ['C', name => 'a*', value => 'S'] - -With a count of 1, it will return only a hash ref, -thereby simply grouping declarations: - - test_foo => 'C' - test => [1, foo => 'C'] - -=item * - -A template value of C is recognised as a length-preceded string -with a constant (maximal) size, and will return only the string adjusted -to its length. -This behaviour is very similar to C<(C/a@x$length)>, except that it never reads -more than the given number of bytes. - -=back - -=head1 AUTHOR - -Mischa POSLAWSKY - -=head1 LICENSE - -GPL version 3. -