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 1 7 14.2
total 90 106 84.9


line stmt bran cond sub pod time code
1             package Directory::Scanner::StreamBuilder::Concat;
2             # ABSTRACT: Connect streaming directory iterators
3              
4 8     8   51 use strict;
  8         16  
  8         205  
5 8     8   61 use warnings;
  8         18  
  8         168  
6              
7 8     8   152 use Carp ();
  8         18  
  8         109  
8 8     8   34 use Scalar::Util ();
  8         14  
  8         112  
9              
10 8     8   38 use UNIVERSAL::Object;
  8         12  
  8         141  
11 8     8   33 use Directory::Scanner::API::Stream;
  8         14  
  8         425  
12              
13             our $VERSION = '0.01';
14             our $AUTHORITY = 'cpan:STEVAN';
15              
16 8   50 8   47 use constant DEBUG => $ENV{DIR_SCANNER_STREAM_CONCAT_DEBUG} // 0;
  8         14  
  8         728  
17              
18             ## ...
19              
20 8     8   698 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         42 _is_done => sub { 0 },
27 1         4 _is_closed => sub { 0 },
28             )
29 8     8   2775 }
30              
31             ## ...
32              
33             sub BUILD {
34 1     1 1 30 my $self = $_[0];
35 1         7 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     20 foreach @$streams;
      33        
40             }
41              
42             sub clone {
43             # TODO - this might be possible ...
44 0     0 0 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 0 1043 my $self = $_[0];
51 7 100       13 return if $self->{_index} > $#{$self->{streams}};
  7         25  
52 6         22 return $self->{streams}->[ $self->{_index} ]->head;
53             }
54              
55 2     2 0 1633 sub is_done { $_[0]->{_is_done} }
56 3     3 0 413 sub is_closed { $_[0]->{_is_closed} }
57              
58             sub close {
59 1     1 0 84 my $self = $_[0];
60 1         2 foreach my $stream ( @{ $self->{streams} } ) {
  1         4  
61 2         8 $stream->close;
62             }
63 1         4 $_[0]->{_is_closed} = 1;
64             return
65 1         2 }
66              
67             sub next {
68 6     6 0 2653 my $self = $_[0];
69              
70 6 50       19 return if $self->{_is_done};
71              
72             Carp::confess 'Cannot call `next` on a closed stream'
73 6 50       20 if $self->{_is_closed};
74              
75 6         10 my $next;
76 6         9 while (1) {
77 10         16 undef $next; # clear any previous values, just cause ...
78 10         12 $self->_log('Entering loop ... ') if DEBUG;
79              
80 10 100       16 if ( $self->{_index} > $#{$self->{streams}} ) {
  10         36  
81             # end of the streams now ...
82 1         6 $self->{_is_done} = 1;
83 1         3 last;
84             }
85            
86 9         18 my $current = $self->{streams}->[ $self->{_index} ];
87              
88 9 100       24 if ( $current->is_done ) {
89             # if we are done, advance the
90             # index and restart the loop
91 2         4 $self->{_index}++;
92 2         4 next;
93             }
94             else {
95 7         15 $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         10 last;
110             }
111             }
112              
113 6         16 return $next;
114             }
115              
116             1;
117              
118             __END__