File Coverage

blib/lib/Data/FixedFormat.pm
Criterion Covered Total %
statement 87 115 75.6
branch 11 24 45.8
condition 4 4 100.0
subroutine 15 24 62.5
pod 5 6 83.3
total 122 173 70.5


line stmt bran cond sub pod time code
1             package Data::FixedFormat;
2              
3 1     1   19586 use strict;
  1         2  
  1         509  
4             our $VERSION = "0.04";
5             1;
6              
7             package Data::FixedFormat;
8              
9             sub new {
10 5     5 1 369 my ($class, $layout) = @_;
11 5         7 my $self;
12 5 100       15 if (ref $layout eq "HASH") {
13 1         7 $self = new Data::FixedFormat::Variants $layout;
14             } else {
15 4         17 $self = { Names=>[], Count=>[], Format=>"", Fields=>{} };
16 4         9 bless $self, $class;
17 4 50       16 $self->parse_fields($layout) if $layout;
18             }
19 5         12 return $self;
20             }
21              
22             sub parse_fields {
23 4     4 0 5 my ($self,$fmt) = @_;
24 4         5 my $ofs = 0;
25 4         7 foreach my $fld (@$fmt) {
26 11         28 my ($name, $format, $count) = split ':',$fld;
27 11         12 push @{$self->{Names}}, $name;
  11         24  
28 11         13 push @{$self->{Count}}, $count;
  11         17  
29 11   100     44 $self->{Format} .= $format x ($count || 1);
30 11         18 $self->{Fields}{$name} = $ofs;
31 11   100     44 $ofs += ($count || 1);
32             }
33             }
34              
35             sub unformat {
36 5     5 1 398 my ($self,$frec) = @_;
37 5         26 my @flds = unpack $self->{Format}, $frec;
38 5         9 my $i = 0;
39 5         8 my $rec = {};
40 5 100       18 @{$rec}{@{$self->{Names}}} =
  5         26  
  12         30  
41 5         11 map { defined($_) ? [ splice @flds, 0, $_ ] : shift @flds }
42 5         9 @{$self->{Count}};
43 5         20 return $rec;
44             }
45              
46             sub unformat_tied {
47 1     1 1 2 my ($self,$frec) = @_;
48 1         7 my @flds = unpack $self->{Format}, $frec;
49 1         8 tie my %h, 'Data::FixedFormat::Tied', $self, \@flds;
50 1         5 return \%h;
51             }
52              
53             sub format {
54 3     3 1 1241 my ($self,$rec) = @_;
55 3         5 my @flds;
56 3         4 my $i = 0;
57 3         4 foreach my $name (@{$self->{Names}}) {
  3         9  
58 10 100       17 if ($self->{Count}[$i]) {
59 1         4 push @flds,@{$rec->{$name}};
  1         4  
60             } else {
61 9         17 push @flds,$rec->{$name};
62             }
63 10         16 $i++;
64             }
65 3         16 my $frec = pack $self->{Format}, @flds;
66 3         11 return $frec;
67             }
68              
69             sub blank {
70 0     0 1 0 my $self = shift;
71 0         0 my $rec = $self->unformat(pack($self->{Format},
72             unpack($self->{Format},
73             '')));
74 0         0 return $rec;
75             }
76              
77             package Data::FixedFormat::Tied;
78 1     1   4 use strict;
  1         2  
  1         396  
79              
80             sub TIEHASH {
81 1     1   3 my ($class,$dff,$data) = @_;
82 1         7 bless { Dff=>$dff, Data=>$data },$class;
83             }
84              
85             sub FETCH {
86 4     4   1098 my ($self,$key) = @_;
87 4 50       17 exists($self->{Dff}{Fields}{$key}) or die "Undefined key: $key";
88 4         9 my $idx = $self->{Dff}{Fields}{$key};
89 4 50       12 if ($self->{Dff}{Count}[$idx]) {
90 0         0 die "Array fields not yet supported with tied interface";
91             } else {
92 4         16 $self->{Data}[$idx];
93             }
94             }
95              
96             sub STORE {
97 0     0   0 my ($self,$key,$value) = @_;
98 0 0       0 exists($self->{Dff}{Fields}{$key}) or die "Undefined key: $key";
99 0         0 my $idx = $self->{Dff}{Fields}{$key};
100 0 0       0 if ($self->{Dff}{Count}[$idx]) {
101 0         0 die "Array fields not yet supported with tied interface";
102             } else {
103 0         0 $self->{Data}[$idx] = $value;
104             }
105             }
106              
107             sub DELETE {
108 0     0   0 my ($self,$key) = @_;
109 0         0 die "Not Yet Implemented";
110             }
111              
112             sub CLEAR {
113 0     0   0 my ($self) = @_;
114 0         0 die "Not Yet Implemented";
115             }
116              
117             sub EXISTS {
118 0     0   0 my ($self,$key) = @_;
119 0         0 exists($self->{Dff}{Fields}{$key});
120             }
121              
122             sub FIRSTKEY {
123 1     1   3 my ($self) = @_;
124 1         11 $self->{Dff}{Names}[0];
125             }
126              
127             sub NEXTKEY {
128 4     4   23 my ($self,$lastkey) = @_;
129 4         21 $self->{Dff}{Names}[$self->{Dff}{Fields}{$lastkey}+1];
130             }
131              
132 0     0   0 sub UNTIE {
133             # my ($self) = @_;
134             }
135              
136 0     0   0 sub DESTROY {
137             # my ($self) = @_;
138             }
139              
140             package Data::FixedFormat::Variants;
141 1     1   4 use strict;
  1         11  
  1         323  
142              
143             sub new {
144 1     1   3 my ($class,$recfmt) = @_;
145 1         1 my $self;
146 1         5 $self = { Layouts=>[], Chooser=>$recfmt->{Chooser} };
147 1         4 bless $self, $class;
148 1         2 foreach my $fmt (@{$recfmt->{Formats}}) {
  1         3  
149 3         3 push @{$self->{Layouts}},new Data::FixedFormat $fmt;
  3         16  
150             }
151 1         3 return $self;
152             }
153              
154             sub unformat {
155 2     2   301 my ($self,$frec) = @_;
156 2         7 my $rec = $self->{Layouts}[0]->unformat($frec);
157 2         2 my $w = &{$self->{Chooser}}($rec);
  2         10  
158 2 50       20 $rec = $self->{Layouts}[$w]->unformat($frec) if $w;
159 2         10 return $rec;
160             }
161              
162             sub unformat_tied {
163 0     0   0 my ($self,$frec) = @_;
164 0         0 my $rec = $self->{Layouts}[0]->unformat_tied($frec);
165 0         0 my $w = &{$self->{Chooser}}($rec);
  0         0  
166 0 0       0 $rec = $self->{Layouts}[$w]->unformat_tied($frec) if $w;
167 0         0 return $rec;
168             }
169              
170             sub format {
171 2     2   9387 my ($self,$rec) = @_;
172 2         4 my $w = 0;
173 2 50       8 if ($self->{Chooser}) {
174 2         3 $w = &{$self->{Chooser}}($rec);
  2         6  
175             }
176 2         15 my $frec = $self->{Layouts}[$w]->format($rec);
177 2         7 return $frec;
178             }
179              
180             sub blank {
181 0     0     my ($self,$w) = @_;
182 0 0         $w = 0 unless $w;
183 0           my $rec = $self->{Layouts}[$w]->blank();
184 0           return $rec;
185             }
186              
187             __END__