Data-Locations

 view release on metacpan or  search on metacpan

Locations.pm  view on Meta::CPAN


@EXPORT_OK = ();

%EXPORT_TAGS = (all => [@EXPORT_OK]);

$VERSION = "5.5";

bootstrap Data::Locations $VERSION;

my $Class = __PACKAGE__;    ##  This class's name
my $Table = $Class . '::';  ##  This class's symbol table

my $Count = 0;  ##  Counter for generating unique names for all locations
my $Alive = 1;  ##  Flag for disabling auto-dump during global destruction

  *print  = \&PRINT;        ##  Define public aliases for internal methods
  *printf = \&PRINTF;
  *read   = \&READLINE;

sub _usage_
{
    my($text) = @_;

    Carp::croak("Usage: $text");
}

sub _error_
{
    my($name,$text) = @_;

    Carp::croak("${Table}${name}(): $text");
}

sub _alert_
{
    my($name,$text) = @_;

    Carp::carp("${Table}${name}(): $text") if $^W;
}

sub _check_filename_
{
    my($name,$file) = @_;

    if (defined $file)
    {
        if (ref($file))
        {
            &_error_($name, "reference not allowed as filename");
        }
        else
        {
            if ($file !~ /^\s*$/) { return "$file"; }
        }
    }
    return '';
}

sub new
{
  &_usage_("\$[top|sub]location = [$Class|\$location]->new( [ \$filename ] );")
    if ((@_ < 1) || (@_ > 2));

    my($outer) = shift;
    my($file,$name,$inner);

    $file = '';
    $file = shift if (@_ > 0);
    $file = &_check_filename_('new', $file);

    $name = 'LOCATION' . $Count++;   ##  Generate a unique name
no strict "refs";
    $inner = \*{$Table . $name};     ##  Create a reference of glob value
use strict "refs";
    bless($inner, $Class);           ##  Bless glob to become an object
    tie(*{$inner}, $Class, $inner);  ##  Tie glob to itself
    ${*{$inner}} = $inner;           ##  Use $ slot of glob for self-ref
    @{*{$inner}} = ();               ##  Use @ slot of glob for the data
    %{*{$inner}} = ();               ##  Use % slot of glob for obj attributes

    ${*{$inner}}{'name'} = $name;    ##  Also keep symbolic self-ref
    ${*{$inner}}{'file'} = $file;    ##  Store filename (is auto-dump flag)

    ${*{$inner}}{'outer'} = {};      ##  List of surrounding locations
    ${*{$inner}}{'inner'} = {};      ##  List of embedded locations

    ##  Enable destruction when last user ref goes out of scope:

    ${*{$inner}}{'refs'} = &_mortalize_($inner);

    if (ref($outer))  ##  Object method (or else class method)
    {
        ${${*{$inner}}{'outer'}}{${*{$outer}}{'name'}} = 1;
        ${${*{$outer}}{'inner'}}{${*{$inner}}{'name'}} = 1;
        push(@{*{$outer}}, $inner);
    }
    return $inner;
}

sub TIEHANDLE
{
    return $_[1];
}

sub CLOSE
{
    &_alert_("close", "operation ignored");
}

sub _unlink_outer_
{
    my($inner) = @_;
    my($name,$list,$item);

    $name = ${*{$inner}}{'name'};
    $list = ${*{$inner}}{'outer'};
    foreach $item (keys %{$list})
    {
        if (exists $Data::Locations::{$item})
        {
            delete ${${*{ $Data::Locations::{$item} }}{'inner'}}{$name};



( run in 4.224 seconds using v1.01-cache-2.11-cpan-e93a5daba3e )