line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Bit::MorseSignals::Receiver; |
2
|
|
|
|
|
|
|
|
3
|
9
|
|
|
9
|
|
109144
|
use strict; |
|
9
|
|
|
|
|
21
|
|
|
9
|
|
|
|
|
387
|
|
4
|
9
|
|
|
9
|
|
51
|
use warnings; |
|
9
|
|
|
|
|
17
|
|
|
9
|
|
|
|
|
283
|
|
5
|
|
|
|
|
|
|
|
6
|
9
|
|
|
9
|
|
50
|
use Carp qw; |
|
9
|
|
|
|
|
17
|
|
|
9
|
|
|
|
|
588
|
|
7
|
9
|
|
|
9
|
|
4207
|
use Encode qw; |
|
9
|
|
|
|
|
46677
|
|
|
9
|
|
|
|
|
579
|
|
8
|
9
|
|
|
9
|
|
4085
|
use Storable qw; |
|
9
|
|
|
|
|
18648
|
|
|
9
|
|
|
|
|
559
|
|
9
|
|
|
|
|
|
|
|
10
|
9
|
|
|
9
|
|
2190
|
use Bit::MorseSignals qw<:consts>; |
|
9
|
|
|
|
|
18
|
|
|
9
|
|
|
|
|
9477
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 NAME |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Bit::MorseSignals::Receiver - Base class for Bit::MorseSignals receivers. |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 VERSION |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
Version 0.08 |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=cut |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
our $VERSION = '0.08'; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 SYNOPSIS |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
use Bit::MorseSignals::Receiver; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my $pants = Bit::MorseSignals::Receiver->new(done => sub { print "received $_[1]!\n" }); |
29
|
|
|
|
|
|
|
while (...) { |
30
|
|
|
|
|
|
|
my $bit = comes_from_somewhere_lets_say_signals(); |
31
|
|
|
|
|
|
|
$pants->push($bit); |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 DESCRIPTION |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
Base class for L receivers. Please refer to this module for more general information about the protocol. |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
Given a sequence of bits coming from the L protocol, the receiver object detects when a packet has been completed and then reconstructs the original message depending of the datatype specified in the header. |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=cut |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub _check_self { |
43
|
5596
|
100
|
100
|
5596
|
|
31577
|
croak 'First argument isn\'t a valid ' . __PACKAGE__ . ' object' |
44
|
|
|
|
|
|
|
unless ref $_[0] and $_[0]->isa(__PACKAGE__); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 METHODS |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=head2 C<< new < done => $cb > >> |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
L object constructor. With the C<'done'> option, you can specify a callback that will be triggered every time a message is completed, and in which C<$_[0]> will be the receiver object and C<$_[1]> the message received. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=cut |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub new { |
56
|
10
|
|
|
10
|
1
|
1338
|
my $class = shift; |
57
|
10
|
100
|
100
|
|
|
78
|
return unless $class = ref $class || $class; |
58
|
9
|
100
|
|
|
|
207
|
croak 'Optional arguments must be passed as key => value pairs' if @_ % 2; |
59
|
8
|
|
|
|
|
25
|
my %opts = @_; |
60
|
8
|
|
|
|
|
33
|
my $self = { |
61
|
|
|
|
|
|
|
msg => undef, |
62
|
|
|
|
|
|
|
done => $opts{done}, |
63
|
|
|
|
|
|
|
}; |
64
|
8
|
|
|
|
|
26
|
bless $self, $class; |
65
|
8
|
|
|
|
|
31
|
$self->reset; |
66
|
8
|
|
|
|
|
28
|
return $self; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head2 C |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Tells the receiver that you have received the bit C<$bit>. Returns true while the message isn't completed, and C as soon as it is. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=cut |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub push { |
76
|
5552
|
|
|
5552
|
1
|
19316
|
my ($self, $bit) = @_; |
77
|
5552
|
|
|
|
|
8234
|
_check_self($self); |
78
|
5550
|
100
|
|
|
|
10471
|
if (!defined $bit) { |
79
|
5527
|
|
|
|
|
5898
|
$bit = $_; |
80
|
5527
|
100
|
|
|
|
10484
|
return unless defined $bit; |
81
|
|
|
|
|
|
|
} |
82
|
5549
|
100
|
|
|
|
8991
|
$bit = $bit ? 1 : 0; |
83
|
|
|
|
|
|
|
|
84
|
5549
|
100
|
|
|
|
15625
|
if ($self->{state} == 3) { # data |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
85
|
|
|
|
|
|
|
|
86
|
5301
|
|
|
|
|
12414
|
vec($self->{buf}, $self->{len}, 1) = $bit; |
87
|
5301
|
|
|
|
|
8064
|
++$self->{len}; |
88
|
5301
|
100
|
|
|
|
11587
|
if ($self->{len} >= $self->{sig_len}) { |
89
|
5153
|
|
|
|
|
6191
|
my $res = 1; |
90
|
5153
|
|
|
|
|
8832
|
for (1 .. $self->{sig_len}) { |
91
|
9592
|
100
|
|
|
|
26100
|
if (vec($self->{buf}, $self->{len} - $_, 1) != vec($self->{sig}, $_-1, 1)) { |
92
|
5128
|
|
|
|
|
5253
|
$res = 0; |
93
|
5128
|
|
|
|
|
6620
|
last; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
} |
96
|
5153
|
100
|
|
|
|
11000
|
if ($res) { |
97
|
25
|
|
|
|
|
128
|
my $base = int $self->{sig_len} / 8 + $self->{sig_len} % 8 != 0; |
98
|
25
|
|
|
|
|
81
|
substr $self->{buf}, -$base, $base, ''; |
99
|
25
|
|
|
9
|
|
245
|
my @demanglers = (sub { $_[0] }, \&decode_utf8, \&thaw ); |
|
9
|
|
|
|
|
67
|
|
100
|
|
|
|
|
|
|
# BM_DATA_{PLAIN, UTF8, STORABLE} |
101
|
|
|
|
|
|
|
$self->{msg} = defined $demanglers[$self->{type}] |
102
|
25
|
100
|
|
|
|
113
|
? do { |
103
|
24
|
|
|
2
|
|
232
|
local $SIG{__DIE__} = sub { warn @_ }; |
|
2
|
|
|
|
|
269
|
|
104
|
24
|
|
|
|
|
126
|
$demanglers[$self->{type}]->($self->{buf}) |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
: $self->{buf}; |
107
|
24
|
|
|
|
|
629
|
$self->reset; |
108
|
24
|
100
|
|
|
|
135
|
$self->{done}->($self, $self->{msg}) if $self->{done}; |
109
|
24
|
|
|
|
|
17270
|
return; |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
} elsif ($self->{state} == 2) { # header |
114
|
|
|
|
|
|
|
|
115
|
75
|
|
|
|
|
194
|
vec($self->{buf}, $self->{len}++, 1) = $bit; |
116
|
75
|
100
|
|
|
|
209
|
if ($self->{len} >= 3) { |
117
|
25
|
|
|
|
|
71
|
my $type = 2 * vec($self->{buf}, 1, 1) |
118
|
|
|
|
|
|
|
+ vec($self->{buf}, 0, 1); |
119
|
25
|
100
|
|
|
|
72
|
$type = BM_DATA_PLAIN if vec($self->{buf}, 2, 1); |
120
|
25
|
|
|
|
|
49
|
@{$self}{qw} = (3, $type, '', 0); |
|
25
|
|
|
|
|
85
|
|
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
} elsif ($self->{state} == 1) { # end of signature |
124
|
|
|
|
|
|
|
|
125
|
148
|
100
|
|
|
|
326
|
if ($self->{sig_bit} != $bit) { |
126
|
25
|
|
|
|
|
42
|
$self->{state} = 2; |
127
|
|
|
|
|
|
|
} |
128
|
148
|
|
|
|
|
446
|
vec($self->{sig}, $self->{sig_len}++, 1) = $bit; |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
} else { # first bit |
131
|
|
|
|
|
|
|
|
132
|
25
|
|
|
|
|
54
|
@{$self}{qw} |
|
25
|
|
|
|
|
116
|
|
133
|
|
|
|
|
|
|
= (1, '', $bit, 1, '', 0 ); |
134
|
25
|
|
|
|
|
97
|
vec($self->{sig}, 0, 1) = $bit; |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
5524
|
|
|
|
|
18444
|
return $self; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=head2 C |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
Resets the current receiver state, obliterating any current message being received. |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=cut |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub reset { |
148
|
35
|
|
|
35
|
1
|
1523
|
my ($self) = @_; |
149
|
35
|
|
|
|
|
85
|
_check_self($self); |
150
|
33
|
|
|
|
|
75
|
$self->{state} = 0; |
151
|
33
|
|
|
|
|
64
|
@{$self}{qw} = (); |
|
33
|
|
|
|
|
109
|
|
152
|
33
|
|
|
|
|
65
|
return $self; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head2 C |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
True when the receiver is in the middle of assembling a message. |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub busy { |
162
|
5
|
|
|
5
|
1
|
860
|
my ($self) = @_; |
163
|
5
|
|
|
|
|
18
|
_check_self($self); |
164
|
3
|
|
|
|
|
16
|
return $self->{state} > 0; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=head2 C |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
The last message completed, or C when no message has been assembled yet. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=cut |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub msg { |
174
|
4
|
|
|
4
|
1
|
1878
|
my ($self) = @_; |
175
|
4
|
|
|
|
|
12
|
_check_self($self); |
176
|
2
|
|
|
|
|
16
|
return $self->{msg}; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 EXPORT |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
An object module shouldn't export any function, and so does this one. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
L (standard since perl 5), L (since perl 5.007003), L (idem). |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=head1 SEE ALSO |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
L, L. |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=head1 AUTHOR |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
Vincent Pit, C<< >>, L. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
You can contact me by mail or on C (vincent). |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=head1 BUGS |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=head1 SUPPORT |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
perldoc Bit::MorseSignals::Receiver |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
Tests code coverage report is available at L. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
Copyright 2008 Vincent Pit, all rights reserved. |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
214
|
|
|
|
|
|
|
under the same terms as Perl itself. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=cut |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
1; # End of Bit::MorseSignals::Receiver |