Data-Handle
view release on metacpan or search on metacpan
lib/Data/Handle.pm view on Meta::CPAN
my %datastash;
use Symbol qw( gensym );
use Scalar::Util qw( weaken );
use parent qw( IO::File );
use Package::Stash 0.15; # has_symbol
use Carp ();
use Data::Handle::Exception;
use Data::Handle::IO;
use Try::Tiny qw( try catch );
sub new {
my ( $class, $targetpackage ) = @_;
_e('NoSymbol')->throw("$targetpackage has no DATA symbol")
if ( !$class->_has_data_symbol($targetpackage) );
if ( !$class->_is_valid_data_tell($targetpackage) ) {
_e('BadFilePos')
->throw( "$targetpackage has a DATA symbol, but the filepointer"
. " is well beyond the __DATA__ section.\n"
. " We can't work out safely where it is.\n"
. $class->_stringify_metadata($targetpackage)
. "\n" );
}
my $sym = gensym();
my $xsym = $sym;
weaken($xsym);
## no critic( ProhibitTies )
tie *{$sym}, 'Data::Handle::IO', { self => $xsym };
${ *{$sym} }{stash} = {};
bless $sym, $class;
$sym->_stash->{start_offset} = $class->_get_start_offset($targetpackage);
$sym->_stash->{targetpackage} = $targetpackage;
$sym->_stash->{current_offset} = $class->_get_start_offset($targetpackage);
$sym->_stash->{filehandle} = $class->_get_data_symbol($targetpackage);
return $sym;
}
sub _has_data_symbol {
my ( undef, $package ) = @_;
my $rval = undef;
try {
my $stash = Package::Stash->new($package);
return unless $stash->has_symbol('DATA');
my $fh = $stash->get_symbol('DATA');
$rval = defined fileno *{$fh};
}
catch {
if (/is not a module name/) {
$rval = undef;
return;
}
## no critic (RequireCarping)
die $_;
};
return $rval;
}
sub _get_data_symbol {
my ( $self, $package ) = @_;
if ( !$self->_has_data_symbol($package) ) {
_e('Internal::BadGet')->throw('_get_data_symbol was called when there is no data_symbol to get');
}
return Package::Stash->new($package)->get_symbol('DATA');
}
sub _get_start_offset {
my ( $self, $package ) = @_;
return $datastash{$package}->{offset}
if ( exists $datastash{$package}->{offset} );
if ( !$self->_has_data_symbol($package) ) {
_e('Internal::BadGet')->throw('_get_start_offset was called when there is no data_symbol to get');
}
my $fd = $self->_get_data_symbol($package);
my $position = tell $fd;
$datastash{$package}->{offset} = $position;
return $position;
}
sub _is_valid_data_tell {
my ( $self, $package ) = @_;
( run in 1.395 second using v1.01-cache-2.11-cpan-39bf76dae61 )