File Coverage

blib/lib/AMF/Connection/InputStream.pm
Criterion Covered Total %
statement 12 63 19.0
branch 0 22 0.0
condition 0 9 0.0
subroutine 4 11 36.3
pod 0 7 0.0
total 16 112 14.2


line stmt bran cond sub pod time code
1             package AMF::Connection::InputStream;
2              
3 1     1   5 use strict;
  1         2  
  1         34  
4 1     1   4 use Carp;
  1         1  
  1         1118  
5              
6             our $storable_with_options;
7              
8 1     1   30 eval "use Storable::AMF0 0.84";
  1         24  
  1         34  
9             if ($@)
10             {
11             $storable_with_options = 0;
12             }
13             else
14             {
15             $storable_with_options = 1;
16             }
17              
18 1     1   5 eval "use Storable::AMF3 0.84";
  1         19  
  1         31  
19             if ($@)
20             {
21             $storable_with_options = 0;
22             }
23             else
24             {
25             $storable_with_options = 1;
26             }
27              
28             sub new {
29 0     0 0   my $proto = shift;
30 0   0       my $class = ref($proto) || $proto;
31              
32 0           my ($stream, $storable_amf_options) = @_;
33              
34 0 0         croak "Input stream must be a valid string"
35             if(ref($stream));
36            
37 0           my $self = {
38             'stream' => $stream,
39             'cursor' => 0
40             };
41              
42 0 0         if (defined $storable_amf_options)
43             {
44 0 0         if ($Storable::AMF::VERSION < 0.84)
45             {
46 0           croak "Storable::AMF 0.84 or newer needed to set stream options\n";
47             }
48 0           $self->{'options'} = Storable::AMF::parse_option ($storable_amf_options);
49             }
50              
51 0           return bless($self, $class);
52             };
53              
54             sub readBuffer {
55 0     0 0   my ($class, $length) = @_;
56              
57 0 0         croak "Buffer underrun at position: ". $class->{'cursor'} . ". Trying to fetch ". $length . " bytes from buffer total length ".length($class->{'stream'})
58             if($length + $class->{'cursor'} > length($class->{'stream'}));
59              
60 0           my $data = substr($class->{'stream'},$class->{'cursor'},$length);
61 0           $class->{'cursor'}+=$length;
62            
63 0           return $data;
64             };
65              
66             sub readByte {
67 0     0 0   my ($class) = @_;
68              
69 0           return ord($class->readBuffer(1));
70             };
71              
72             sub readInt {
73 0     0 0   my ($class) = @_;
74              
75 0           my $block = $class->readBuffer(2);
76 0           my @int = unpack("n",$block);
77              
78 0           return $int[0];
79             };
80              
81             sub readDouble {
82 0     0 0   my ($class) = @_;
83              
84 0           my $double = $class->readBuffer(8);
85              
86 0           my @testEndian = unpack("C*",pack("S*",256));
87 0           my $bigEndian = !$testEndian[1]==1;
88 0 0         $double = reverse($double)
89             if($bigEndian);
90 0           my @double = unpack("d",$double);
91              
92 0           return $double[0];
93             };
94              
95             sub readLong {
96 0     0 0   my ($class) = @_;
97              
98 0           my $block = $class->readBuffer(4);
99 0           my @long = unpack("N",$block);
100              
101 0           return $long[0];
102             };
103              
104             # deparse out the next avail AMF entity
105             # TODO - make sure ref counts are reset/preserved between calls in the scope of the same InputStream - study Storable::AMF API
106             sub readAMFData {
107 0     0 0   my ($class) = @_;
108              
109 0           my $type = $class->readByte();
110              
111             # Storable::AMF will take care of deparsing the right AMF format
112 0           $class->{'cursor'}--;
113              
114 0           local $@ = undef;
115              
116 0           my ($obj, $len);
117 0           my $encoding=0;
118 0 0         if($type == 0x11) {
119 0           $encoding=3;
120 0           $class->{'cursor'}++;
121 0 0 0       if ($storable_with_options == 0
122             || not defined $class->{'options'})
123             {
124 0           ($obj, $len) = Storable::AMF3::deparse_amf( substr($class->{'stream'},$class->{'cursor'}));
125             }
126             else
127             {
128 0           ($obj, $len) = Storable::AMF3::deparse_amf( substr($class->{'stream'},$class->{'cursor'}), $class->{'options'});
129             }
130             } else {
131             # NOTE: Storable::AMF0 seems not needing extra readByte() before deparse
132              
133 0 0 0       if ($storable_with_options == 0
134             || not defined $class->{'options'})
135             {
136 0           ($obj, $len) = Storable::AMF0::deparse_amf( substr($class->{'stream'},$class->{'cursor'}));
137             }
138             else
139             {
140 0           ($obj, $len) = Storable::AMF0::deparse_amf( substr($class->{'stream'},$class->{'cursor'}), $class->{'options'});
141             }
142             };
143              
144 0 0         croak "Can not read AMF".$encoding." data starting from position ".$class->{'cursor'}." of input - reason: ".$@ ."\n"
145             if($@);
146              
147 0 0         if(defined $obj) {
148 0 0         $class->{'cursor'}+=$len
149             unless( $len + $class->{'cursor'} > length($class->{'stream'}) );
150             };
151              
152 0           return $obj;
153             };
154              
155             1;
156             __END__