=pod

=for vim
   vim: tw=72 ts=3 sts=3 sw=3 et ai :

=encoding utf8

=head1 NAME

Data::Tubes::Plugin::Source

=head1 DESCRIPTION

This module contains factory functions to generate I<tubes> that ease
handling data sources.

=head1 FUNCTIONS

=head2 B<< iterate_array >>

   my $tube = iterate_array($array, %args); # OR
   my $tube = iterate_array(%args); # OR
   my $tube = iterate_array(\%args);

iterate over an array, that can be provided to the factory as an
C<array> field or unnamed first parameter C<$array>, or provided as
input record. In case both are provided, the array from the factory (the
I<global> array) is iterated for each call to the tube, before the array
provided to the tube call itself.

The input record for the generated tube MUST be either I<false> or a
reference to an array. The returned tube ALWAYS returns an iterator
(i.e. it returns the string C<iterator>, followed by a sub reference
that acts as an iterator).

The following arguments are supported:

=over

=item C<array>

the I<global> array to iterate over. Defaults to an empty array
reference. It can be passed also as the first unnamed argument;

=item C<name>

name of the tube, useful when debugging;

=back

=head2 B<< open_file >>

   my $tube = open_file($binmode, %args); # OR
   my $tube = open_file(%args); # OR
   my $tube = open_file(\%args);

open a file from the input record.

Depending on what is provided as parameter C<input> in C<%args>, the
input channel will be either the record itself (if C<input> is undefined
or zero-length) or what C<input> points inside the input record, that in
this case MUST be a hash.

The input channel might be either a filehandle or a string; in either
case, C<normalize_filename> from L<Data::Tubes::Util> is used to resolve
a handle or a filename.

The tube returns a data structure that copies the input one (if C<input>
is defined and not empty) and sets an C<output> field (set in the
factory, defaults to C<source>) to a hash reference with the following
fields:

=over

=item C<fh>

a filehandle that can be used to read from the source;

=item C<input>

what was passed as input;

=item C<type>

the type of the particular source, might be C<handle>, C<scalar> (if the
input is a reference to a scalar) or C<file>;

=item C<name>

a name that will provide a hint about what the channel is. If the input
channel is a handle, this will be set to C<handle:%s> (with C<%s>
expanded to a string); if it is a reference to a scalar (which is a
I<valid filename> for C<CORE::open>) it sets it to C<scalar:%s> and if
it is a plain filename it sets it to C<file:%s>.

=back

The arguments accepted by the factory function are the following:

=over

=item C<binmode>

whenever a filehandle is opened, the generated filehandle is set to this
via C<CORE::binmode>. Defaults to C<:encoding(UTF-8)>. This parameter
can also be passed as the first unnamed argument in the call to the
factory function;

=item C<input>

if defined and not empty, the records input to the tube MUST be hash
references with a field named as the provided C<input>; otherwise, the
whole input record is the channel to open;

=item C<name>

name for the tube, useful for debugging;

=item C<output>

name of the output field in the returned record, defaults to C<source>.

=back

=head2 B<< iterate_files >>

   my $tube = iterate_files(@channels_list); # OR
   my $tube = iterate_files(@channels_list, \%args);

generate a tube that iterates over a list of files, either provided to
the factory function directly, or provided as a reference to an array
when invoking the tube. The two following cases are equivalent:

   # pass the file list to the factory
   my $tube1 = iterate_files('foo.txt', 'bar.txt');
   my (undef, $iterator) = $tube1->();

   # leave factory without list, pass to the tube
   my $tube2 = iterate_files();
   my (undef, $iterator)= $tube2->(['foo.txt', 'bar.txt']);

All elements in C<@channels_list> MUST be valid channels for the tube
generated by L</open_file>. Optionally, the last item in the argument
list can be a reference to a hash, with further options for the factory.

The factory is built as a C<sequence> (see
L<Data::Tubes::Plugin::Plumbing>) of L</iterate_array>, L</open_file>
and a C<logger> (see L<Data::Tubes::Plugin::Plumbing> for the latter).

The following arguments can be (optionally) supplied via C<%args>:

=over

=item C<iterate_array>

optional hash with arguments for L</iterate_array>, where the C<array>
field is overridden with C<@channels_list>;

=item C<logger>

optional hash with arguments for C<logger> in
L<Data::Tubes::Plugin::Plubming>. Defaults to setting a C<target>
pointing to a sub reference that gives out message
C<reading from %s>, where C<%s> is expanded with the content of
C<< $record->{source}{name} >>;

=item C<name>

=item C<open_file>

optional hash with arguments for the L</open_file> sub-tube, defaults to
the empty hash which means taking all defaults from L</open_file>.

=back

=head1 BUGS AND LIMITATIONS

Report bugs either through RT or GitHub (patches welcome).

=head1 AUTHOR

Flavio Poletti <polettix@cpan.org>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2016 by Flavio Poletti <polettix@cpan.org>

This module is free software. You can redistribute it and/or modify it
under the terms of the Artistic License 2.0.

This program is distributed in the hope that it will be useful, but
without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.

=cut
