File Coverage

blib/lib/Compress/LZF_PP.pm
Criterion Covered Total %
statement 51 72 70.8
branch 16 24 66.6
condition n/a
subroutine 3 3 100.0
pod 0 1 0.0
total 70 100 70.0


line stmt bran cond sub pod time code
1             package Compress::LZF_PP;
2 1     1   781 use strict;
  1         1  
  1         35  
3 1     1   5 use warnings;
  1         2  
  1         836  
4             our $VERSION = '0.33';
5             our @ISA = qw(Exporter);
6             our @EXPORT = qw(decompress);
7              
8             my $DEBUG = 0;
9              
10             sub decompress {
11 10     10 0 7927 my $in_data = shift;
12 10         16 my $in_len = length($in_data);
13 10         13 my $out_data = '';
14 10         13 my $out_len = 0;
15              
16 10         8 my $iidx = 0;
17 10         11 my $oidx = 0;
18              
19 10         31 my $length0 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
20 10 100       42 if ( $length0 == 0 ) {
    100          
    100          
    100          
    50          
    0          
    0          
21 2         8 return substr( $in_data, 1, $in_len - 1 );
22             } elsif ( !( $length0 & 0x80 ) ) {
23 4         6 $out_len = $length0 & 0xff;
24             } elsif ( !( $length0 & 0x20 ) ) {
25 1         2 my $length1 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
26 1         2 $out_len = ( $out_len << 6 ) | ( $length1 & 0x3f );
27             } elsif ( !( $length0 & 0x10 ) ) {
28 2         3 my $length1 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
29 2         4 my $length2 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
30 2         2 $out_len = $length0 & 0x1f;
31 2         3 $out_len = ( $out_len << 6 ) | ( $length1 & 0x3f );
32 2         3 $out_len = ( $out_len << 6 ) | ( $length2 & 0x3f );
33             } elsif ( !( $length0 & 0x08 ) ) {
34 1         3 my $length1 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
35 1         4 my $length2 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
36 1         3 my $length3 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
37 1         2 $out_len = $length0 & 0x1f;
38 1         4 $out_len = ( $out_len << 6 ) | ( $length1 & 0x3f );
39 1         3 $out_len = ( $out_len << 6 ) | ( $length2 & 0x3f );
40 1         2 $out_len = ( $out_len << 6 ) | ( $length3 & 0x3f );
41             } elsif ( !( $length0 & 0x04 ) ) {
42 0         0 my $length1 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
43 0         0 my $length2 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
44 0         0 my $length3 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
45 0         0 my $length4 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
46 0         0 $out_len = $length0 & 0x1f;
47 0         0 $out_len = ( $out_len << 6 ) | ( $length1 & 0x3f );
48 0         0 $out_len = ( $out_len << 6 ) | ( $length2 & 0x3f );
49 0         0 $out_len = ( $out_len << 6 ) | ( $length3 & 0x3f );
50 0         0 $out_len = ( $out_len << 6 ) | ( $length4 & 0x3f );
51             } elsif ( !( $length0 & 0x02 ) ) {
52 0         0 my $length1 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
53 0         0 my $length2 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
54 0         0 my $length3 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
55 0         0 my $length4 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
56 0         0 my $length5 = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
57 0         0 $out_len = $length0 & 0x1f;
58 0         0 $out_len = ( $out_len << 6 ) | ( $length1 & 0x3f );
59 0         0 $out_len = ( $out_len << 6 ) | ( $length2 & 0x3f );
60 0         0 $out_len = ( $out_len << 6 ) | ( $length3 & 0x3f );
61 0         0 $out_len = ( $out_len << 6 ) | ( $length4 & 0x3f );
62 0         0 $out_len = ( $out_len << 6 ) | ( $length5 & 0x3f );
63             } else {
64 0         0 die "Unsupported length";
65             }
66              
67 8         21 while ( $iidx < $in_len ) {
68 2124         4944 my $ctrl = unpack( 'C', substr( $in_data, $iidx++, 1 ) );
69              
70 2124 50       4127 warn "$iidx, $oidx control $ctrl [[$out_data]]" if $DEBUG;
71              
72 2124 100       3752 if ( $ctrl < ( 1 << 5 ) ) {
73 15         13 $ctrl++;
74 15         22 my $toadd = substr( $in_data, $iidx, $ctrl );
75 15 50       27 warn " literal run $ctrl [$toadd]" if $DEBUG;
76 15         19 $out_data .= $toadd;
77 15         14 $oidx += $ctrl;
78 15         27 $iidx += $ctrl;
79             } else {
80 2109         2362 my $len = $ctrl >> 5;
81 2109         8137 my $reference = ( $oidx - ( ( $ctrl & 0x1f ) << 8 ) - 1 );
82 2109 100       3617 if ( $len == 7 ) {
83 2108         3919 $len += unpack( 'C', substr( $in_data, $iidx++, 1 ) );
84             }
85 2109         3669 $reference -= unpack( 'C', substr( $in_data, $iidx++, 1 ) );
86 2109 50       3694 warn " back reference $reference $len" if $DEBUG;
87 2109         2160 $oidx += $len - 3;
88 2109         2139 $len += 3;
89              
90 2109         3801 while ( --$len != 0 ) {
91 555548         969490 $out_data .= substr( $out_data, $reference++, 1 );
92             }
93             }
94             }
95 8         1042 return $out_data;
96             }
97              
98             1;
99              
100             __END__