File Coverage

blib/lib/Statistics/R/IO/Base.pm
Criterion Covered Total %
statement 56 57 98.2
branch 25 30 83.3
condition 4 6 66.6
subroutine 13 13 100.0
pod 1 4 25.0
total 99 110 90.0


line stmt bran cond sub pod time code
1             package Statistics::R::IO::Base;
2             # ABSTRACT: Common object methods for processing R files
3             $Statistics::R::IO::Base::VERSION = '1.0001';
4 2     2   957 use 5.010;
  2         5  
5              
6 2     2   900 use IO::File;
  2         13894  
  2         205  
7 2     2   11 use IO::Handle;
  2         2  
  2         56  
8              
9 2     2   1095 use IO::Uncompress::Gunzip ();
  2         59574  
  2         50  
10 2     2   1327 use IO::Uncompress::Bunzip2 ();
  2         8285  
  2         68  
11 2     2   13 use Scalar::Util qw(blessed);
  2         3  
  2         101  
12 2     2   10 use Carp;
  2         3  
  2         103  
13              
14 2     2   11 use Class::Tiny::Antlers;
  2         2  
  2         17  
15              
16              
17             has fh => (
18             is => 'ro',
19             );
20              
21              
22             sub BUILDARGS {
23 534     534 0 338968 my $class = shift;
24 534 100       1278 if ( scalar @_ == 1 ) {
    50          
25 530 50       1235 if ( defined $_[0] ) {
26 530 100       1462 if ( ref $_[0] eq 'HASH' ) {
    100          
27 233         272 return { %{ $_[0] } }
  233         955  
28             } elsif (ref $_[0] eq '') {
29 295         285 my $name = shift;
30 295 100       5336 die "No such file '$name'" unless -r $name;
31 293         1723 my $fh = IO::File->new($name);
32 293         17024 binmode $fh;
33 293         1009 return { fh => $fh }
34             }
35             }
36 2         16 die "Single parameters to new() must be a HASH ref or filename scalar"
37             }
38             elsif ( @_ % 2 ) {
39 0         0 die "The new() method for $class expects a hash reference or a key/value list."
40             . " You passed an odd number of arguments\n";
41             }
42             else {
43 4         14 return {@_}
44             }
45             }
46              
47              
48             sub BUILD {
49 530     530 0 7465 my ($self, $args) = @_;
50              
51 530 50       1208 die "This is an abstract class and must be subclassed" if ref($self) eq __PACKAGE__;
52              
53             # Required methods
54 530 50       1933 die "'read' method required" unless $self->can('read');
55              
56             # Required attribute types
57 530 100       1133 die "Attribute 'fh' is required" unless defined($args->{fh});
58            
59             die "Attribute 'fh' must be an instance of IO::Handle or an open filehandle" if
60             defined($args->{fh}) &&
61             !((ref($args->{fh}) eq "GLOB" && Scalar::Util::openhandle($args->{fh})) ||
62 528 100 66     6297 (blessed($args->{fh}) && $args->{fh}->isa("IO::Handle")));
      66        
63             }
64              
65             sub _read_and_uncompress {
66 526     526   498 my $self = shift;
67            
68 526         721 my ($data, $rc) = '';
69 526         10032 while ($rc = $self->fh->read($data, 8192, length $data)) {}
70 526 50       20992 croak $! unless defined $rc;
71 526 100       1949 if (substr($data, 0, 2) eq "\x1f\x8b") {
    100          
    100          
72             ## gzip-compressed file
73 120         210 my $input = $data;
74 120         442 IO::Uncompress::Gunzip::gunzip \$input, \$data;
75             }
76             elsif (substr($data, 0, 3) eq 'BZh') {
77             ## bzip2-compressed file
78 120         183 my $input = $data;
79 120         442 IO::Uncompress::Bunzip2::bunzip2 \$input, \$data;
80             }
81             elsif (substr($data, 0, 6) eq "\xfd7zXZ\0") {
82 60         9305 croak "xz-compressed R files are not supported";
83             }
84              
85             $data
86 466         220392 }
87              
88              
89             sub close {
90 994     994 1 173560 my $self = shift;
91 994         17963 $self->fh->close
92             }
93              
94              
95             sub DEMOLISH {
96 530     530 0 22218 my $self = shift;
97             ## TODO: should only close if given a filename (OR autoclose, if I
98             ## choose to implement it)
99 530 100       10603 $self->close if $self->fh
100             }
101              
102              
103             # sub eof {
104             # my $self = shift;
105             # $self->position >= scalar @{$self->data};
106             # }
107              
108            
109             1;
110              
111             __END__