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; |