File Coverage

blib/lib/MVS/VBFile.pm
Criterion Covered Total %
statement 75 82 91.4
branch 36 48 75.0
condition 5 8 62.5
subroutine 10 10 100.0
pod 5 6 83.3
total 131 154 85.0


line stmt bran cond sub pod time code
1             package MVS::VBFile;
2              
3 1     1   686 use strict;
  1         2  
  1         40  
4 1     1   5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  1         2  
  1         81  
5 1     1   6 use Carp;
  1         4  
  1         1093  
6              
7             require Exporter;
8              
9             @ISA = qw(Exporter);
10             @EXPORT = qw(vbget);
11             @EXPORT_OK = qw(vbget vbopen vbput vbclose vb_blocks_written);
12             $VERSION = '0.05';
13              
14             %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
15              
16             my $blib = 0; # Bytes left in block
17             $MVS::VBFile::bdws = 0;
18             $MVS::VBFile::keep_rdw = 0;
19              
20             %MVS::VBFile::outblock = ();
21             %MVS::VBFile::blksizes = ();
22             %MVS::VBFile::blocks_written = ();
23              
24             #--- vbget gets a single record; if called in array context (the user
25             #--- wants all records in a single array), it calls vbget_array.
26             #
27             sub vbget {
28 32     32 1 578 my $FH = shift; # Filehandle
29 32 100       58 if (wantarray) {
30 3         9 return vbget_array($FH);
31             }
32              
33 29         24 my ($bdw, $rdw, $reclen, $v_record, $n);
34 29 100 66     70 if ($blib == 0 && $MVS::VBFile::bdws) {
35             #--- Beginning of a block: read the Block Descriptor Word
36             #--- if we've been told to.
37 2         16 $n = read($FH, $bdw, 4);
38 2 100       9 if ($n < 4) { # End of file
39 1         4 return undef();
40             }
41 1         4 $blib = unpack("n2", substr($bdw, 0,2)) - 4;
42             }
43             #--- Now read the Record Descriptor Word
44 28         111 $n = read($FH, $rdw, 4);
45 28 100       62 if ($n < 4) {
46 2 50       8 return undef() if ! $MVS::VBFile::bdws; # End of file
47 0         0 Carp::carp "vbget: Unexpected end of file";
48 0         0 return undef();
49             }
50 26         49 $reclen = unpack("n2", substr($rdw, 0,2)) - 4;
51            
52 26         60 $n = read($FH, $v_record, $reclen);
53 26 50       50 if ($n != $reclen) {
54 0         0 Carp::carp "vbget: Unexpected end of file";
55             }
56 26 100       50 $blib = $blib - ($reclen + 4) if $MVS::VBFile::bdws;
57 26 100       50 $v_record = $rdw.$v_record if $MVS::VBFile::keep_rdw;
58              
59 26         66 return $v_record;
60             }
61              
62             #--- Get all records in a single array.
63             #
64             sub vbget_array {
65 3     3 0 6 my $FH = shift; # Filehandle
66 3         4 my ($bdw, $rdw, $reclen, $v_record, $n);
67 3         4 my @out = ();
68              
69 3         6 while (1) {
70 29 100 66     71 if ($blib == 0 && $MVS::VBFile::bdws) {
71             #--- Beginning of a block: read the Block Descriptor Word
72             #--- if we've been told to.
73 2         15 $n = read($FH, $bdw, 4);
74 2 100       9 if ($n < 4) { # End of file
75 1         14 return @out;
76             }
77 1         4 $blib = unpack("n2", substr($bdw, 0,2)) - 4;
78             }
79             #--- Now read the Record Descriptor Word
80 28         77 $n = read($FH, $rdw, 4);
81 28 100       56 if ($n < 4) {
82 2 50       32 return @out if ! $MVS::VBFile::bdws; # End of file
83 0         0 Carp::carp "vbget: Unexpected end of file";
84 0         0 return @out;
85             }
86 26         43 $reclen = unpack("n2", substr($rdw, 0,2)) - 4;
87            
88 26         63 $n = read($FH, $v_record, $reclen);
89 26 50       51 if ($n != $reclen) {
90 0         0 Carp::carp "vbget: Unexpected end of file";
91 0         0 return @out;
92             }
93 26 100       46 $blib = $blib - ($reclen + 4) if $MVS::VBFile::bdws;
94 26 100       46 $v_record = $rdw.$v_record if $MVS::VBFile::keep_rdw;
95              
96 26         41 push @out, $v_record;
97             }
98             }
99              
100             #---------------------------------------
101             # OUTPUT: vbopen, vbput, vbclose
102             #---------------------------------------
103              
104             #--- vbopen: pretty much the same as open() except that it also sets
105             #--- the blksize for the file.
106             #
107             sub vbopen {
108 1     1 1 50 my ($FH, $expr, $blksize) = @_;
109 1   50     5 $blksize ||= 32760;
110 1 50       4 $blksize = 32760 if $blksize < 9;
111 1 50       4 $blksize = 32760 if $blksize > 262_144;
112              
113 1         6 $MVS::VBFile::blksizes{ $FH } = $blksize;
114 1         3 $MVS::VBFile::outblock{$FH} = pack('x4'); # Start with a dummy BDW
115 1         3 $MVS::VBFile::blocks_written{$FH} = 0;
116 1         111 return open($FH, $expr);
117             }
118              
119             #--- vbput puts a single logical record. When a block is filled up,
120             #--- write the block and start a new one.
121             #
122             sub vbput {
123 400     400 1 1639 my ($FH, $record) = @_;
124 400 50       773 Carp::croak "vbput: No filehandle specified" unless $FH;
125 400 50       583 Carp::croak "vbput: No record specified" unless $record;
126 400         828 my $blksize = $MVS::VBFile::blksizes{ $FH };
127              
128 400         642 my $L = length($record) + 4;
129 400 100       1102 if ($L + length($MVS::VBFile::outblock{$FH}) > $blksize) {
130 5         14 _put_block($FH);
131 5         16 $MVS::VBFile::outblock{$FH} = pack('x4'); # Start with a dummy BDW
132             }
133 400         749 my $rdw = pack("n x2",$L);
134 400         1481 $MVS::VBFile::outblock{$FH} .= $rdw.$record;
135             }
136              
137             sub _put_block {
138 6     6   8 my $FH = shift;
139 6         20 my $outrec = $MVS::VBFile::outblock{$FH};
140              
141 6         26 substr($outrec,0,4) = pack("n x2",length($outrec));
142              
143 6 50       117 print $FH $outrec or Carp::croak "Error in vbput: $!";
144 6         23 $MVS::VBFile::blocks_written{$FH}++;
145             }
146              
147             #--- vbclose: close the output file, but first write out the last
148             #--- block if necessary.
149             #
150             sub vbclose {
151 1     1 1 9 my $FH = shift;
152 1 50       6 Carp::croak "vbput: No filehandle specified" unless $FH;
153              
154 1 50       9 _put_block($FH) if length($MVS::VBFile::outblock{$FH}) > 4;
155              
156 1         53 return close($FH);
157             }
158              
159             sub vb_blocks_written {
160 1     1 1 6 my $FH = shift;
161 1 50       8 Carp::croak "vb_blocks_written: No filehandle specified" unless $FH;
162 1         7 return $MVS::VBFile::blocks_written{ $FH };
163             }
164              
165             1;
166              
167             __END__