package Data::Stream::Bulk::Path::Class; BEGIN { $Data::Stream::Bulk::Path::Class::AUTHORITY = 'cpan:NUFFIN'; } { $Data::Stream::Bulk::Path::Class::VERSION = '0.11'; } use Moose; # ABSTRACT: L traversal use Path::Class; use Carp qw(croak); use namespace::clean -except => 'meta'; with qw(Data::Stream::Bulk); has dir => ( isa => "Path::Class::Dir", is => "ro", required => 1, ); has depth_first => ( isa => "Bool", is => "rw", default => 1, ); has only_files => ( isa => "Bool", is => "ro", ); has chunk_size => ( isa => "Int", is => "rw", default => 250, ); has _stack => ( isa => "ArrayRef", is => "ro", default => sub { [] }, ); has _queue => ( isa => "ArrayRef", is => "ro", lazy => 1, default => sub { my $self = shift; return [ $self->dir ], }, ); sub is_done { my $self = shift; return ( @{ $self->_stack } == 0 and @{ $self->_queue } == 0 ); } sub next { my $self = shift; my $queue = $self->_queue; my $stack = $self->_stack; my $depth_first = $self->depth_first; my $only_files = $self->only_files; my $chunk_size = $self->chunk_size; my @ret; { outer: while ( @$stack ) { my $frame = $stack->[-1]; my ( $dh, $parent ) = @$frame; while ( defined(my $entry = $dh->read) ) { next if $entry eq '.' || $entry eq '..'; my $path = $parent->file($entry); if ( -d $path ) { my $dir = $parent->subdir($entry); if ( $depth_first ) { unshift @$queue, $dir; } else { push @$queue, $dir; } last outer; } else { push @ret, $path; return \@ret if @ret >= $chunk_size; } } # we're done reading this dir pop @$stack; } if ( @$queue ) { my $dir = shift @$queue; my $dh = $dir->open || croak("Can't open directory $dir: $!"); if ( $depth_first ) { push @$stack, [ $dh, $dir ]; } else { unshift @$stack, [ $dh, $dir ]; } unless ( $only_files ) { push @ret, $dir; return \@ret if @ret >= $chunk_size; } redo; } } return unless @ret; return \@ret; } __PACKAGE__->meta->make_immutable; __PACKAGE__; =pod =head1 NAME Data::Stream::Bulk::Path::Class - L traversal =head1 VERSION version 0.11 =head1 SYNOPSIS use Data::Stream::Bulk::Path::Class; my $dir = Data::Stream::Bulk::Path::Class->new( dir => Path::Class::Dir->new( ... ), ); =head1 DESCRIPTION This stream produces depth or breadth first traversal order recursion through L objects. Items are read iteratively, and a stack of open directory handles is used to keep track of state. =head1 ATTRIBUTES =over 4 =item chunk_size Defaults to 250. =item depth_first Chooses between depth first and breadth first traversal order. =item only_files If true only L items will be returned in the output streams (no directories). =back =head1 METHODS =over 4 =item is_done Returns true when no more files are left to iterate. =item next Returns the next chunk of L objects =back =head1 AUTHOR Yuval Kogman =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Yuval Kogman. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__