line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Bit::MorseSignals::Emitter; |
2
|
|
|
|
|
|
|
|
3
|
8
|
|
|
8
|
|
117594
|
use strict; |
|
8
|
|
|
|
|
22
|
|
|
8
|
|
|
|
|
304
|
|
4
|
8
|
|
|
8
|
|
46
|
use warnings; |
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
316
|
|
5
|
|
|
|
|
|
|
|
6
|
8
|
|
|
8
|
|
47
|
use Carp qw; |
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
545
|
|
7
|
8
|
|
|
8
|
|
18756
|
use Encode qw; |
|
8
|
|
|
|
|
105083
|
|
|
8
|
|
|
|
|
812
|
|
8
|
8
|
|
|
8
|
|
11318
|
use Storable qw; |
|
8
|
|
|
|
|
31309
|
|
|
8
|
|
|
|
|
742
|
|
9
|
|
|
|
|
|
|
|
10
|
8
|
|
|
8
|
|
3723
|
use Bit::MorseSignals qw<:consts>; |
|
8
|
|
|
|
|
34
|
|
|
8
|
|
|
|
|
12037
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 NAME |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Bit::MorseSignals::Emitter - Base class for Bit::MorseSignals emitters. |
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::Emitter; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my $deuce = Bit::MorseSignals::Emitter->new; |
29
|
|
|
|
|
|
|
$deuce->post("hlagh") for 1 .. 3; |
30
|
|
|
|
|
|
|
while (defined(my $bit = $deuce->pop)) { |
31
|
|
|
|
|
|
|
sends_by_some_mean_lets_say_signals($bit); |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 DESCRIPTION |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
Base class for L emitters. Please refer to this module for more general information about the protocol. |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
The emitter object enqueues messages and prepares them one by one into L packets. It gives then back the bits of the packet in the order they should be sent. |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=cut |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub _check_self { |
43
|
6264
|
100
|
100
|
6264
|
|
37910
|
croak 'First argument isn\'t a valid ' . __PACKAGE__ . ' object' |
44
|
|
|
|
|
|
|
unless ref $_[0] and $_[0]->isa(__PACKAGE__); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub _count_bits { |
48
|
60
|
|
|
60
|
|
160
|
my ($len, $cur, $seq, $lng) = @_[1 .. 4]; |
49
|
60
|
|
|
|
|
175
|
for (my $i = 0; $i < $len; ++$i) { |
50
|
5250
|
|
|
|
|
5777
|
my $bit = vec $_[0], $i, 1; |
51
|
5250
|
100
|
|
|
|
7663
|
if ($cur == $bit) { |
52
|
3167
|
|
|
|
|
6229
|
++$seq; |
53
|
|
|
|
|
|
|
} else { |
54
|
2083
|
100
|
|
|
|
3691
|
$lng->[$cur] = $seq if $seq > $lng->[$cur]; |
55
|
2083
|
|
|
|
|
2182
|
$seq = 1; |
56
|
2083
|
|
|
|
|
4628
|
$cur = $bit; |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
} |
59
|
60
|
100
|
|
|
|
163
|
$lng->[$cur] = $seq if $seq > $lng->[$cur]; |
60
|
60
|
|
|
|
|
190
|
return $cur, $seq; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=head1 METHODS |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=head2 C |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
L object constructor. Currently does not take any optional argument. |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=cut |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub new { |
72
|
9
|
|
|
9
|
1
|
2240
|
my $class = shift; |
73
|
9
|
100
|
100
|
|
|
78
|
return unless $class = ref $class || $class; |
74
|
8
|
100
|
|
|
|
212
|
croak 'Optional arguments must be passed as key => value pairs' if @_ % 2; |
75
|
7
|
|
|
|
|
63
|
my %opts = @_; |
76
|
7
|
|
|
|
|
30
|
my $self = { |
77
|
|
|
|
|
|
|
queue => [], |
78
|
|
|
|
|
|
|
}; |
79
|
7
|
|
|
|
|
25
|
bless $self, $class; |
80
|
7
|
|
|
|
|
34
|
$self->reset; |
81
|
7
|
|
|
|
|
23
|
return $self; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=head2 C<< post $msg, < type => $type > >> |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Adds C<$msg> to the message queue and, if no other message is currently processed, dequeue the oldest item and prepare it. The type is automatically chosen, but you may want to try to force it with the C option : C<$type> is then one of the C constants listed in L |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=cut |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub post { |
91
|
99
|
|
|
99
|
1
|
2563
|
my $self = shift; |
92
|
99
|
|
|
|
|
163
|
my $msg = shift; |
93
|
99
|
|
|
|
|
176
|
_check_self($self); |
94
|
97
|
100
|
|
|
|
401
|
croak 'Optional arguments must be passed as key => value pairs' if @_ % 2; |
95
|
96
|
|
|
|
|
177
|
my %opts = @_; |
96
|
|
|
|
|
|
|
|
97
|
96
|
|
|
|
|
149
|
my $type = $opts{type}; |
98
|
|
|
|
|
|
|
|
99
|
96
|
100
|
|
|
|
312
|
if (defined $msg) { |
|
|
100
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
101
|
54
|
|
|
36
|
|
266
|
my @manglers = (sub { $_[0] }, \&encode_utf8, \&freeze); |
|
36
|
|
|
|
|
60
|
|
102
|
|
|
|
|
|
|
# BM_DATA_{PLAIN, UTF8, STORABLE} |
103
|
54
|
100
|
100
|
|
|
199
|
$type = BM_DATA_AUTO unless defined $type and exists $manglers[$type]; |
104
|
54
|
100
|
|
|
|
161
|
if (ref $msg) { |
|
|
100
|
|
|
|
|
|
105
|
10
|
100
|
|
|
|
16
|
return if { map { $_ => 1 } qw }->{ref $msg}; |
|
20
|
|
|
|
|
86
|
|
106
|
8
|
|
|
|
|
18
|
$type = BM_DATA_STORABLE; |
107
|
|
|
|
|
|
|
} elsif ($type == BM_DATA_AUTO) { |
108
|
43
|
100
|
|
|
|
163
|
$type = is_utf8($msg) ? BM_DATA_UTF8 : BM_DATA_PLAIN; |
109
|
|
|
|
|
|
|
} |
110
|
52
|
|
|
|
|
129
|
$msg = $manglers[$type]->($msg); |
111
|
|
|
|
|
|
|
|
112
|
52
|
100
|
|
|
|
618
|
if ($self->{state}) { # Busy/queued, can't handle this message right now. |
113
|
43
|
|
|
|
|
61
|
push @{$self->{queue}}, [ $msg, $type ]; |
|
43
|
|
|
|
|
132
|
|
114
|
43
|
100
|
|
|
|
316
|
return -1 if $self->{state} == 2; # Currently sending |
115
|
1
|
|
|
|
|
2
|
($msg, $type) = @{shift @{$self->{queue}}}; # Otherwise something's queued |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
9
|
|
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
} elsif ($self->{state} == 1) { # No msg was given, but the queue isn't empty. |
119
|
|
|
|
|
|
|
|
120
|
20
|
|
|
|
|
90
|
($msg, $type) = @{shift @{$self->{queue}}}; |
|
20
|
|
|
|
|
28
|
|
|
20
|
|
|
|
|
139
|
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
} else { # Either unused or busy sending. |
123
|
|
|
|
|
|
|
|
124
|
22
|
|
|
|
|
106
|
return; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
30
|
|
|
|
|
93
|
$self->{state} = 2; |
129
|
|
|
|
|
|
|
|
130
|
30
|
|
|
|
|
55
|
my $head = ''; |
131
|
30
|
|
|
|
|
119
|
vec($head, 0, 1) = ($type & 1); |
132
|
30
|
|
|
|
|
116
|
vec($head, 1, 1) = ($type & 2) >> 1; |
133
|
30
|
|
|
|
|
73
|
vec($head, 2, 1) = 0; |
134
|
30
|
|
|
|
|
62
|
my $hlen = 3; |
135
|
|
|
|
|
|
|
|
136
|
30
|
|
|
|
|
79
|
my $len = 8 * length $msg; |
137
|
30
|
|
|
|
|
71
|
my @lng = (0, 0, 0); |
138
|
30
|
|
|
|
|
120
|
my ($cur, $seq) = _count_bits $head, $hlen, 2, 0, \@lng; |
139
|
30
|
|
|
|
|
99
|
($cur, $seq) = _count_bits $msg, $len, $cur, $seq, \@lng; |
140
|
30
|
100
|
|
|
|
120
|
($cur, $seq) = ($lng[0] > $lng[1]) ? (1, $lng[1]) |
141
|
|
|
|
|
|
|
: (0, $lng[0]); # Take the smallest. |
142
|
30
|
|
|
|
|
50
|
++$seq; |
143
|
|
|
|
|
|
|
|
144
|
30
|
|
|
|
|
93
|
$self->{len} = 1 + $seq + $hlen + $len + $seq + 1; |
145
|
30
|
|
|
|
|
59
|
$self->{buf} = ''; |
146
|
30
|
|
|
|
|
57
|
my ($i, $j, $k) = (0, 0, 0); |
147
|
30
|
|
|
|
|
379
|
vec($self->{buf}, $i++, 1) = $cur for 1 .. $seq; |
148
|
30
|
|
|
|
|
97
|
vec($self->{buf}, $i++, 1) = 1 - $cur; |
149
|
30
|
|
|
|
|
242
|
vec($self->{buf}, $i++, 1) = vec($head, $j++, 1) for 1 .. $hlen; |
150
|
30
|
|
|
|
|
5838
|
vec($self->{buf}, $i++, 1) = vec($msg, $k++, 1) for 1 .. $len; |
151
|
30
|
|
|
|
|
101
|
vec($self->{buf}, $i++, 1) = 1 - $cur; |
152
|
30
|
|
|
|
|
310
|
vec($self->{buf}, $i++, 1) = $cur for 1 .. $seq; |
153
|
|
|
|
|
|
|
|
154
|
30
|
|
|
|
|
63
|
$self->{pos} = 0; |
155
|
|
|
|
|
|
|
|
156
|
30
|
|
|
|
|
125
|
return 1; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=head2 C |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
If a message is being processed, pops the next bit in the packet. When the message is over, the next in the queue is immediatly prepared and the first bit of the new packet is given back. If the queue is empty, C is returned. You may want to use this method with the idiom : |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
while (defined(my $bit = $deuce->pop)) { |
164
|
|
|
|
|
|
|
... |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=cut |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub pop { |
170
|
5672
|
|
|
5672
|
1
|
57321
|
my ($self) = @_; |
171
|
5672
|
|
|
|
|
8675
|
_check_self($self); |
172
|
5670
|
100
|
|
|
|
12202
|
return if $self->{state} == 0; |
173
|
5662
|
100
|
|
|
|
10792
|
$self->post if $self->{state} == 1; |
174
|
5662
|
|
|
|
|
9701
|
my $bit = vec $self->{buf}, $self->{pos}++, 1; |
175
|
5662
|
100
|
|
|
|
11281
|
$self->reset if $self->{pos} >= $self->{len}; |
176
|
5662
|
|
|
|
|
12794
|
return $bit; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head2 C |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
The length of the currently posted message. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=cut |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
sub len { |
186
|
68
|
|
|
68
|
1
|
11593
|
my ($self) = @_; |
187
|
68
|
|
|
|
|
126
|
_check_self($self); |
188
|
66
|
|
|
|
|
311
|
return $self->{len}; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=head2 C |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
The number of bits that have already been sent for the current message. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=cut |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
sub pos { |
198
|
68
|
|
|
68
|
1
|
1076
|
my ($self) = @_; |
199
|
68
|
|
|
|
|
147
|
_check_self($self); |
200
|
66
|
|
|
|
|
202
|
return $self->{pos}; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=head2 C |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
Cancels the current transfer, but does not empty the queue. |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=cut |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
sub reset { |
210
|
39
|
|
|
39
|
1
|
1048
|
my ($self) = @_; |
211
|
39
|
|
|
|
|
94
|
_check_self($self); |
212
|
37
|
|
|
|
|
54
|
$self->{state} = @{$self->{queue}} > 0; |
|
37
|
|
|
|
|
154
|
|
213
|
37
|
|
|
|
|
85
|
@{$self}{qw} = (); |
|
37
|
|
|
|
|
101
|
|
214
|
37
|
|
|
|
|
82
|
return $self; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=head2 C |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
Flushes the queue, but does not cancel the current transfer. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=cut |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
sub flush { |
224
|
24
|
|
|
24
|
1
|
1006
|
my ($self) = @_; |
225
|
24
|
|
|
|
|
48
|
_check_self($self); |
226
|
22
|
|
|
|
|
46
|
$self->{queue} = []; |
227
|
22
|
|
|
|
|
56
|
return $self; |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=head2 C |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
True when the emitter is busy, i.e. when a packet is being chunked. |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=cut |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub busy { |
237
|
259
|
|
|
259
|
1
|
8430
|
my ($self) = @_; |
238
|
259
|
|
|
|
|
470
|
_check_self($self); |
239
|
257
|
|
|
|
|
1203
|
return $self->{state} >= 2; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=head2 C |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Returns the number of queued items. |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=cut |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub queued { |
249
|
35
|
|
|
35
|
1
|
1031
|
my ($self) = @_; |
250
|
35
|
|
|
|
|
65
|
_check_self($self); |
251
|
33
|
|
|
|
|
40
|
return @{$self->{queue}}; |
|
33
|
|
|
|
|
162
|
|
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=head1 EXPORT |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
An object module shouldn't export any function, and so does this one. |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
L (standard since perl 5), L (since perl 5.007003), L (idem). |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=head1 SEE ALSO |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
L, L. |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=head1 AUTHOR |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
Vincent Pit, C<< >>, L. |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
You can contact me by mail or on C (vincent). |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=head1 BUGS |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
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. |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=head1 SUPPORT |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
perldoc Bit::MorseSignals::Emitter |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
Tests code coverage report is available at L. |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
Copyright 2008 Vincent Pit, all rights reserved. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
289
|
|
|
|
|
|
|
under the same terms as Perl itself. |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=cut |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
1; # End of Bit::MorseSignals::Emitter |