File Coverage

blib/lib/Directory/Scanner/StreamBuilder/Concat.pm
Criterion Covered Total %
statement 61 63 96.8
branch 10 12 83.3
condition 3 8 37.5
subroutine 15 16 93.7
pod 7 7 100.0
total 96 106 90.5


line stmt bran cond sub pod time code
1             package Directory::Scanner::StreamBuilder::Concat;
2             # ABSTRACT: Connect streaming directory iterators
3              
4 8     8   49 use strict;
  8         17  
  8         197  
5 8     8   34 use warnings;
  8         17  
  8         159  
6              
7 8     8   138 use Carp ();
  8         18  
  8         94  
8 8     8   41 use Scalar::Util ();
  8         12  
  8         106  
9              
10 8     8   35 use UNIVERSAL::Object;
  8         10  
  8         184  
11 8     8   40 use Directory::Scanner::API::Stream;
  8         17  
  8         389  
12              
13             our $VERSION = '0.02';
14             our $AUTHORITY = 'cpan:STEVAN';
15              
16 8   50 8   40 use constant DEBUG => $ENV{DIR_SCANNER_STREAM_CONCAT_DEBUG} // 0;
  8         11  
  8         604  
17              
18             ## ...
19              
20 8     8   649 our @ISA; BEGIN { @ISA = ('UNIVERSAL::Object', 'Directory::Scanner::API::Stream') }
21             our %HAS; BEGIN {
22             %HAS = (
23 0         0 streams => sub { [] },
24             # internal state ...
25 1         4 _index => sub { 0 },
26 1         3 _is_done => sub { 0 },
27 1         39 _is_closed => sub { 0 },
28             )
29 8     8   2586 }
30              
31             ## ...
32              
33             sub BUILD {
34 1     1 1 32 my $self = $_[0];
35 1         3 my $streams = $self->{streams};
36              
37             (Scalar::Util::blessed($_) && $_->DOES('Directory::Scanner::API::Stream'))
38             || Carp::confess 'You must supply all directory stream objects'
39 1   33     18 foreach @$streams;
      33        
40             }
41              
42             sub clone {
43             # TODO - this might be possible ...
44 0     0 1 0 Carp::confess 'Cloning a concat stream is not a good idea, just dont do it';
45             }
46              
47             ## delegate
48              
49             sub head {
50 7     7 1 947 my $self = $_[0];
51 7 100       11 return if $self->{_index} > $#{$self->{streams}};
  7         21  
52 6         19 return $self->{streams}->[ $self->{_index} ]->head;
53             }
54              
55 2     2 1 1429 sub is_done { $_[0]->{_is_done} }
56 3     3 1 397 sub is_closed { $_[0]->{_is_closed} }
57              
58             sub close {
59 1     1 1 77 my $self = $_[0];
60 1         1 foreach my $stream ( @{ $self->{streams} } ) {
  1         3  
61 2         7 $stream->close;
62             }
63 1         3 $_[0]->{_is_closed} = 1;
64             return
65 1         3 }
66              
67             sub next {
68 6     6 1 2483 my $self = $_[0];
69              
70 6 50       20 return if $self->{_is_done};
71              
72             Carp::confess 'Cannot call `next` on a closed stream'
73 6 50       13 if $self->{_is_closed};
74              
75 6         7 my $next;
76 6         8 while (1) {
77 10         14 undef $next; # clear any previous values, just cause ...
78 10         11 $self->_log('Entering loop ... ') if DEBUG;
79              
80 10 100       12 if ( $self->{_index} > $#{$self->{streams}} ) {
  10         20  
81             # end of the streams now ...
82 1         2 $self->{_is_done} = 1;
83 1         2 last;
84             }
85              
86 9         18 my $current = $self->{streams}->[ $self->{_index} ];
87              
88 9 100       20 if ( $current->is_done ) {
89             # if we are done, advance the
90             # index and restart the loop
91 2         3 $self->{_index}++;
92 2         4 next;
93             }
94             else {
95 7         14 $next = $current->next;
96              
97             # if next returns nothing,
98             # then we now done, so
99             # restart the loop which
100             # will trigger the ->is_done
101             # block above and DWIM
102 7 100       16 next unless defined $next;
103              
104 5         7 $self->_log('Exiting loop ... ') if DEBUG;
105              
106             # if we have gotten to this
107             # point, we have a value and
108             # want to return it
109 5         9 last;
110             }
111             }
112              
113 6         12 return $next;
114             }
115              
116             1;
117              
118             __END__