| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Data::BitStream::Base; |
|
2
|
28
|
|
|
28
|
|
372573
|
use strict; |
|
|
28
|
|
|
|
|
84
|
|
|
|
28
|
|
|
|
|
1213
|
|
|
3
|
28
|
|
|
28
|
|
195
|
use warnings; |
|
|
28
|
|
|
|
|
327
|
|
|
|
28
|
|
|
|
|
916
|
|
|
4
|
28
|
|
|
28
|
|
159
|
use Carp; |
|
|
28
|
|
|
|
|
49
|
|
|
|
28
|
|
|
|
|
3276
|
|
|
5
|
|
|
|
|
|
|
BEGIN { |
|
6
|
28
|
|
|
28
|
|
68
|
$Data::BitStream::Base::AUTHORITY = 'cpan:DANAJ'; |
|
7
|
28
|
|
|
|
|
5937
|
$Data::BitStream::Base::VERSION = '0.08'; |
|
8
|
|
|
|
|
|
|
} |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our $CODEINFO = [ { package => __PACKAGE__, |
|
11
|
|
|
|
|
|
|
name => 'Unary', |
|
12
|
|
|
|
|
|
|
universal => 0, |
|
13
|
|
|
|
|
|
|
params => 0, |
|
14
|
|
|
|
|
|
|
encodesub => sub {shift->put_unary(@_)}, |
|
15
|
|
|
|
|
|
|
decodesub => sub {shift->get_unary(@_)}, |
|
16
|
|
|
|
|
|
|
}, |
|
17
|
|
|
|
|
|
|
{ package => __PACKAGE__, |
|
18
|
|
|
|
|
|
|
name => 'Unary1', |
|
19
|
|
|
|
|
|
|
universal => 0, |
|
20
|
|
|
|
|
|
|
params => 0, |
|
21
|
|
|
|
|
|
|
encodesub => sub {shift->put_unary1(@_)}, |
|
22
|
|
|
|
|
|
|
decodesub => sub {shift->get_unary1(@_)}, |
|
23
|
|
|
|
|
|
|
}, |
|
24
|
|
|
|
|
|
|
{ package => __PACKAGE__, |
|
25
|
|
|
|
|
|
|
name => 'BinWord', |
|
26
|
|
|
|
|
|
|
universal => 0, |
|
27
|
|
|
|
|
|
|
params => 1, |
|
28
|
|
|
|
|
|
|
encodesub => sub {shift->put_binword(@_)}, |
|
29
|
|
|
|
|
|
|
decodesub => sub {shift->get_binword(@_)}, |
|
30
|
|
|
|
|
|
|
}, |
|
31
|
|
|
|
|
|
|
]; |
|
32
|
|
|
|
|
|
|
|
|
33
|
28
|
|
|
28
|
|
196
|
use Moo::Role; |
|
|
28
|
|
|
|
|
62
|
|
|
|
28
|
|
|
|
|
208
|
|
|
34
|
28
|
|
|
28
|
|
49133
|
use MooX::Types::MooseLike::Base qw/Int Bool Str ArrayRef/; |
|
|
28
|
|
|
|
|
190482
|
|
|
|
28
|
|
|
|
|
23644
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# pos is ignored while writing |
|
37
|
|
|
|
|
|
|
has 'pos' => (is => 'ro', writer => '_setpos', default => sub{0}); |
|
38
|
|
|
|
|
|
|
has 'len' => (is => 'ro', writer => '_setlen', default => sub{0}); |
|
39
|
|
|
|
|
|
|
has 'mode' => (is => 'rw', default => sub{'rdwr'}); |
|
40
|
|
|
|
|
|
|
has '_code_pos_array' => (is => 'rw', |
|
41
|
|
|
|
|
|
|
isa => ArrayRef[Int], |
|
42
|
|
|
|
|
|
|
default => sub {[]} ); |
|
43
|
|
|
|
|
|
|
has '_code_str_array' => (is => 'rw', |
|
44
|
|
|
|
|
|
|
isa => ArrayRef[Str], |
|
45
|
|
|
|
|
|
|
default => sub {[]} ); |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
has 'file' => (is => 'ro', writer => '_setfile'); |
|
48
|
|
|
|
|
|
|
has 'fheader' => (is => 'ro', writer => '_setfheader'); |
|
49
|
|
|
|
|
|
|
has 'fheaderlines' => (is => 'ro'); |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
has 'writing' => (is => 'ro', isa => Bool, writer => '_setwrite', default => sub {1}); |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# Useful for testing, but time consuming. Not so bad now that all the test |
|
54
|
|
|
|
|
|
|
# suites call put_* ~30 times with a list instead of per-value ~30,000 times. |
|
55
|
|
|
|
|
|
|
# It still makes the test suite take about 20% longer. |
|
56
|
|
|
|
|
|
|
# |
|
57
|
|
|
|
|
|
|
# after '_setpos' => sub { |
|
58
|
|
|
|
|
|
|
# my $self = shift; |
|
59
|
|
|
|
|
|
|
# my $pos = $self->pos; |
|
60
|
|
|
|
|
|
|
# my $len = $self->len; |
|
61
|
|
|
|
|
|
|
# die "position must be >= 0" if $pos < 0; |
|
62
|
|
|
|
|
|
|
# die "position must be <= length" if $pos > $len; |
|
63
|
|
|
|
|
|
|
# $pos; |
|
64
|
|
|
|
|
|
|
# }; |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub BUILD { |
|
67
|
1648
|
|
|
1648
|
0
|
94401
|
my $self = shift; |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# Looks like some systems aren't setting these correctly via the default. |
|
70
|
|
|
|
|
|
|
# I cannot reproduce the issue even with the same versions of Perl, Moo, |
|
71
|
|
|
|
|
|
|
# and Class::XSAccessor. So, we'll set them here. |
|
72
|
1648
|
|
|
|
|
8908
|
$self->_code_pos_array([]); |
|
73
|
1648
|
|
|
|
|
201904
|
$self->_code_str_array([]); |
|
74
|
1648
|
|
|
|
|
182312
|
$self->_setpos(0); |
|
75
|
1648
|
|
|
|
|
5606
|
$self->_setlen(0); |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# Change mode to canonical form |
|
78
|
1648
|
|
|
|
|
5491
|
my $curmode = $self->mode; |
|
79
|
1648
|
|
|
|
|
2946
|
my $is_writing; |
|
80
|
1648
|
50
|
|
|
|
16706
|
if ($curmode eq 'read') { $curmode = 'r'; } |
|
|
0
|
50
|
|
|
|
0
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
0
|
elsif ($curmode eq 'readonly') { $curmode = 'ro'; } |
|
82
|
0
|
|
|
|
|
0
|
elsif ($curmode eq 'write') { $curmode = 'w'; } |
|
83
|
0
|
|
|
|
|
0
|
elsif ($curmode eq 'writeonly') { $curmode = 'wo'; } |
|
84
|
0
|
|
|
|
|
0
|
elsif ($curmode eq 'readwrite') { $curmode = 'rw'; } |
|
85
|
1647
|
|
|
|
|
3701
|
elsif ($curmode eq 'rdwr') { $curmode = 'rw'; } |
|
86
|
0
|
|
|
|
|
0
|
elsif ($curmode eq 'append') { $curmode = 'a'; } |
|
87
|
1648
|
100
|
|
|
|
10498
|
die "Unknown mode: $curmode" unless $curmode =~ /^(?:r|ro|w|wo|rw|a)$/; |
|
88
|
1647
|
|
|
|
|
5058
|
$self->mode( $curmode ); |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# Set writing based on mode |
|
91
|
1647
|
50
|
|
|
|
14564
|
if ($curmode =~ /^ro?$/) { $is_writing = 0; } |
|
|
0
|
50
|
|
|
|
0
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
0
|
elsif ($curmode =~ /^wo?$/) { $is_writing = 1; } |
|
93
|
1647
|
|
|
|
|
4636
|
elsif ($curmode eq 'rw') { $is_writing = 1; } |
|
94
|
0
|
|
|
|
|
0
|
elsif ($curmode eq 'a') { $is_writing = 0; } |
|
95
|
|
|
|
|
|
|
|
|
96
|
1647
|
50
|
|
|
|
4467
|
if ($is_writing) { |
|
97
|
1647
|
|
|
|
|
7868
|
$self->_setwrite(1); |
|
98
|
1647
|
|
|
|
|
140400
|
$self->write_open; |
|
99
|
|
|
|
|
|
|
} else { |
|
100
|
0
|
|
|
|
|
0
|
$self->_setwrite(0); |
|
101
|
0
|
|
|
|
|
0
|
$self->read_open; |
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
|
|
104
|
1647
|
50
|
|
|
|
39579
|
$self->write_open if $curmode eq 'a'; |
|
105
|
|
|
|
|
|
|
# TODO: writeonly doesn't really work |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub DEMOLISH { |
|
109
|
1648
|
|
|
1648
|
0
|
2590995
|
my $self = shift; |
|
110
|
1648
|
100
|
|
|
|
39203
|
$self->write_close if $self->writing; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
my $_host_word_size; # maxbits |
|
114
|
|
|
|
|
|
|
my $_all_ones; # maxval |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
BEGIN { |
|
117
|
28
|
|
|
28
|
|
314
|
use Config; |
|
|
28
|
|
|
|
|
56
|
|
|
|
28
|
|
|
|
|
3296
|
|
|
118
|
28
|
50
|
0
|
28
|
|
29980
|
$_host_word_size = |
|
119
|
|
|
|
|
|
|
( (defined $Config{'use64bitint'} && $Config{'use64bitint'} eq 'define') |
|
120
|
|
|
|
|
|
|
|| (defined $Config{'use64bitall'} && $Config{'use64bitall'} eq 'define') |
|
121
|
|
|
|
|
|
|
|| (defined $Config{'longsize'} && $Config{'longsize'} >= 8) |
|
122
|
|
|
|
|
|
|
) |
|
123
|
|
|
|
|
|
|
? 64 |
|
124
|
|
|
|
|
|
|
: 32; |
|
125
|
28
|
|
|
28
|
|
176
|
no Config; |
|
|
28
|
|
|
|
|
76
|
|
|
|
28
|
|
|
|
|
3382
|
|
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# Check sanity of ~0 |
|
128
|
28
|
|
|
|
|
101920
|
my $notzero = ~0; |
|
129
|
28
|
50
|
|
|
|
137
|
if ($_host_word_size == 32) { |
|
130
|
0
|
|
|
|
|
0
|
die "Config says 32-bit Perl, but int is $notzero" if ~0 != 0xFFFFFFFF; |
|
131
|
|
|
|
|
|
|
} else { |
|
132
|
28
|
|
|
|
|
72
|
die "Config says 64-bit Perl, but int is $notzero" if ((~0 >> 16) >> 16) != 0xFFFFFFFF; |
|
133
|
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# 64-bit seems broken in Perl 5.6.2 on the 32-bit system I have (and at |
|
136
|
|
|
|
|
|
|
# least one CPAN Tester shows the same). Try: |
|
137
|
|
|
|
|
|
|
# perl -e 'die if 18446744073709550593 == ~0' |
|
138
|
|
|
|
|
|
|
# That inexplicably dies on 64-bit 5.6.2. It works fine on 5.8.0 and later. |
|
139
|
|
|
|
|
|
|
# |
|
140
|
|
|
|
|
|
|
# Direct method, pre-5.8.0 Perls. |
|
141
|
|
|
|
|
|
|
# $_host_word_size = 32 if $] < 5.008; |
|
142
|
|
|
|
|
|
|
# Detect the symptoms (should allow 5.6.2 on 64-bit O/S to work fine): |
|
143
|
28
|
50
|
50
|
|
|
266
|
if ( ($_host_word_size == 64) && (18446744073709550592 == ~0) ) { |
|
144
|
0
|
|
|
|
|
0
|
$_host_word_size = 32; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
28
|
50
|
|
|
|
150011
|
$_all_ones = ($_host_word_size == 32) ? 0xFFFFFFFF : ~0; |
|
148
|
|
|
|
|
|
|
} |
|
149
|
|
|
|
|
|
|
# Moo 1.000007 doesn't allow inheritance of 'use constant'. |
|
150
|
|
|
|
|
|
|
#use constant maxbits => $_host_word_size; |
|
151
|
|
|
|
|
|
|
#use constant maxval => $_all_ones; |
|
152
|
|
|
|
|
|
|
# Use a sub with empty prototype (see perlsub documentation) |
|
153
|
1105889
|
|
|
1105889
|
1
|
9807369
|
sub maxbits () { $_host_word_size } ## no critic (ProhibitSubroutinePrototypes) |
|
154
|
92500
|
|
|
92500
|
1
|
250918
|
sub maxval () { $_all_ones } ## no critic (ProhibitSubroutinePrototypes) |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub rewind { |
|
157
|
30205
|
|
|
30205
|
1
|
823130
|
my $self = shift; |
|
158
|
30205
|
100
|
|
|
|
79346
|
$self->error_stream_mode('rewind') if $self->writing; |
|
159
|
30204
|
|
|
|
|
50125
|
$self->_setpos(0); |
|
160
|
30204
|
|
|
|
|
62646
|
1; |
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
sub skip { |
|
163
|
77787
|
|
|
77787
|
1
|
105653
|
my $self = shift; |
|
164
|
77787
|
100
|
|
|
|
218445
|
$self->error_stream_mode('skip') if $self->writing; |
|
165
|
77786
|
|
|
|
|
100375
|
my $skip = shift; |
|
166
|
77786
|
|
|
|
|
139660
|
my $pos = $self->pos; |
|
167
|
77786
|
|
|
|
|
117010
|
my $len = $self->len; |
|
168
|
77786
|
|
|
|
|
95925
|
my $newpos = $pos + $skip; |
|
169
|
77786
|
100
|
66
|
|
|
379723
|
$self->error_off_stream('skip') if $newpos < 0 || $newpos > $len; |
|
170
|
77776
|
|
|
|
|
173656
|
$self->_setpos($newpos); |
|
171
|
77776
|
|
|
|
|
143452
|
1; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
sub exhausted { |
|
174
|
1
|
|
|
1
|
1
|
654
|
my $self = shift; |
|
175
|
1
|
50
|
|
|
|
9
|
$self->error_stream_mode('exhausted') if $self->writing; |
|
176
|
0
|
|
|
|
|
0
|
$self->pos >= $self->len; |
|
177
|
|
|
|
|
|
|
} |
|
178
|
|
|
|
|
|
|
sub erase { |
|
179
|
20047
|
|
|
20047
|
1
|
139273
|
my $self = shift; |
|
180
|
20047
|
|
|
|
|
44441
|
$self->_setlen(0); |
|
181
|
20047
|
|
|
|
|
542352
|
$self->_setpos(0); |
|
182
|
|
|
|
|
|
|
# Writing state is left unchanged |
|
183
|
|
|
|
|
|
|
# You want an after method to handle the data |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
sub read_open { |
|
186
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
187
|
0
|
0
|
|
|
|
0
|
$self->error_stream_mode('read') if $self->mode eq 'wo'; |
|
188
|
0
|
0
|
|
|
|
0
|
$self->write_close if $self->writing; |
|
189
|
0
|
|
|
|
|
0
|
my $file = $self->file; |
|
190
|
0
|
0
|
|
|
|
0
|
if (defined $file) { |
|
191
|
0
|
0
|
|
|
|
0
|
open(my $fp, "<", $file) or die "Cannot open file '$file' for read: $!\n"; |
|
192
|
0
|
|
|
|
|
0
|
my $headerlines = $self->fheaderlines; |
|
193
|
0
|
0
|
|
|
|
0
|
if (defined $headerlines) { |
|
194
|
|
|
|
|
|
|
# Read in their header |
|
195
|
0
|
|
|
|
|
0
|
my $header = ''; |
|
196
|
0
|
|
|
|
|
0
|
while ($headerlines-- > 0) { |
|
197
|
0
|
|
|
|
|
0
|
$header .= <$fp>; |
|
198
|
|
|
|
|
|
|
} |
|
199
|
0
|
|
|
|
|
0
|
$self->_setfheader($header); |
|
200
|
|
|
|
|
|
|
} |
|
201
|
0
|
|
|
|
|
0
|
binmode $fp; |
|
202
|
|
|
|
|
|
|
# Turn off file linking while calling from_raw |
|
203
|
0
|
|
|
|
|
0
|
my $saved_mode = $self->mode; |
|
204
|
0
|
|
|
|
|
0
|
$self->_setfile( undef ); |
|
205
|
0
|
|
|
|
|
0
|
$self->mode( 'rw' ); |
|
206
|
0
|
|
|
|
|
0
|
my $bits = <$fp>; |
|
207
|
|
|
|
|
|
|
{ |
|
208
|
0
|
|
|
|
|
0
|
local $/; |
|
|
0
|
|
|
|
|
0
|
|
|
209
|
0
|
|
|
|
|
0
|
$self->from_raw( <$fp>, $bits ); |
|
210
|
|
|
|
|
|
|
} |
|
211
|
0
|
|
|
|
|
0
|
close $fp; |
|
212
|
|
|
|
|
|
|
# link us back. |
|
213
|
0
|
|
|
|
|
0
|
$self->_setfile( $file ); |
|
214
|
0
|
|
|
|
|
0
|
$self->mode( $saved_mode ); |
|
215
|
|
|
|
|
|
|
} |
|
216
|
0
|
|
|
|
|
0
|
1; |
|
217
|
|
|
|
|
|
|
} |
|
218
|
|
|
|
|
|
|
sub write_open { |
|
219
|
27146
|
|
|
27146
|
1
|
45147
|
my $self = shift; |
|
220
|
27146
|
50
|
|
|
|
86544
|
$self->error_stream_mode('write') if $self->mode eq 'ro'; |
|
221
|
27146
|
100
|
|
|
|
74001
|
if (!$self->writing) { |
|
222
|
25427
|
|
|
|
|
89968
|
$self->_setwrite(1); |
|
223
|
|
|
|
|
|
|
# pos is now ignored |
|
224
|
|
|
|
|
|
|
} |
|
225
|
27146
|
|
|
|
|
2001097
|
1; |
|
226
|
|
|
|
|
|
|
} |
|
227
|
|
|
|
|
|
|
sub write_close { |
|
228
|
27091
|
|
|
27091
|
1
|
37148
|
my $self = shift; |
|
229
|
27091
|
100
|
|
|
|
67645
|
if ($self->writing) { |
|
230
|
27075
|
|
|
|
|
90852
|
$self->_setwrite(0); |
|
231
|
27075
|
|
|
|
|
2099796
|
$self->_setpos($self->len); |
|
232
|
|
|
|
|
|
|
|
|
233
|
27075
|
|
|
|
|
58985
|
my $file = $self->file; |
|
234
|
27075
|
50
|
|
|
|
67980
|
if (defined $file) { |
|
235
|
0
|
0
|
|
|
|
0
|
open(my $fp, ">", $file) or die "Cannot open file $file for write: $!\n"; |
|
236
|
0
|
|
|
|
|
0
|
my $header = $self->fheader; |
|
237
|
0
|
0
|
0
|
|
|
0
|
print $fp $header, "\n" if defined $header && length($header) > 0; |
|
238
|
0
|
|
|
|
|
0
|
binmode $fp; |
|
239
|
0
|
|
|
|
|
0
|
print $fp $self->len, "\n"; |
|
240
|
0
|
|
|
|
|
0
|
print $fp $self->to_raw; |
|
241
|
0
|
|
|
|
|
0
|
close $fp; |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
} |
|
244
|
27091
|
|
|
|
|
48620
|
1; |
|
245
|
|
|
|
|
|
|
} |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
####### Error handling |
|
249
|
|
|
|
|
|
|
# |
|
250
|
|
|
|
|
|
|
# This section has two purposes: |
|
251
|
|
|
|
|
|
|
# 1. enforce a common set of failure messages for all codes. |
|
252
|
|
|
|
|
|
|
# 2. enable the position to be reset to the start of a code on an error. |
|
253
|
|
|
|
|
|
|
# |
|
254
|
|
|
|
|
|
|
# Number 2 is relatively complex since codes can be composed of other codes, |
|
255
|
|
|
|
|
|
|
# and we want to back up to the start of the outermost code. We set up a stack |
|
256
|
|
|
|
|
|
|
# of saved positions which can be used when an error occurs. |
|
257
|
|
|
|
|
|
|
# |
|
258
|
|
|
|
|
|
|
# If your code methods do not either call other codes or make multiple calls to |
|
259
|
|
|
|
|
|
|
# read / skip, then there really is no extra effort. If they do, then it is |
|
260
|
|
|
|
|
|
|
# important to call code_pos_start() before starting, code_pos_set() before |
|
261
|
|
|
|
|
|
|
# each successive value, and code_pos_end() when done. What you get in return |
|
262
|
|
|
|
|
|
|
# is not having to worry about how far you've read -- the position will be |
|
263
|
|
|
|
|
|
|
# restored to the start of the outermost code. |
|
264
|
|
|
|
|
|
|
# |
|
265
|
|
|
|
|
|
|
# From the user's point of view, this means if they try to read a complicated |
|
266
|
|
|
|
|
|
|
# code and it is invalid, the position is left unchanged, instead of some |
|
267
|
|
|
|
|
|
|
# random distance forward in the stream. |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
sub code_pos_start { # Starting a code |
|
270
|
106285
|
|
|
106285
|
1
|
140606
|
my $self = shift; |
|
271
|
106285
|
|
|
|
|
130558
|
my $name = shift; |
|
272
|
106285
|
|
|
|
|
117143
|
push @{$self->_code_pos_array}, $self->pos; |
|
|
106285
|
|
|
|
|
368221
|
|
|
273
|
106285
|
|
|
|
|
3438846
|
push @{$self->_code_str_array}, $name; |
|
|
106285
|
|
|
|
|
315865
|
|
|
274
|
|
|
|
|
|
|
#print STDERR "error stack is ", join(",", @{$self->_code_str_array}), "\n"; |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
sub code_pos_set { # Replace position |
|
277
|
183272
|
|
|
183272
|
1
|
266145
|
my $self = shift; |
|
278
|
183272
|
|
|
|
|
633020
|
$self->_code_pos_array->[-1] = $self->pos; |
|
279
|
|
|
|
|
|
|
} |
|
280
|
|
|
|
|
|
|
sub code_pos_end { # Remove position -- we're not in this code any more |
|
281
|
106164
|
|
|
106164
|
1
|
139046
|
my $self = shift; |
|
282
|
106164
|
|
|
|
|
112677
|
pop @{$self->_code_pos_array}; |
|
|
106164
|
|
|
|
|
319243
|
|
|
283
|
106164
|
|
|
|
|
14213778
|
pop @{$self->_code_str_array}; |
|
|
106164
|
|
|
|
|
331417
|
|
|
284
|
|
|
|
|
|
|
} |
|
285
|
|
|
|
|
|
|
sub _code_restore_pos { # Returns string of code name |
|
286
|
182
|
|
|
182
|
|
332
|
my $self = shift; |
|
287
|
|
|
|
|
|
|
# Check that we aren't trying to restore a position while writing |
|
288
|
182
|
50
|
66
|
|
|
993
|
if ($self->writing and @{$self->_code_pos_array}) { |
|
|
64
|
|
|
|
|
220
|
|
|
289
|
0
|
|
|
|
|
0
|
confess "Found code position while error in writing: " . $self->_code_str_array->[0]; |
|
290
|
|
|
|
|
|
|
} |
|
291
|
|
|
|
|
|
|
# Put position back to start of topmost code |
|
292
|
182
|
100
|
|
|
|
4365
|
if (@{$self->_code_pos_array}) { |
|
|
182
|
|
|
|
|
597
|
|
|
293
|
95
|
|
|
|
|
5069
|
$self->_setpos($self->_code_pos_array->[0]); |
|
294
|
95
|
|
|
|
|
3177
|
@{$self->_code_pos_array} = (); |
|
|
95
|
|
|
|
|
304
|
|
|
295
|
|
|
|
|
|
|
} |
|
296
|
182
|
|
|
|
|
7761
|
my $codename = ''; |
|
297
|
182
|
100
|
|
|
|
239
|
if (@{$self->_code_str_array}) { |
|
|
182
|
|
|
|
|
1860
|
|
|
298
|
95
|
50
|
|
|
|
3874
|
$codename = $self->_code_str_array->[0] if defined $self->_code_str_array->[0]; |
|
299
|
95
|
|
|
|
|
8302
|
@{$self->_code_str_array} = (); |
|
|
95
|
|
|
|
|
314
|
|
|
300
|
|
|
|
|
|
|
} |
|
301
|
182
|
|
|
|
|
6960
|
$codename; |
|
302
|
|
|
|
|
|
|
} |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# This can be called after any code routines have been used, to verify they |
|
305
|
|
|
|
|
|
|
# cleaned up after themselves. Failing this usually means someone died inside |
|
306
|
|
|
|
|
|
|
# an eval, while being called by a code routine. It's also possible a broken |
|
307
|
|
|
|
|
|
|
# code routine did a code_pos_start then returned without a matching end. |
|
308
|
|
|
|
|
|
|
sub code_pos_is_set { |
|
309
|
119
|
|
|
119
|
1
|
215643
|
my $self = shift; |
|
310
|
119
|
50
|
|
|
|
562
|
return unless @{$self->_code_pos_array}; # return undef if nothing. |
|
|
119
|
|
|
|
|
762
|
|
|
311
|
|
|
|
|
|
|
|
|
312
|
0
|
|
|
|
|
0
|
my $text = join(",", @{$self->_code_str_array}); |
|
|
0
|
|
|
|
|
0
|
|
|
313
|
0
|
|
|
|
|
0
|
$text; |
|
314
|
|
|
|
|
|
|
} |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
sub error_off_stream { |
|
317
|
57
|
|
|
57
|
1
|
87
|
my $self = shift; |
|
318
|
57
|
|
|
|
|
81
|
my $skipping = shift; |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# Give the skip error only if we were not reading a code. |
|
321
|
57
|
100
|
100
|
|
|
165
|
if ( (defined $skipping) && (@{$self->_code_pos_array} == 0) ) { |
|
|
10
|
|
|
|
|
45
|
|
|
322
|
1
|
|
|
|
|
181
|
croak "skip off end of stream"; |
|
323
|
|
|
|
|
|
|
} |
|
324
|
|
|
|
|
|
|
|
|
325
|
56
|
|
|
|
|
601
|
my $codename = $self->_code_restore_pos(); |
|
326
|
56
|
100
|
|
|
|
261
|
$codename = " ($codename)" if $codename ne ''; |
|
327
|
56
|
|
|
|
|
18211
|
croak "read off end of stream$codename"; |
|
328
|
|
|
|
|
|
|
} |
|
329
|
|
|
|
|
|
|
sub error_stream_mode { |
|
330
|
10
|
|
|
10
|
1
|
16
|
my $self = shift; |
|
331
|
10
|
|
|
|
|
17
|
my $type = shift; |
|
332
|
10
|
|
|
|
|
21
|
my $codename = $self->_code_restore_pos(); |
|
333
|
10
|
50
|
|
|
|
26
|
$codename = " ($codename)" if $codename ne ''; |
|
334
|
|
|
|
|
|
|
|
|
335
|
10
|
50
|
66
|
|
|
44
|
croak "write while stream opened readonly" |
|
336
|
|
|
|
|
|
|
if ($type eq 'write') && ($self->mode eq 'ro'); |
|
337
|
10
|
50
|
66
|
|
|
41
|
croak "read while stream opened writeonly" |
|
338
|
|
|
|
|
|
|
if ($type eq 'read') && ($self->mode eq 'wo'); |
|
339
|
|
|
|
|
|
|
|
|
340
|
10
|
100
|
|
|
|
37
|
if ($self->writing) { |
|
341
|
7
|
100
|
|
|
|
28
|
if ($type eq 'rewind') { croak "rewind while writing$codename"; } |
|
|
1
|
100
|
|
|
|
110
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
342
|
4
|
|
|
|
|
424
|
elsif ($type eq 'read' ) { croak "read while writing$codename"; } |
|
343
|
1
|
|
|
|
|
94
|
elsif ($type eq 'skip' ) { croak "skip while writing$codename"; } |
|
344
|
1
|
|
|
|
|
114
|
elsif ($type eq 'exhausted') { croak "exhausted while writing$codename"; } |
|
345
|
|
|
|
|
|
|
} else { |
|
346
|
3
|
50
|
|
|
|
8
|
if ($type eq 'write' ) { croak "write while reading$codename"; } |
|
|
3
|
|
|
|
|
475
|
|
|
347
|
|
|
|
|
|
|
} |
|
348
|
0
|
|
|
|
|
0
|
croak "Mode error$codename: $type"; |
|
349
|
|
|
|
|
|
|
} |
|
350
|
|
|
|
|
|
|
sub error_code { |
|
351
|
116
|
|
|
116
|
1
|
192
|
my $self = shift; |
|
352
|
116
|
|
|
|
|
178
|
my $type = shift; |
|
353
|
116
|
|
|
|
|
146
|
my $text = shift; |
|
354
|
116
|
100
|
|
|
|
1839
|
if ($type eq 'zeroval') { # Implied text |
|
355
|
54
|
|
|
|
|
76
|
$type = 'value'; |
|
356
|
54
|
|
|
|
|
74
|
$text = 'value must be >= 0'; |
|
357
|
|
|
|
|
|
|
} |
|
358
|
116
|
50
|
|
|
|
274
|
if ($type eq 'range') { # Range is given the value, the min, and the max |
|
359
|
0
|
|
|
|
|
0
|
$type = 'value'; |
|
360
|
0
|
0
|
|
|
|
0
|
if (!defined $text) { |
|
361
|
0
|
|
|
|
|
0
|
$text = 'value out of range'; |
|
362
|
|
|
|
|
|
|
} else { |
|
363
|
0
|
|
|
|
|
0
|
my $min = shift; |
|
364
|
0
|
|
|
|
|
0
|
my $max = shift; |
|
365
|
0
|
|
|
|
|
0
|
$text = "value $text out of range"; |
|
366
|
0
|
0
|
0
|
|
|
0
|
$text .= " $min - $max" if defined $min && defined $max; |
|
367
|
|
|
|
|
|
|
} |
|
368
|
|
|
|
|
|
|
} |
|
369
|
116
|
|
|
|
|
517
|
my $codename = $self->_code_restore_pos(); |
|
370
|
116
|
|
|
|
|
211
|
my $trailer = ''; |
|
371
|
116
|
100
|
|
|
|
390
|
$trailer .= " ($codename)" if $codename ne ''; |
|
372
|
116
|
100
|
|
|
|
1792
|
$trailer .= ": $text" if defined $text; |
|
373
|
116
|
100
|
|
|
|
740
|
if ($type eq 'param') { croak "invalid parameters$trailer"; } |
|
|
17
|
100
|
|
|
|
1958
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
374
|
54
|
|
|
|
|
10352
|
elsif ($type eq 'value') { croak "invalid value$trailer"; } |
|
375
|
0
|
|
|
|
|
0
|
elsif ($type eq 'string') { croak "invalid string$trailer"; } |
|
376
|
6
|
|
|
|
|
1093
|
elsif ($type eq 'base') { croak "code error: invalid base$trailer";} |
|
|
38
|
|
|
|
|
9381
|
|
|
377
|
|
|
|
|
|
|
elsif ($type eq 'overflow'){croak "code error: overflow$trailer";} |
|
378
|
1
|
|
|
|
|
157
|
elsif ($type eq 'short') { croak "short read$trailer"; } |
|
379
|
0
|
|
|
|
|
0
|
elsif ($type eq 'assert') { confess "internal assert$trailer"; } |
|
380
|
0
|
|
|
|
|
0
|
else { confess "Unknown error$trailer"; } |
|
381
|
|
|
|
|
|
|
} |
|
382
|
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
####### Combination functions |
|
385
|
|
|
|
|
|
|
sub erase_for_write { |
|
386
|
20044
|
|
|
20044
|
1
|
209266
|
my $self = shift; |
|
387
|
20044
|
|
|
|
|
611762
|
$self->erase; |
|
388
|
20044
|
100
|
|
|
|
180430
|
$self->write_open if !$self->writing; |
|
389
|
|
|
|
|
|
|
} |
|
390
|
|
|
|
|
|
|
sub rewind_for_read { |
|
391
|
29547
|
|
|
29547
|
1
|
143606
|
my $self = shift; |
|
392
|
29547
|
100
|
|
|
|
101054
|
$self->write_close if $self->writing; |
|
393
|
29547
|
|
|
|
|
71081
|
$self->rewind; |
|
394
|
|
|
|
|
|
|
} |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
sub readahead { |
|
398
|
6
|
|
|
6
|
1
|
3097
|
my $self = shift; |
|
399
|
6
|
|
|
|
|
14
|
my $bits = shift; |
|
400
|
6
|
|
|
|
|
24
|
$self->read($bits, 'readahead'); |
|
401
|
|
|
|
|
|
|
} |
|
402
|
|
|
|
|
|
|
sub read { # You need to implement this. |
|
403
|
0
|
|
|
0
|
1
|
0
|
confess "The read method has not been implemented!"; |
|
404
|
|
|
|
|
|
|
} |
|
405
|
|
|
|
|
|
|
sub write { # You need to implement this. |
|
406
|
0
|
|
|
0
|
1
|
0
|
confess "The write method has not been implemented!"; |
|
407
|
|
|
|
|
|
|
} |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
sub put_unary { |
|
411
|
5916
|
|
|
5916
|
1
|
11683
|
my $self = shift; |
|
412
|
|
|
|
|
|
|
|
|
413
|
5916
|
|
|
|
|
10022
|
foreach my $val (@_) { |
|
414
|
6290
|
50
|
33
|
|
|
26394
|
$self->error_code('zeroval') unless defined $val and $val >= 0; |
|
415
|
6290
|
50
|
|
|
|
13333
|
warn "Trying to write large unary value ($val)" if $val > 10_000_000; |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
# Since the write routine is allowed to take any number of bits when |
|
418
|
|
|
|
|
|
|
# writing 0 and 1, this works, and is very fast. |
|
419
|
6290
|
|
|
|
|
20700
|
$self->write($val+1, 1); |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
# Alternate implementation, much slower for large values: |
|
422
|
|
|
|
|
|
|
# |
|
423
|
|
|
|
|
|
|
# if ($val < maxbits) { |
|
424
|
|
|
|
|
|
|
# $self->write($val+1, 1); |
|
425
|
|
|
|
|
|
|
# } else { |
|
426
|
|
|
|
|
|
|
# my $nbits = $val % maxbits; |
|
427
|
|
|
|
|
|
|
# my $nwords = ($val-$nbits) / maxbits; |
|
428
|
|
|
|
|
|
|
# $self->write(maxbits, 0) for (1 .. $nwords); |
|
429
|
|
|
|
|
|
|
# $self->write($nbits+1, 1); |
|
430
|
|
|
|
|
|
|
# } |
|
431
|
|
|
|
|
|
|
} |
|
432
|
5916
|
|
|
|
|
14754
|
1; |
|
433
|
|
|
|
|
|
|
} |
|
434
|
|
|
|
|
|
|
sub get_unary { # You ought to override this. |
|
435
|
33456
|
|
|
33456
|
1
|
79749
|
my $self = shift; |
|
436
|
33456
|
50
|
|
|
|
93524
|
$self->error_stream_mode('read') if $self->writing; |
|
437
|
33456
|
|
|
|
|
41674
|
my $count = shift; |
|
438
|
33456
|
100
|
|
|
|
64508
|
if (!defined $count) { $count = 1; } |
|
|
33443
|
100
|
|
|
|
49646
|
|
|
|
|
100
|
|
|
|
|
|
|
439
|
9
|
|
|
|
|
34
|
elsif ($count < 0) { $count = ~0; } # Get everything |
|
440
|
2
|
|
|
|
|
7
|
elsif ($count == 0) { return; } |
|
441
|
|
|
|
|
|
|
|
|
442
|
33454
|
|
|
|
|
36311
|
my @vals; |
|
443
|
33454
|
|
|
|
|
71650
|
$self->code_pos_start('Unary'); |
|
444
|
33454
|
|
|
|
|
1147454
|
while ($count-- > 0) { |
|
445
|
33854
|
|
|
|
|
73233
|
$self->code_pos_set; |
|
446
|
33854
|
|
|
|
|
994993
|
my $val = 0; |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
# Simple code: |
|
449
|
|
|
|
|
|
|
# |
|
450
|
|
|
|
|
|
|
# my $maxval = $len - $pos - 1; # Maximum unary value in remaining space |
|
451
|
|
|
|
|
|
|
# $val++ while ( ($val <= $maxval) && ($self->read(1) == 0) ); |
|
452
|
|
|
|
|
|
|
# die "read off end of stream" if $pos >= $len; |
|
453
|
|
|
|
|
|
|
# |
|
454
|
|
|
|
|
|
|
# Faster code, looks at 32 bits at a time. Still comparatively slow. |
|
455
|
|
|
|
|
|
|
|
|
456
|
33854
|
|
|
|
|
65009
|
my $word = $self->read(maxbits, 'readahead'); |
|
457
|
33854
|
100
|
|
|
|
72848
|
last unless defined $word; |
|
458
|
33690
|
|
|
|
|
84187
|
while ($word == 0) { |
|
459
|
8265
|
|
|
|
|
13386
|
$val += maxbits; |
|
460
|
8265
|
|
|
|
|
11878
|
$self->skip(maxbits); |
|
461
|
8265
|
|
|
|
|
13216
|
$word = $self->read(maxbits, 'readahead'); |
|
462
|
|
|
|
|
|
|
} |
|
463
|
33690
|
|
|
|
|
58998
|
while (($word >> (maxbits-1) & 1) == 0) { |
|
464
|
207425
|
|
|
|
|
223706
|
$val++; |
|
465
|
207425
|
|
|
|
|
316588
|
$word <<= 1; |
|
466
|
|
|
|
|
|
|
} |
|
467
|
33690
|
|
|
|
|
56635
|
my $nbits = $val % maxbits; |
|
468
|
33690
|
|
|
|
|
88014
|
$self->skip($nbits + 1); |
|
469
|
|
|
|
|
|
|
|
|
470
|
33690
|
|
|
|
|
102702
|
push @vals, $val; |
|
471
|
|
|
|
|
|
|
} |
|
472
|
33454
|
|
|
|
|
71681
|
$self->code_pos_end; |
|
473
|
33454
|
100
|
|
|
|
1127446
|
wantarray ? @vals : $vals[-1]; |
|
474
|
|
|
|
|
|
|
} |
|
475
|
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
# Write unary as 1111.....0 instead of 0000.....1 |
|
477
|
|
|
|
|
|
|
sub put_unary1 { |
|
478
|
8744
|
|
|
8744
|
1
|
19569
|
my $self = shift; |
|
479
|
|
|
|
|
|
|
|
|
480
|
8744
|
|
|
|
|
15514
|
foreach my $val (@_) { |
|
481
|
9686
|
100
|
100
|
|
|
43040
|
$self->error_code('zeroval') unless defined $val and $val >= 0; |
|
482
|
9684
|
50
|
|
|
|
20591
|
warn "Trying to write large unary value ($val)" if $val > 10_000_000; |
|
483
|
9684
|
100
|
|
|
|
17549
|
if ($val < maxbits) { |
|
484
|
8887
|
|
|
|
|
32870
|
$self->write($val+1, maxval() << 1); |
|
485
|
|
|
|
|
|
|
} else { |
|
486
|
797
|
|
|
|
|
1465
|
my $nbits = $val % maxbits; |
|
487
|
797
|
|
|
|
|
1734
|
my $nwords = ($val-$nbits) / maxbits(); |
|
488
|
797
|
|
|
|
|
2316
|
$self->write(maxbits, maxval) for (1 .. $nwords); |
|
489
|
797
|
|
|
|
|
2119
|
$self->write($nbits+1, maxval() << 1); |
|
490
|
|
|
|
|
|
|
} |
|
491
|
|
|
|
|
|
|
} |
|
492
|
8742
|
|
|
|
|
25111
|
1; |
|
493
|
|
|
|
|
|
|
} |
|
494
|
|
|
|
|
|
|
sub get_unary1 { # You ought to override this. |
|
495
|
8968
|
|
|
8968
|
1
|
19907
|
my $self = shift; |
|
496
|
8968
|
50
|
|
|
|
23864
|
$self->error_stream_mode('read') if $self->writing; |
|
497
|
8968
|
|
|
|
|
11898
|
my $count = shift; |
|
498
|
8968
|
100
|
|
|
|
17983
|
if (!defined $count) { $count = 1; } |
|
|
8953
|
50
|
|
|
|
13142
|
|
|
|
|
0
|
|
|
|
|
|
|
499
|
15
|
|
|
|
|
37
|
elsif ($count < 0) { $count = ~0; } # Get everything |
|
500
|
0
|
|
|
|
|
0
|
elsif ($count == 0) { return; } |
|
501
|
|
|
|
|
|
|
|
|
502
|
8968
|
|
|
|
|
10525
|
my @vals; |
|
503
|
8968
|
|
|
|
|
33111
|
$self->code_pos_start('Unary1'); |
|
504
|
8968
|
|
|
|
|
272467
|
while ($count-- > 0) { |
|
505
|
9925
|
|
|
|
|
22361
|
$self->code_pos_set; |
|
506
|
9925
|
|
|
|
|
325994
|
my $val = 0; |
|
507
|
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
# Simple code: |
|
509
|
|
|
|
|
|
|
# |
|
510
|
|
|
|
|
|
|
# my $maxval = $len - $pos - 1; # Maximum unary value in remaining space |
|
511
|
|
|
|
|
|
|
# $val++ while ( ($val <= $maxval) && ($self->read(1) == 0) ); |
|
512
|
|
|
|
|
|
|
# die "read off end of stream" if $pos >= $len; |
|
513
|
|
|
|
|
|
|
# |
|
514
|
|
|
|
|
|
|
# Faster code, looks at 32 bits at a time. Still comparatively slow. |
|
515
|
|
|
|
|
|
|
|
|
516
|
9925
|
|
|
|
|
37738
|
my $word = $self->read(maxbits, 'readahead'); |
|
517
|
9925
|
100
|
|
|
|
27362
|
last unless defined $word; |
|
518
|
9843
|
|
|
|
|
33705
|
while ($word == maxval) { |
|
519
|
13011
|
|
|
|
|
23305
|
$val += maxbits; |
|
520
|
13011
|
|
|
|
|
22836
|
$self->skip(maxbits); |
|
521
|
13011
|
|
|
|
|
24233
|
$word = $self->read(maxbits, 'readahead'); |
|
522
|
|
|
|
|
|
|
} |
|
523
|
9843
|
|
|
|
|
31575
|
while (($word >> (maxbits-1) & 1) != 0) { |
|
524
|
140818
|
|
|
|
|
163790
|
$val++; |
|
525
|
140818
|
|
|
|
|
246875
|
$word <<= 1; |
|
526
|
|
|
|
|
|
|
} |
|
527
|
9843
|
|
|
|
|
17234
|
my $nbits = $val % maxbits; |
|
528
|
9843
|
|
|
|
|
25053
|
$self->skip($nbits + 1); |
|
529
|
|
|
|
|
|
|
|
|
530
|
9834
|
|
|
|
|
33009
|
push @vals, $val; |
|
531
|
|
|
|
|
|
|
} |
|
532
|
8959
|
|
|
|
|
19960
|
$self->code_pos_end; |
|
533
|
8959
|
100
|
|
|
|
306343
|
wantarray ? @vals : $vals[-1]; |
|
534
|
|
|
|
|
|
|
} |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
# binary values of given length |
|
537
|
|
|
|
|
|
|
sub put_binword { |
|
538
|
817
|
|
|
817
|
1
|
13748
|
my $self = shift; |
|
539
|
817
|
|
|
|
|
1221
|
my $bits = shift; |
|
540
|
817
|
50
|
33
|
|
|
3658
|
$self->error_code('param', "bits must be in range 0-" . maxbits) |
|
541
|
|
|
|
|
|
|
if ($bits <= 0) || ($bits > maxbits); |
|
542
|
|
|
|
|
|
|
|
|
543
|
817
|
|
|
|
|
1562
|
foreach my $val (@_) { |
|
544
|
3493
|
50
|
33
|
|
|
15146
|
$self->error_code('zeroval') unless defined $val and $val >= 0; |
|
545
|
3493
|
|
|
|
|
9850
|
$self->write($bits, $val); |
|
546
|
|
|
|
|
|
|
} |
|
547
|
817
|
|
|
|
|
2435
|
1; |
|
548
|
|
|
|
|
|
|
} |
|
549
|
|
|
|
|
|
|
sub get_binword { |
|
550
|
842
|
|
|
842
|
1
|
13428
|
my $self = shift; |
|
551
|
842
|
50
|
|
|
|
2424
|
$self->error_stream_mode('read') if $self->writing; |
|
552
|
842
|
|
|
|
|
1390
|
my $bits = shift; |
|
553
|
842
|
100
|
100
|
|
|
3759
|
$self->error_code('param', "bits must be in range 0-" . maxbits) |
|
554
|
|
|
|
|
|
|
if ($bits <= 0) || ($bits > maxbits); |
|
555
|
839
|
|
|
|
|
1312
|
my $count = shift; |
|
556
|
839
|
100
|
|
|
|
2200
|
if (!defined $count) { $count = 1; } |
|
|
815
|
50
|
|
|
|
1190
|
|
|
|
|
0
|
|
|
|
|
|
|
557
|
24
|
|
|
|
|
91
|
elsif ($count < 0) { $count = ~0; } # Get everything |
|
558
|
0
|
|
|
|
|
0
|
elsif ($count == 0) { return; } |
|
559
|
|
|
|
|
|
|
|
|
560
|
839
|
|
|
|
|
1221
|
my @vals; |
|
561
|
839
|
|
|
|
|
2217
|
while ($count-- > 0) { |
|
562
|
3539
|
|
|
|
|
9681
|
my $val = $self->read($bits); |
|
563
|
3537
|
100
|
|
|
|
8121
|
last unless defined $val; |
|
564
|
3513
|
|
|
|
|
12133
|
push @vals, $val; |
|
565
|
|
|
|
|
|
|
} |
|
566
|
837
|
100
|
|
|
|
4112
|
wantarray ? @vals : $vals[-1]; |
|
567
|
|
|
|
|
|
|
} |
|
568
|
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
# Write one or more text binary strings (e.g. '10010') |
|
571
|
|
|
|
|
|
|
sub put_string { |
|
572
|
5064
|
|
|
5064
|
1
|
8377
|
my $self = shift; |
|
573
|
5064
|
50
|
|
|
|
13610
|
$self->error_stream_mode('write') unless $self->writing; |
|
574
|
|
|
|
|
|
|
|
|
575
|
5064
|
|
|
|
|
8540
|
foreach my $str (@_) { |
|
576
|
5064
|
50
|
|
|
|
11170
|
next unless defined $str; |
|
577
|
5064
|
50
|
|
|
|
12021
|
$self->error_code('string') if $str =~ tr/01//c; |
|
578
|
5064
|
|
|
|
|
7562
|
my $bits = length($str); |
|
579
|
5064
|
50
|
|
|
|
12043
|
next unless $bits > 0; |
|
580
|
|
|
|
|
|
|
|
|
581
|
5064
|
|
|
|
|
5495
|
my $spos = 0; |
|
582
|
5064
|
|
|
|
|
11223
|
while ($bits >= 32) { |
|
583
|
3051
|
|
|
|
|
20126
|
$self->write(32, oct('0b' . substr($str, $spos, 32))); |
|
584
|
3051
|
|
|
|
|
3749
|
$spos += 32; |
|
585
|
3051
|
|
|
|
|
6704
|
$bits -= 32; |
|
586
|
|
|
|
|
|
|
} |
|
587
|
5064
|
100
|
|
|
|
12225
|
if ($bits > 0) { |
|
588
|
4927
|
|
|
|
|
23845
|
$self->write($bits, oct('0b' . substr($str, $spos, $bits))); |
|
589
|
|
|
|
|
|
|
} |
|
590
|
|
|
|
|
|
|
} |
|
591
|
5064
|
|
|
|
|
12408
|
1; |
|
592
|
|
|
|
|
|
|
} |
|
593
|
|
|
|
|
|
|
# Get a text binary string. Similar to read, but bits can be 0 - len. |
|
594
|
|
|
|
|
|
|
sub read_string { |
|
595
|
2880
|
|
|
2880
|
1
|
5145
|
my $self = shift; |
|
596
|
2880
|
100
|
|
|
|
6954
|
$self->error_stream_mode('read') if $self->writing; |
|
597
|
2879
|
|
|
|
|
3494
|
my $bits = shift; |
|
598
|
2879
|
100
|
66
|
|
|
11615
|
$self->error_code('param', "bits must be >= 0") unless defined $bits && $bits >= 0; |
|
599
|
2878
|
100
|
|
|
|
8732
|
$self->error_code('short') unless $bits <= ($self->len - $self->pos); |
|
600
|
2877
|
|
|
|
|
3879
|
my $str = ''; |
|
601
|
2877
|
|
|
|
|
6451
|
while ($bits >= 32) { |
|
602
|
1542
|
|
|
|
|
4697
|
$str .= unpack("B32", pack("N", $self->read(32))); |
|
603
|
1542
|
|
|
|
|
3890
|
$bits -= 32; |
|
604
|
|
|
|
|
|
|
} |
|
605
|
2877
|
100
|
|
|
|
6257
|
if ($bits > 0) { |
|
606
|
2782
|
|
|
|
|
11107
|
$str .= substr(unpack("B32", pack("N", $self->read($bits))), -$bits); |
|
607
|
|
|
|
|
|
|
} |
|
608
|
2877
|
|
|
|
|
9975
|
$str; |
|
609
|
|
|
|
|
|
|
} |
|
610
|
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
# Conversion to and from strings of 0's and 1's. Note that the order is |
|
612
|
|
|
|
|
|
|
# completely left to right based on what was written. |
|
613
|
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
sub to_string { # You should override this. |
|
615
|
2873
|
|
|
2873
|
1
|
25400
|
my $self = shift; |
|
616
|
2873
|
|
|
|
|
6799
|
$self->rewind_for_read; |
|
617
|
2873
|
|
|
|
|
7295
|
$self->read_string($self->len); |
|
618
|
|
|
|
|
|
|
} |
|
619
|
|
|
|
|
|
|
sub from_string { # You should override this. |
|
620
|
2866
|
|
|
2866
|
1
|
31919
|
my $self = shift; |
|
621
|
|
|
|
|
|
|
#my $str = shift; |
|
622
|
|
|
|
|
|
|
#my $bits = shift || length($str); |
|
623
|
2866
|
|
|
|
|
14010
|
$self->erase_for_write; |
|
624
|
2866
|
|
|
|
|
8068
|
$self->put_string($_[0]); |
|
625
|
2866
|
|
|
|
|
6090
|
$self->rewind_for_read; |
|
626
|
|
|
|
|
|
|
} |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
# Conversion to and from binary. Note that the order is completely left to |
|
629
|
|
|
|
|
|
|
# right based on what was written. This means it is an array of big-endian |
|
630
|
|
|
|
|
|
|
# units. This implementation uses 32-bit words as the units. |
|
631
|
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
sub to_raw { # You ought to override this. |
|
633
|
3
|
|
|
3
|
1
|
234
|
my $self = shift; |
|
634
|
3
|
|
|
|
|
33
|
$self->rewind_for_read; |
|
635
|
3
|
|
|
|
|
11
|
my $len = $self->len; |
|
636
|
3
|
|
|
|
|
20
|
my $pos = $self->pos; |
|
637
|
3
|
|
|
|
|
8
|
my $vec = ''; |
|
638
|
3
|
|
|
|
|
13
|
while ( ($pos+31) < $len ) { |
|
639
|
1296
|
|
|
|
|
4703
|
$vec .= pack("N", $self->read(32)); |
|
640
|
1296
|
|
|
|
|
2963
|
$pos += 32; |
|
641
|
|
|
|
|
|
|
} |
|
642
|
3
|
50
|
|
|
|
19
|
if ($pos < $len) { |
|
643
|
3
|
|
|
|
|
28
|
$vec .= pack("N", $self->read($len-$pos) << 32-($len-$pos)); |
|
644
|
|
|
|
|
|
|
} |
|
645
|
3
|
|
|
|
|
28
|
$vec; |
|
646
|
|
|
|
|
|
|
} |
|
647
|
|
|
|
|
|
|
sub put_raw { # You ought to override this. |
|
648
|
2
|
|
|
2
|
1
|
5
|
my $self = shift; |
|
649
|
2
|
50
|
|
|
|
9
|
$self->error_stream_mode('write') unless $self->writing; |
|
650
|
|
|
|
|
|
|
|
|
651
|
2
|
|
|
|
|
6
|
my $vec = shift; |
|
652
|
2
|
|
33
|
|
|
6
|
my $bits = shift || int((length($vec)+7)/8); |
|
653
|
|
|
|
|
|
|
|
|
654
|
2
|
|
|
|
|
4
|
my $vpos = 0; |
|
655
|
2
|
|
|
|
|
8
|
while ($bits >= 32) { |
|
656
|
1062
|
|
|
|
|
3318
|
$self->write(32, unpack("N", substr($vec, $vpos, 4))); |
|
657
|
1062
|
|
|
|
|
1336
|
$vpos += 4; |
|
658
|
1062
|
|
|
|
|
1994
|
$bits -= 32; |
|
659
|
|
|
|
|
|
|
} |
|
660
|
2
|
50
|
|
|
|
11
|
if ($bits > 0) { |
|
661
|
2
|
|
|
|
|
10
|
my $nbytes = int(($bits+7)/8); # this many bytes left |
|
662
|
2
|
|
|
|
|
5
|
my $pvec = substr($vec, $vpos, $nbytes); # extract the bytes |
|
663
|
2
|
|
|
|
|
6
|
vec($pvec,33,1) = 0; # zero fill the 32-bit word |
|
664
|
2
|
|
|
|
|
5
|
my $word = unpack("N", $pvec); # unpack the filled word |
|
665
|
2
|
|
|
|
|
9
|
$word >>= (32-$bits); # shift data to lower bits |
|
666
|
2
|
|
|
|
|
8
|
$self->write($bits, $word); # write data to stream |
|
667
|
|
|
|
|
|
|
} |
|
668
|
2
|
|
|
|
|
7
|
1; |
|
669
|
|
|
|
|
|
|
} |
|
670
|
|
|
|
|
|
|
sub from_raw { |
|
671
|
5
|
|
|
5
|
1
|
17734
|
my $self = shift; |
|
672
|
5
|
|
|
|
|
15
|
my $vec = shift; |
|
673
|
5
|
|
33
|
|
|
30
|
my $bits = shift || int((length($vec)+7)/8); |
|
674
|
5
|
|
|
|
|
23
|
$self->erase_for_write; |
|
675
|
5
|
|
|
|
|
29
|
$self->put_raw($vec, $bits); |
|
676
|
5
|
|
|
|
|
22
|
$self->rewind_for_read; |
|
677
|
|
|
|
|
|
|
} |
|
678
|
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
# Conversion to and from your internal data. This can be in any form desired. |
|
680
|
|
|
|
|
|
|
# This could be a little-endian array, or a byte stream, or a string, etc. |
|
681
|
|
|
|
|
|
|
# The main point is that we can get a single chunk that can be saved off, and |
|
682
|
|
|
|
|
|
|
# later can restore the stream. This should be efficient. |
|
683
|
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
sub to_store { # You ought to implement this. |
|
685
|
3
|
|
|
3
|
1
|
19
|
my $self = shift; |
|
686
|
3
|
|
|
|
|
16
|
$self->to_raw(@_); |
|
687
|
|
|
|
|
|
|
} |
|
688
|
|
|
|
|
|
|
sub from_store { # You ought to implement this. |
|
689
|
3
|
|
|
3
|
1
|
26999
|
my $self = shift; |
|
690
|
3
|
|
|
|
|
23
|
$self->from_raw(@_); |
|
691
|
|
|
|
|
|
|
} |
|
692
|
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
# Takes a stream and inserts its contents into the current stream. |
|
694
|
|
|
|
|
|
|
# Non-destructive to both streams. |
|
695
|
|
|
|
|
|
|
sub put_stream { |
|
696
|
6
|
|
|
6
|
1
|
28
|
my $self = shift; |
|
697
|
6
|
|
|
|
|
10
|
my $source = shift; |
|
698
|
6
|
50
|
33
|
|
|
59
|
return 0 unless defined $source && $source->can('to_string'); |
|
699
|
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
# In an implementation, you could check if ref $source eq __PACKAGE__ |
|
701
|
|
|
|
|
|
|
# and do something special. BLVec / XS does this. |
|
702
|
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
# This is reasonably fast for most implementations. |
|
704
|
6
|
|
|
|
|
19
|
$self->put_string($source->to_string); |
|
705
|
|
|
|
|
|
|
# In theory this could be faster. Since all the implementations have custom |
|
706
|
|
|
|
|
|
|
# string code, and none have custom raw code, it's currently slower. |
|
707
|
|
|
|
|
|
|
# $self->put_raw($source->to_raw, $source->len); |
|
708
|
6
|
|
|
|
|
17
|
1; |
|
709
|
|
|
|
|
|
|
} |
|
710
|
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
# Helper class methods for other functions |
|
714
|
|
|
|
|
|
|
sub _floorlog2 { |
|
715
|
0
|
|
|
0
|
|
|
my $d = shift; |
|
716
|
0
|
|
|
|
|
|
my $base = 0; |
|
717
|
0
|
|
|
|
|
|
$base++ while ($d >>= 1); |
|
718
|
0
|
|
|
|
|
|
$base; |
|
719
|
|
|
|
|
|
|
} |
|
720
|
|
|
|
|
|
|
sub _ceillog2 { |
|
721
|
0
|
|
|
0
|
|
|
my $d = shift; |
|
722
|
0
|
|
|
|
|
|
$d--; |
|
723
|
0
|
|
|
|
|
|
my $base = 1; |
|
724
|
0
|
|
|
|
|
|
$base++ while ($d >>= 1); |
|
725
|
0
|
|
|
|
|
|
$base; |
|
726
|
|
|
|
|
|
|
} |
|
727
|
|
|
|
|
|
|
sub _bin_to_dec { |
|
728
|
28
|
|
|
28
|
|
531
|
no warnings 'portable'; |
|
|
28
|
|
|
|
|
68
|
|
|
|
28
|
|
|
|
|
5573
|
|
|
729
|
0
|
|
|
0
|
|
|
oct '0b' . substr($_[1], 0, $_[0]); |
|
730
|
|
|
|
|
|
|
} |
|
731
|
|
|
|
|
|
|
sub _dec_to_bin { |
|
732
|
|
|
|
|
|
|
# The following is typically fastest with 5.9.2 and later: |
|
733
|
|
|
|
|
|
|
# |
|
734
|
|
|
|
|
|
|
# scalar reverse unpack("b$bits",($bits>32) ? pack("Q>",$v) : pack("V",$v)); |
|
735
|
|
|
|
|
|
|
# |
|
736
|
|
|
|
|
|
|
# With 5.9.2 and later on a 64-bit machine, this will work quickly: |
|
737
|
|
|
|
|
|
|
# |
|
738
|
|
|
|
|
|
|
# substr(unpack("B64", pack("Q>", $v)), -$bits); |
|
739
|
|
|
|
|
|
|
# |
|
740
|
|
|
|
|
|
|
# This is the best compromise that works with 5.8.x, BE/LE, and 32-bit: |
|
741
|
0
|
|
|
0
|
|
|
my $bits = shift; |
|
742
|
0
|
|
|
|
|
|
my $v = shift; |
|
743
|
0
|
0
|
|
|
|
|
if ($bits > 32) { |
|
744
|
|
|
|
|
|
|
# return substr(unpack("B64", pack("Q>", $v)), -$bits); # needs v5.9.2 |
|
745
|
0
|
|
|
|
|
|
return substr(unpack("B32", pack("N", $v>>32)), -($bits-32)) |
|
746
|
|
|
|
|
|
|
. unpack("B32", pack("N", $v)); |
|
747
|
|
|
|
|
|
|
} else { |
|
748
|
|
|
|
|
|
|
# return substr(unpack("B32", pack("N", $v)), -$bits); # slower |
|
749
|
0
|
|
|
|
|
|
return scalar reverse unpack("b$bits", pack("V", $v)); |
|
750
|
|
|
|
|
|
|
} |
|
751
|
|
|
|
|
|
|
} |
|
752
|
|
|
|
|
|
|
|
|
753
|
28
|
|
|
28
|
|
191
|
no Moo::Role; |
|
|
28
|
|
|
|
|
65
|
|
|
|
28
|
|
|
|
|
391
|
|
|
754
|
|
|
|
|
|
|
1; |
|
755
|
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
# ABSTRACT: A Role implementing the API for Data::BitStream |
|
758
|
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
=pod |
|
760
|
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
=head1 NAME |
|
762
|
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
Data::BitStream::Base - A Role implementing the API for Data::BitStream |
|
764
|
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
766
|
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
use Moo; |
|
768
|
|
|
|
|
|
|
with 'Data::BitStream::Base'; |
|
769
|
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
771
|
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
A role written for L that provides the basic API, including |
|
773
|
|
|
|
|
|
|
generic code for almost all functionality. |
|
774
|
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
This is used by particular implementations such as L |
|
776
|
|
|
|
|
|
|
and L. |
|
777
|
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
=head2 DATA |
|
782
|
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
=over 4 |
|
784
|
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
=item B< pos > |
|
786
|
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
A read-only non-negative integer indicating the current position in a read |
|
788
|
|
|
|
|
|
|
stream. It is advanced by C, C, and C methods, as well |
|
789
|
|
|
|
|
|
|
as changed by C, C, C, and C methods. |
|
790
|
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
=item B< len > |
|
792
|
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
A read-only non-negative integer indicating the current length of the stream |
|
794
|
|
|
|
|
|
|
in bits. It is advanced by C and C methods, as well as changed |
|
795
|
|
|
|
|
|
|
by C and C methods. |
|
796
|
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
=item B< writing > |
|
798
|
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
A read-only boolean indicating whether the stream is open for writing or |
|
800
|
|
|
|
|
|
|
reading. Methods for read such as |
|
801
|
|
|
|
|
|
|
C, C, C, C, C, and C |
|
802
|
|
|
|
|
|
|
are not allowed while writing. Methods for write such as |
|
803
|
|
|
|
|
|
|
C and C |
|
804
|
|
|
|
|
|
|
are not allowed while reading. |
|
805
|
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
The C and C methods will set writing to true. |
|
807
|
|
|
|
|
|
|
The C and C methods will set writing to false. |
|
808
|
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
The read/write distinction allows implementations more freedom in internal |
|
810
|
|
|
|
|
|
|
caching of data. For instance, they can gather writes into blocks. It also |
|
811
|
|
|
|
|
|
|
can be helpful in catching mistakes such as reading from a target stream. |
|
812
|
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
=item B< mode > |
|
814
|
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
The stream mode. Especially useful when given a file. The mode may be one of |
|
816
|
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
r (read) |
|
818
|
|
|
|
|
|
|
ro (readonly) |
|
819
|
|
|
|
|
|
|
w (write) |
|
820
|
|
|
|
|
|
|
wo (writeonly) |
|
821
|
|
|
|
|
|
|
rdwr (readwrite) |
|
822
|
|
|
|
|
|
|
a (append) |
|
823
|
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
=item B< file > |
|
825
|
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
The name of a file to read or write (depending on the mode). |
|
827
|
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
=item B< fheaderlines > |
|
829
|
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
Only applicible when reading a file. Indicates how many header lines exist |
|
831
|
|
|
|
|
|
|
before the data. |
|
832
|
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
=item B< fheader > |
|
834
|
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
When writing a file, this is the header to write before the data. |
|
836
|
|
|
|
|
|
|
When reading a file, this will be set to the header, if fheaderlines was given. |
|
837
|
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
=back |
|
839
|
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
=head2 CLASS METHODS |
|
844
|
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
=over 4 |
|
846
|
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
=item B< maxbits > |
|
848
|
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
Returns the number of bits in a word, which is the largest allowed size of |
|
850
|
|
|
|
|
|
|
the C argument to C and C. This will be either 32 or 64. |
|
851
|
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
=item B< maxval > |
|
853
|
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
Returns the maximum value we can handle. This should be C< 2 ** maxbits - 1 >, |
|
855
|
|
|
|
|
|
|
or C< 0xFFFF_FFFF > for 32-bit, and C< 0xFFFF_FFFF_FFFF_FFFF > for 64-bit. |
|
856
|
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
=back |
|
858
|
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
=head2 OBJECT METHODS (I) |
|
863
|
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
These methods are only valid while the stream is in reading state. |
|
865
|
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
=over 4 |
|
867
|
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
=item B< rewind > |
|
869
|
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
Moves the position to the stream beginning. |
|
871
|
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
=item B< exhausted > |
|
873
|
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
Returns true is the stream is at the end. Rarely used. |
|
875
|
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
=item B< read($bits [, 'readahead']) > |
|
877
|
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
Reads C<$bits> from the stream and returns the value. |
|
879
|
|
|
|
|
|
|
C<$bits> must be between C<1> and C. |
|
880
|
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
Returns undef if the current position is at the end of the stream. |
|
882
|
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
Croaks with an off stream error if not enough bits are left in the stream. |
|
884
|
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
The position is advanced unless the second argument is the string 'readahead'. |
|
886
|
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
I: You have to implement this. |
|
888
|
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
=item B< readahead($bits>) > |
|
890
|
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
Identical to calling read with 'readahead' as the second argument. |
|
892
|
|
|
|
|
|
|
Returns the value of the next C<$bits> bits (between C<1> and C). |
|
893
|
|
|
|
|
|
|
Returns undef if the current position is at the end. |
|
894
|
|
|
|
|
|
|
Allows reading past the end of the stream (fills with zeros as necessary). |
|
895
|
|
|
|
|
|
|
Does not advance the position. |
|
896
|
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
=item B< skip($bits) > |
|
898
|
|
|
|
|
|
|
|
|
899
|
|
|
|
|
|
|
Advances the position C<$bits> bits. |
|
900
|
|
|
|
|
|
|
Typically used in conjunction with C. |
|
901
|
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
=item B< get_unary([$count]) > |
|
903
|
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
Reads one or more values from the stream in C<0000...1> unary coding. |
|
905
|
|
|
|
|
|
|
If C<$count> is C<1> or not supplied, a single value will be read. |
|
906
|
|
|
|
|
|
|
If C<$count> is positive, that many values will be read. |
|
907
|
|
|
|
|
|
|
If C<$count> is negative, values are read until the end of the stream. |
|
908
|
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
In list context this returns a list of all values read. In scalar context |
|
910
|
|
|
|
|
|
|
it returns the last value read. |
|
911
|
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
I: You should have efficient code for this. |
|
913
|
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
=item B< get_unary1([$count]) > |
|
915
|
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
Like C, but using C<1111...0> unary coding. Less common. |
|
917
|
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
=item B< get_binword($bits, [$count]) > |
|
919
|
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
Reads one or more values from the stream as fixed-length binary numbers, each |
|
921
|
|
|
|
|
|
|
using C<$bits> bits. The treatment of count and return values is identical to |
|
922
|
|
|
|
|
|
|
C. |
|
923
|
|
|
|
|
|
|
|
|
924
|
|
|
|
|
|
|
=item B< read_string($bits) > |
|
925
|
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
Reads C<$bits> bits from the stream and returns them as a binary string, such |
|
927
|
|
|
|
|
|
|
as '0011011'. |
|
928
|
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
=back |
|
930
|
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
|
|
932
|
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
=head2 OBJECT METHODS (I) |
|
935
|
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
These methods are only valid while the stream is in writing state. |
|
937
|
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
=over 4 |
|
939
|
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
=item B< write($bits, $value) > |
|
941
|
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
Writes C<$value> to the stream using C<$bits> bits. |
|
943
|
|
|
|
|
|
|
C<$bits> must be between C<1> and C, unless C is 0 or 1, in |
|
944
|
|
|
|
|
|
|
which case C may be larger than C. |
|
945
|
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
The stream length will be increased by C<$bits> bits. |
|
947
|
|
|
|
|
|
|
Regardless of the contents of C<$value>, exactly C<$bits> bits will be used. |
|
948
|
|
|
|
|
|
|
If C<$value> has more non-zero bits than C<$bits>, the lower bits are written. |
|
949
|
|
|
|
|
|
|
In other words, C<$value> will be masked before writing. |
|
950
|
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
I: You have to implement this. |
|
952
|
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
=item B< put_unary(@values) > |
|
954
|
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
Writes the values to the stream in C<0000...1> unary coding. |
|
956
|
|
|
|
|
|
|
Unary coding is only appropriate for relatively small numbers, as it uses |
|
957
|
|
|
|
|
|
|
C<$value + 1> bits. |
|
958
|
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
I: You should have efficient code for this. |
|
960
|
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
=item B< put_unary1(@values) > |
|
962
|
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
Like C, but using C<1111...0> unary coding. Less common. |
|
964
|
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
=item B< put_binword($bits, @values) > |
|
966
|
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
Writes the values to the stream as fixed-length binary values. This is just |
|
968
|
|
|
|
|
|
|
a loop inserting each value with C. |
|
969
|
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
=item B< put_string(@strings) > |
|
971
|
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
Takes one or more binary strings, such as '1001101', '001100', etc. and |
|
973
|
|
|
|
|
|
|
writes them to the stream. The number of bits used for each value is equal |
|
974
|
|
|
|
|
|
|
to the string length. |
|
975
|
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
=item B< put_raw($packed, [, $bits]) > |
|
977
|
|
|
|
|
|
|
Writes the packed big-endian vector C<$packed> which has C<$bits> bits of data. |
|
978
|
|
|
|
|
|
|
If C<$bits> is not present, then C will be used as the |
|
979
|
|
|
|
|
|
|
byte-length. It is recommended that you include C<$bits>. |
|
980
|
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
=item B< put_stream($source_stream) > |
|
982
|
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
Writes the contents of C<$source_stream> to the stream. This is a helper |
|
984
|
|
|
|
|
|
|
method that might be more efficient than doing it in one of the many other |
|
985
|
|
|
|
|
|
|
possible ways. Some functionally equivalent methods: |
|
986
|
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
$self->put_string( $source_stream->to_string ); # The default for put_stream |
|
988
|
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
$self->put_raw( $source_stream->to_raw, $source_stream->len ); |
|
990
|
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
my $bits = $source_stream->len; |
|
992
|
|
|
|
|
|
|
$source_stream->rewind_for_read; |
|
993
|
|
|
|
|
|
|
while ($bits > 0) { |
|
994
|
|
|
|
|
|
|
my $wbits = ($bits >= 32) ? 32 : $bits; |
|
995
|
|
|
|
|
|
|
$self->write($wbits, $source_stream->read($wbits)); |
|
996
|
|
|
|
|
|
|
$bits -= $wbits; |
|
997
|
|
|
|
|
|
|
} |
|
998
|
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
=back |
|
1000
|
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
=head2 OBJECT METHODS (I) |
|
1005
|
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
These methods may be called at any time, and will adjust the state of the |
|
1007
|
|
|
|
|
|
|
stream. |
|
1008
|
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
=over 4 |
|
1010
|
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
=item B< to_string > |
|
1012
|
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
Returns the stream as a binary string, e.g. '00110101'. |
|
1014
|
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
=item B< to_raw > |
|
1016
|
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
Returns the stream as packed big-endian data. This form is portable to |
|
1018
|
|
|
|
|
|
|
any other implementation on any architecture. |
|
1019
|
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
=item B< to_store > |
|
1021
|
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
Returns the stream as some scalar holding the data in some implementation |
|
1023
|
|
|
|
|
|
|
specific way. This may be portable or not, but it can always be read by |
|
1024
|
|
|
|
|
|
|
the same implementation. It might be more efficient than the raw format. |
|
1025
|
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
=item B< from_string($string) > |
|
1028
|
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
The stream will be set to the binary string C<$string>. |
|
1030
|
|
|
|
|
|
|
|
|
1031
|
|
|
|
|
|
|
=item B< from_raw($packed [, $bits]) > |
|
1032
|
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
The stream is set to the packed big-endian vector C<$packed> which has |
|
1034
|
|
|
|
|
|
|
C<$bits> bits of data. If C<$bits> is not present, then C |
|
1035
|
|
|
|
|
|
|
will be used as the byte-length. It is recommended that you include C<$bits>. |
|
1036
|
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
=item B< from_store($blob [, $bits]) > |
|
1038
|
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
Similar to C, but using the value returned by C. |
|
1040
|
|
|
|
|
|
|
|
|
1041
|
|
|
|
|
|
|
=back |
|
1042
|
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
=head2 OBJECT METHODS (I) |
|
1047
|
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
=over 4 |
|
1049
|
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
=item B< erase > |
|
1051
|
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
Erases all the data, while the writing state is left unchanged. The position |
|
1053
|
|
|
|
|
|
|
and length will both be 0 after this is finished. |
|
1054
|
|
|
|
|
|
|
|
|
1055
|
|
|
|
|
|
|
I: You need an 'after' method to actually erase the data. |
|
1056
|
|
|
|
|
|
|
|
|
1057
|
|
|
|
|
|
|
=item B< read_open > |
|
1058
|
|
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
Reads the current input file, if one exists. |
|
1060
|
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
=item B< write_open > |
|
1062
|
|
|
|
|
|
|
|
|
1063
|
|
|
|
|
|
|
Changes the state to writing with no other API-visible changes. |
|
1064
|
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
=item B< write_close > |
|
1066
|
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
Changes the state to reading, and the position is set to the end of the |
|
1068
|
|
|
|
|
|
|
stream. No other API-visible changes happen. |
|
1069
|
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
=item B< erase_for_write > |
|
1071
|
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
A helper function that performs C followed by C. |
|
1073
|
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
=item B< rewind_for_read > |
|
1075
|
|
|
|
|
|
|
|
|
1076
|
|
|
|
|
|
|
A helper function that performs C followed by C. |
|
1077
|
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
=back |
|
1079
|
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
|
|
1082
|
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
=head2 INTERNAL METHODS |
|
1084
|
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
These methods are used by roles. |
|
1086
|
|
|
|
|
|
|
As a stream user you should not be using these. |
|
1087
|
|
|
|
|
|
|
|
|
1088
|
|
|
|
|
|
|
=over 4 |
|
1089
|
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
=item B< code_pos_start > |
|
1091
|
|
|
|
|
|
|
|
|
1092
|
|
|
|
|
|
|
=item B< code_pos_end > |
|
1093
|
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
=item B< code_pos_set > |
|
1095
|
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
Used to handle exceptions for codes that call other codes. Generally used |
|
1097
|
|
|
|
|
|
|
in C< get_* > methods. The primary reasoning for this is that we want to |
|
1098
|
|
|
|
|
|
|
unroll the stream location back to where the caller tried to read the code |
|
1099
|
|
|
|
|
|
|
on an error. That way they can try again with a different code, or examine |
|
1100
|
|
|
|
|
|
|
the bits that resulted in an incorrect code. |
|
1101
|
|
|
|
|
|
|
C starts a new stack entry, C sets the start |
|
1102
|
|
|
|
|
|
|
of the current code so we know where to go back to, and C |
|
1103
|
|
|
|
|
|
|
indicates we're done so the code stack entry can be removed. |
|
1104
|
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
=item B< code_pos_is_set > |
|
1106
|
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
Returns the code stack or C if not in a code. This should always be |
|
1108
|
|
|
|
|
|
|
C for users. If it is not, it means some code routine finished |
|
1109
|
|
|
|
|
|
|
abnormally and didn't remove their error stack. |
|
1110
|
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
=item B< error_off_stream > |
|
1112
|
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
Croaks with a message about reading or skipping off the stream. If this |
|
1114
|
|
|
|
|
|
|
happens inside a C method, it should indicate the outermost code that |
|
1115
|
|
|
|
|
|
|
was used. The stream position is restored to the start of the outer code. |
|
1116
|
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
=item B< error_stream_mode > |
|
1118
|
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
Croaks with a message about the wrong mode being used. This is what happens |
|
1120
|
|
|
|
|
|
|
when an attempt is made to write to a stream opened for reading, or read from |
|
1121
|
|
|
|
|
|
|
a stream opened for writing. |
|
1122
|
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
=item B< error_code > |
|
1124
|
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
Central routine that captures code errors, including incorrect parameters, |
|
1126
|
|
|
|
|
|
|
values out of range, overflows, range errors, etc. All errors cause a croak |
|
1127
|
|
|
|
|
|
|
except assertions, which will confess (since they indicate a serious internal |
|
1128
|
|
|
|
|
|
|
issue). Some additional information is also included if possible (e.g. the |
|
1129
|
|
|
|
|
|
|
outermost code being used, the allowed range, the value, etc.). |
|
1130
|
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
=back |
|
1132
|
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
1137
|
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
=over 4 |
|
1139
|
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
=item L |
|
1141
|
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
=item L |
|
1143
|
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
=item L |
|
1145
|
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
=back |
|
1147
|
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
=head1 AUTHORS |
|
1149
|
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
Dana Jacobsen Edana@acm.orgE |
|
1151
|
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
1153
|
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
Copyright 2011-2012 by Dana Jacobsen Edana@acm.orgE |
|
1155
|
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |
|
1157
|
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
=cut |