File Coverage

blib/lib/Net/OBEX/Packet/Headers.pm
Criterion Covered Total %
statement 56 58 96.5
branch 14 22 63.6
condition 3 3 100.0
subroutine 13 13 100.0
pod 5 5 100.0
total 91 101 90.1


line stmt bran cond sub pod time code
1             package Net::OBEX::Packet::Headers;
2              
3 3     3   33444 use strict;
  3         6  
  3         108  
4 3     3   16 use warnings;
  3         4  
  3         120  
5              
6             our $VERSION = '1.001001'; # VERSION
7              
8 3     3   13 use Carp;
  3         7  
  3         226  
9 3     3   1235 use Net::OBEX::Packet::Headers::Unicode;
  3         8  
  3         90  
10 3     3   1352 use Net::OBEX::Packet::Headers::ByteSeq;
  3         6  
  3         76  
11 3     3   1175 use Net::OBEX::Packet::Headers::Byte4;
  3         6  
  3         2547  
12              
13             my %Header_Meaning_Of = _make_header_meanings();
14             my %Header_Type_Of = (
15             ( map { $_ => 'byte4' } qw( count length timeb connection_id ) ),
16              
17             ( map { $_ => 'byteseq' } qw(
18             type time target http
19             who app_params auth_challenge auth_response
20             body end_of_body object_class
21             )
22             ),
23              
24             ( map { $_ => 'unicode' } qw( name description ) ),
25             );
26              
27             sub new {
28 2     2 1 339 my ( $class, $headers_raw ) = @_;
29              
30 2         14 return bless { HEADERS_RAW => $headers_raw }, $class;
31             }
32              
33             sub make {
34 17     17 1 1275 my $self = shift;
35 17         25 my ( $name, $value ) = @_;
36 17         21 $name = lc $name;
37 17 50       39 croak "Invalid header name specified to make()"
38             unless exists $Header_Type_Of{ $name };
39              
40 17         21 my $type = $Header_Type_Of{ $name };
41 17 100       37 if ( $type eq 'byteseq' ) {
    100          
    50          
42 11         39 return Net::OBEX::Packet::Headers::ByteSeq->new(
43             $name => $value,
44             )->make;
45             }
46             elsif ( $type eq 'byte4' ) {
47 4         18 return Net::OBEX::Packet::Headers::Byte4->new(
48             $name => $value,
49             )->make;
50             }
51             elsif ( $type eq 'unicode' ) {
52 2         30 return Net::OBEX::Packet::Headers::Unicode->new(
53             $name => $value,
54             )->make;
55             }
56             else {
57 0         0 die 'I should never got to here. Please email '
58             . 'to zoffix@cpan.org';
59             }
60             }
61              
62             sub parse {
63 2     2 1 10 my $self = shift;
64              
65 2         4 my $headers_raw = shift;
66 2 50       7 $headers_raw = $self->headers_raw
67             unless defined $headers_raw;
68              
69 2         8 $self->headers_raw( $headers_raw );
70              
71 2         3 my %headers;
72 2         23 while (length $headers_raw) {
73 19         50 (my $HI_raw, $headers_raw ) = unpack 'a a*', $headers_raw;
74              
75 19         31 my $HI = $Header_Meaning_Of{ $HI_raw };
76             last
77 19 50       26 unless defined $HI;
78              
79 19         36 ( $headers{ $HI }, $headers_raw)
80             = $self->_make_header_value( $HI_raw, $headers_raw );
81             }
82              
83 2         8 return $self->headers_parsed( \%headers );
84             }
85              
86             sub _make_header_value {
87 19     19   25 my ( $self, $HI_raw, $headers_raw ) = @_;
88              
89             # Bits 8 and 7 of HI - Interpretation
90             # 00 - null terminated Unicode text,
91             # length prefixed with 2 byte unsigned integer
92             # 01 - byte sequence, length prefixed with 2 byte unsigned integer
93             # 10 - 1 byte quantity
94             # 11 - 4 byte quantity - transmitted in network byte order
95              
96 19         30 my $type = unpack 'B2', $HI_raw;
97 19 100 100     77 if ( $type eq '00' or $type eq '01' ) {
    50          
    50          
98 14         31 my ( $header_length, $headers_raw ) = unpack 'n a*', $headers_raw;
99 14         15 $header_length -= 3; # first three bytes of length are
100             # the HI and it's length bytes
101 14         73 return unpack "a$header_length a*", $headers_raw;
102             }
103             elsif ( $type eq '10' ) {
104 0         0 return unpack 'aa*', $headers_raw;
105             }
106             elsif ( $type eq '11' ) {
107 5         24 return unpack 'a4a*', $headers_raw;
108             }
109             }
110              
111             sub headers_raw {
112 2     2 1 4 my $self = shift;
113 2 50       8 if ( @_ ) {
114 2         7 $self->{ HEADERS_RAW } = shift;
115             }
116 2         4 return $self->{ HEADERS_RAW };
117             }
118              
119             sub headers_parsed {
120 2     2 1 4 my $self = shift;
121 2 50       5 if ( @_ ) {
122 2         4 $self->{ HEADERS_PARSED } = shift;
123             }
124 2         7 return $self->{ HEADERS_PARSED };
125             }
126              
127             sub _make_header_meanings {
128             return (
129 3     3   79 "\xC0" => 'count',
130             "\x01" => 'name',
131             "\x42" => 'type',
132             "\xC3" => 'length',
133             "\x44" => 'time',
134             "\xC4" => 'timeb',
135             "\x05" => 'description',
136             "\x46" => 'target',
137             "\x47" => 'http',
138             "\x48" => 'body',
139             "\x49" => 'end_of_body',
140             "\x4A" => 'who',
141             "\xCB" => 'connection_id',
142             "\x4C" => 'app_params',
143             "\x4D" => 'auth_challenge',
144             "\x4E" => 'auth_response',
145             "\x4F" => 'object_class',
146             );
147              
148             }
149              
150             1;
151              
152             __END__