File Coverage

blib/lib/Tie/FileSection.pm
Criterion Covered Total %
statement 86 92 93.4
branch 42 48 87.5
condition 36 43 83.7
subroutine 8 10 80.0
pod 1 1 100.0
total 173 194 89.1


line stmt bran cond sub pod time code
1 3     3   1372 use strict;
  3         7  
  3         2317  
2             package Tie::FileSection;
3             $Tie::FileSection::VERSION = '0.171860';
4             # ABSTRACT: restrict files sequential access using array like boundaries
5             require Tie::Handle;
6             our @ISA = qw( Tie::StdHandle );
7              
8             sub new{
9 26 50   26 1 2381 my $pkg = $_[0] eq __PACKAGE__ ? shift : __PACKAGE__ ;
10 26         90 my %opts = @_;
11 26 50 66     103 $opts{filename} || $opts{file} or die "filename|file parameter is mandatory!";
12 26   100     79 my $first_line = $opts{first_line} // 0;
13 26   100     69 my $last_line = $opts{last_line} // 0;
14 26         43 my $use_real_line_nr = $opts{use_real_line_nr};
15 26         38 my $FH = $opts{file};
16 26 100 66     92 if(!$FH && defined $opts{filename}){
17 12 50       275 open $FH, '<', $opts{filename} or die "** could not open file $opts{filename} : $!\n";
18             }
19 26         108 tie *F, $pkg, $FH, $first_line, $last_line, $use_real_line_nr;
20 26         74 return \*F;
21             }
22              
23             sub TIEHANDLE{
24 26     26   60 my ($pkg, $FH, $first_line, $last_line, $use_real_line_nr) = @_;
25 26         146 my $self = bless {
26             handle => $FH,
27             first_line => $first_line,
28             last_line => $last_line,
29             init => 0, #lazy read
30             curr_line => 0,
31             use_real_line_nr => $use_real_line_nr,
32             line_buffer => [],
33             tell_buffer => [],
34             }, $pkg;
35 26         134 return $self;
36             }
37              
38             sub UNTIE{
39 0     0   0 my $fh = $_[0]->{handle};
40 0         0 undef $_[0];
41 0         0 close( $fh );
42             }
43              
44             sub EOF{
45 108     108   5014 my $self = shift;
46 108         181 my $f = $self->{first_line};
47 108         159 my $l = $self->{last_line};
48 108 50 100     411 if($f>=0 && $l>0 && $f > $l){ #static EOF
      66        
49 0         0 return 1;
50             }
51 108 50 100     370 if($f<0 && $l<0 && $l < $f ){ #static EOF
      66        
52 0         0 return 1;
53             }
54            
55 108 100 100     308 if($f<0 && $l>0){
56 16         70 return abs($f) + $self->{curr_line} >= $l;
57             }
58            
59 92 100 100     388 if($self->{init} && 0 <= $l && $l >= $self->{curr_line}){
      100        
60 6         26 return 1;
61             }
62            
63 86 100       332 if(eof( $self->{handle} )){
64             #take in account buffer here
65 32 100 100     78 if($l < 0 && scalar(@{$self->{line_buffer}})
  20         63  
66 12         49 return 1;
67             }
68             else{
69             #buffer not empty
70 20 100       28 return if @{$self->{line_buffer}};
  20         59  
71             }
72            
73 12         49 return 1;
74             }
75 54         128 return;
76             }
77              
78             sub TELL {
79 28     28   231 my $self = shift;
80 28 100       73 return tell($self->{handle}) unless $self->{use_buffer};
81 16         38 return $self->{tell_buffer}[0];
82             }
83              
84             sub _readline{
85 60     60   87 my $self = shift;
86 60         93 my $fh = $self->{handle};
87 60         93 my $l = $self->{last_line};
88 60         86 my $tellbuff = $self->{tell_buffer};
89 60         87 my $linebuff = $self->{line_buffer};
90 60 100       140 unless($self->{init}++){
91 26         52 my $f = $self->{first_line};
92 26 100       67 if($f > 0){
    100          
93 10         14 my $i = $f;
94 10   66     57 while(--$i && defined scalar <$fh>){
95             }
96             }
97             elsif($f < 0){
98             #need to read until eof for abs($f) records
99 12         36 for(1..abs $f){
100 28         58 push @$tellbuff, tell($fh);
101 28         90 push @$linebuff, scalar <$fh>;
102             }
103 12         24 $self->{use_buffer}++;
104 12         35 while(!eof $fh){
105 32         42 shift @$tellbuff;
106 32         48 shift @$linebuff;
107 32         58 push @$tellbuff, tell($fh);
108 32         120 push @$linebuff, scalar <$fh>;
109             }
110             }
111 26 100 100     89 if($f > 0 && $l < 0){
112 4         12 for(1..abs $l){
113 8         16 push @$tellbuff, tell($fh);
114 8         19 push @$linebuff, scalar <$fh>;
115             }
116 4         10 $self->{use_buffer}++;
117             }
118 26 100       66 if(eof($fh)){
119             #add the final pos if requested aftere EOF.
120 12         22 push @$tellbuff, tell($fh);
121             }
122 26 100       61 $self->{curr_line} = $. if $self->{use_real_line_nr};
123 26         59 $. = undef;
124             }
125             #read one line and return it, take in accound first_line/last_line and buffer
126 60         104 my $eof = eof($fh);
127 60         96 my $pos = tell($fh);
128 60 100       180 my $line = $eof ? undef : <$fh>;
129 60 100       134 if($self->{use_buffer}){
130 32 100 33     114 unless($eof){
131 8         16 push @$linebuff, $line;
132 8         14 push @$tellbuff, $pos;
133             }
134             elsif($l < 0 && scalar(@$linebuff)
135             return;
136             }
137 32         56 $line = shift @$linebuff;
138 32 50       79 shift @$tellbuff unless @$tellbuff == 1; #always keep last pos
139             }
140 60         104 $self->{curr_line}++;
141 60         99 $. = $self->{curr_line};
142 60         186 return $line;
143             }
144              
145             sub READLINE {
146 96     96   13842 my $self = shift;
147 96 100       183 return if $self->EOF; #test basics boundaries
148 72 100       157 unless(wantarray){
149 60         132 return $self->_readline;
150             }
151             #ARRAY
152 12         17 my @rows;
153 12         30 while(defined($_=$self->READLINE)){
154 28         65 push @rows, $_;
155             }
156 12         43 @rows;
157             }
158              
159 12     12   127 sub CLOSE { close($_[0]->{handle}) }
160 0     0     sub FILENO { fileno($_[0]->{handle}) }
161             1;
162              
163             __END__