File Coverage

blib/lib/Bit/MorseSignals/Receiver.pm
Criterion Covered Total %
statement 79 79 100.0
branch 34 34 100.0
condition 6 6 100.0
subroutine 14 14 100.0
pod 5 5 100.0
total 138 138 100.0


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