File Coverage

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


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.0002';
4 2     2   671 use 5.010;
  2         6  
5              
6 2     2   529 use IO::File;
  2         11954  
  2         185  
7 2     2   13 use IO::Handle;
  2         3  
  2         53  
8              
9 2     2   698 use IO::Uncompress::Gunzip ();
  2         52990  
  2         46  
10 2     2   649 use IO::Uncompress::Bunzip2 ();
  2         5768  
  2         44  
11 2     2   12 use Scalar::Util qw(blessed);
  2         3  
  2         87  
12 2     2   11 use Carp;
  2         3  
  2         73  
13              
14 2     2   10 use Class::Tiny::Antlers;
  2         5  
  2         14  
15              
16              
17             has fh => (
18             is => 'ro',
19             );
20              
21              
22             sub BUILDARGS {
23 534     534 0 689515 my $class = shift;
24 534 100       1613 if ( scalar @_ == 1 ) {
    50          
25 530 50       1475 if ( defined $_[0] ) {
26 530 100       1915 if ( ref $_[0] eq 'HASH' ) {
    100          
27 233         395 return { %{ $_[0] } }
  233         1099  
28             } elsif (ref $_[0] eq '') {
29 295         519 my $name = shift;
30 295 100       6413 die "No such file '$name'" unless -r $name;
31 293         2013 my $fh = IO::File->new($name);
32 293         21056 binmode $fh;
33 293         1329 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         13 return {@_}
44             }
45             }
46              
47              
48             sub BUILD {
49 530     530 0 10085 my ($self, $args) = @_;
50              
51 530 50       1619 die "This is an abstract class and must be subclassed" if ref($self) eq __PACKAGE__;
52              
53             # Required methods
54 530 50       2206 die "'read' method required" unless $self->can('read');
55              
56             # Required attribute types
57 530 100       1598 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 100     6025 (blessed($args->{fh}) && $args->{fh}->isa("IO::Handle")));
      66        
63             }
64              
65             sub _read_and_uncompress {
66 526     526   1013 my $self = shift;
67            
68 526         1126 my ($data, $rc) = '';
69 526         10325 while ($rc = $self->fh->read($data, 8192, length $data)) {}
70 526 50       25313 croak $! unless defined $rc;
71 526 100       2574 if (substr($data, 0, 2) eq "\x1f\x8b") {
    100          
    100          
72             ## gzip-compressed file
73 120         260 my $input = $data;
74 120         591 IO::Uncompress::Gunzip::gunzip \$input, \$data;
75             }
76             elsif (substr($data, 0, 3) eq 'BZh') {
77             ## bzip2-compressed file
78 120         301 my $input = $data;
79 120         565 IO::Uncompress::Bunzip2::bunzip2 \$input, \$data;
80             }
81             elsif (substr($data, 0, 6) eq "\xfd7zXZ\0") {
82 60         9210 croak "xz-compressed R files are not supported";
83             }
84              
85             $data
86 466         321273 }
87              
88              
89             sub close {
90 994     994 1 196773 my $self = shift;
91 994         17220 $self->fh->close
92             }
93              
94              
95             sub DEMOLISH {
96 530     530 0 28667 my $self = shift;
97             ## TODO: should only close if given a filename (OR autoclose, if I
98             ## choose to implement it)
99 530 100       9613 $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__