1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
package Data::TableReader::Iterator;
use strict;
use warnings;
use Try::Tiny;
use Carp;
use Scalar::Util 'refaddr';
# ABSTRACT: Base class for iterators (blessed coderefs)
our $VERSION = '0.021'; # VERSION
our %_iterator_fields;
sub new {
my ($class, $sub, $fields)= @_;
ref $sub eq 'CODE' and ref $fields eq 'HASH'
or croak "Expected new(CODEREF, HASHREF)";
$_iterator_fields{refaddr $sub}= $fields;
return bless $sub, $class;
}
sub _fields {
$_iterator_fields{refaddr shift};
}
sub DESTROY {
delete $_iterator_fields{refaddr shift};
}
sub progress {
undef;
}
sub row {
croak "Unimplemented";
}
sub dataset_idx {
0
}
sub tell {
undef;
}
sub seek {
croak "Unimplemented";
}
sub next_dataset {
undef;
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Data::TableReader::Iterator - Base class for iterators (blessed coderefs)
=head1 VERSION
version 0.021
=head1 SYNOPSIS
my $iter= $record_reader->iterator;
while (my $rec= $iter->()) {
...
my $position= $iter->tell;
print "Marking position $position"; # position stringifies to human-readable
...
$iter->seek($position);
}
if ($iter->next_dataset) {
# iterate some more
while ($rec= $iter->()) {
...
printf "Have processed %3d %% of the file", $iter->progress*100;
}
}
=head1 DESCRIPTION
This is the abstract base class for iterators used in Data::TableReader,
which are blessed coderefs that return records on each call.
The coderef should support a single argument of a "slice" to extract from the record, in case
not all of the record is needed.
=head1 ATTRIBUTES
=head2 position
Return a human-readable string describing the current location within the source file.
This will be something like C<"$filename row $row"> or C<"$filename $worksheet:$cell_id">.
=head2 row
A numeric 1-based row number for the current position of the current dataset. This is not
affected by which row the header was found on.
=head2 dataset_idx
A numeric 0-based dataset number. For Decoders which only support a single dataset, this is
always C<0>.
=head2 progress
An estimate of how much of the data has already been returned. If the stream
is not seekable this may return undef.
=head1 METHODS
=head2 new
$iter= Data::TableReader::Iterator->new( \&coderef, \%fields );
The iterator is a blessed coderef. The first argument is the coderef to be blessed,
and the second argument is the magic hashref of fields to be made available as
C<< $iter->_fields >>.
=head2 tell
If seeking is supported, this will return some value that can be passed to
seek to come back to this point in the stream. This value will always be
true. If seeking is not supported this will return undef.
=head2 seek
$iter->seek($pos);
Seek to a point previously reported by L</tell>. If seeking is not supported
this will die. If C<$pos> is any false value it means to seek to the start of
the stream.
=head2 next_dataset
If a file format supports more than one tabular group of data, this method allows you to jump
to the next. Returns true if it moved to a new dataset, and false at the end of iteration.
=head1 AUTHOR
Michael Conrad <mike@nrdvana.net>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2024 by Michael Conrad.
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
|