File Coverage

blib/lib/Data/BitStream/Code/Varint.pm
Criterion Covered Total %
statement 14 53 26.4
branch 0 26 0.0
condition 0 3 0.0
subroutine 5 7 71.4
pod 0 2 0.0
total 19 91 20.8


line stmt bran cond sub pod time code
1             package Data::BitStream::Code::Varint;
2 28     28   21656 use strict;
  28         66  
  28         1161  
3 28     28   500 use warnings;
  28         68  
  28         1527  
4             BEGIN {
5 28     28   107 $Data::BitStream::Code::Varint::AUTHORITY = 'cpan:DANAJ';
6 28         2794 $Data::BitStream::Code::Varint::VERSION = '0.08';
7             }
8              
9             our $CODEINFO = { package => __PACKAGE__,
10             name => 'Varint',
11             universal => 1,
12             params => 0,
13             encodesub => sub {shift->put_varint(@_)},
14             decodesub => sub {shift->get_varint(@_)}, };
15              
16 28     28   171 use Moo::Role;
  28         222  
  28         222  
17             requires qw(maxbits read write);
18              
19             # base-128 encoding, LSB first.
20             # This is the Unsigned LEB128 format used in DWARF and numerous other places.
21             # It is called Varint or Varint-128 by Google.
22             # It is an endian reverse of the ASN.1 BER format.
23             # The Perl Sereal module uses this format.
24              
25             # Very fast to parse (especially in C), but lousy space usage compared to
26             # most other VLCs. It has advantages in being byte aligned and
27             # restart-friendly. Fibonacci codes have the latter property but not the
28             # first. UTF-8 is an example of variable length coding that uses both
29             # properties to advantage.
30             #
31             # Since it is byte-aligned, the results should be amenable to compression
32             # with byte compressors such as Snappy, ZLIB, BZIP, 7ZIP, etc.
33              
34             sub put_varint {
35 0     0 0   my $self = shift;
36 0 0         $self->error_stream_mode('write') unless $self->writing;
37              
38 0           foreach my $val (@_) {
39 0 0 0       $self->error_code('zeroval') unless defined $val and $val >= 0;
40             # Coalesce calls to write for small numbers.
41 0 0         if ($val <= 127) {
    0          
    0          
42 0           $self->write(8, $val);
43             } elsif ($val <= 16383) {
44 0           $self->write(16, 0x00008000
45             | (($val & 0x7F) << 8)
46             | ($val >> 7) );
47             } elsif ($val <= 2097151) {
48 0           $self->write(24, 0x00808000
49             | (($val & 0x7F) << 16)
50             | ((($val >> 7) & 0x7F) << 8)
51             | ($val >> 14) );
52             } else {
53 0           my $v = $val;
54 0           while ($v > 127) {
55 0           $self->write(8, ($v & 0x7F) | 0x80);
56 0           $v >>= 7;
57             }
58 0           $self->write(8, $v);
59             }
60             }
61 0           1;
62             }
63              
64             sub get_varint {
65 0     0 0   my $self = shift;
66 0 0         $self->error_stream_mode('read') if $self->writing;
67 0           my $count = shift;
68 0 0         if (!defined $count) { $count = 1; }
  0 0          
    0          
69 0           elsif ($count < 0) { $count = ~0; } # Get everything
70 0           elsif ($count == 0) { return; }
71              
72 0           my @vals;
73 0           my $maxbits = $self->maxbits;
74 0           $self->code_pos_start('varint');
75 0           while ($count-- > 0) {
76 0           $self->code_pos_set;
77 0           my $byte = $self->read(8);
78 0 0         last unless defined $byte;
79 0           my $val = $byte & 0x7F;
80 0           my $shift = 7;
81 0           while ($byte > 127) {
82 0           $byte = $self->read(8);
83 0 0         $self->error_off_stream unless defined $byte;
84 0 0         $self->error_code('overflow') if $shift > $maxbits;
85 0           $val |= ($byte & 0x7F) << $shift;
86 0           $shift += 7;
87             }
88 0           push @vals, $val;
89             }
90 0           $self->code_pos_end;
91 0 0         wantarray ? @vals : $vals[-1];
92             }
93 28     28   25003 no Moo::Role;
  28         65  
  28         176  
94             1;