File Coverage

blib/lib/Directory/Scanner/Stream/Concat.pm
Criterion Covered Total %
statement 62 64 96.8
branch 10 12 83.3
condition 3 8 37.5
subroutine 14 15 93.3
pod 1 7 14.2
total 90 106 84.9


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