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 |