Class-Tie-InsideOut

 view release on metacpan or  search on metacpan

lib/Tie/InsideOut.pm  view on Meta::CPAN

package Tie::InsideOut;

use 5.006001;
use strict;
use warnings;

use Carp qw( croak );
use Scalar::Util qw( refaddr );

our $VERSION = '0.11';

our @ISA = qw( );

my %NameSpaces;               # default namespace for each hash
my %Keys;                     # tracks defined keys and namespaces

=begin internal

The %Keys hash is structured as follows:

  $Keys{$id}->{$key}->{$namespace}        = $hash_ref

C<$id> refers to the unique object identifier (returned by the L</_get_id> method).

C<$key> refers to the name of the hash key, qhich corresponds to the name of a hash
variable in the C<$namespace>.

C<$namespace> refers to the namespace that the value is in. Encapsulation means
that child classes can use the same key names without conflict.

C<$hash_ref> is a reference to the hash variable that contains the value. Which is
accessible:

  $Keys{$id}->{$key}->{$namespace}->{$id} = $value

We maintain a structure that incidcates where all of the keys are so that we can
clean up the data when the object is destroyed.  It also allows us to serialize
and deserialize data.

=end internal

=cut

sub TIEHASH {
  my $class  = shift || __PACKAGE__;

  my $scalar;
  my $self  = \$scalar;
  bless $self, $class;

  my $id    = $self->_get_id;
  {
    my $caller = shift || (caller)[0];
    no strict 'refs';
    $NameSpaces{$id} = $caller;
  }
  $self->CLEAR;

  return $self;
}

BEGIN {
  *new = \&TIEHASH;
}

sub DESTROY {
  my $self = shift;
  my $id   = $self->_get_id;

  $self->CLEAR;

  delete $Keys{$id};
  delete $NameSpaces{$id};
}

sub CLEAR {
  my $self = shift;
  my $id   = $self->_get_id;

  foreach my $key (keys %{$Keys{$id}}) {
    foreach my $namespace (keys %{$Keys{$id}->{$key}}) {
      delete $Keys{$id}->{$key}->{$namespace}->{$id};
      delete $Keys{$id}->{$key}->{$namespace};
    }
    delete $Keys{$id}->{$key};
  }
  $Keys{$id} = { };
}

sub SCALAR {
  my $self = shift;
  my $id   = $self->_get_id;
  return scalar (%{$Keys{$id}});
}

sub FETCH {
  my $self = shift;
  my $key  = shift;

  my ($id, $hash_ref) = $self->_validate_key($key);
  $hash_ref->{$id};
}

sub EXISTS {
  my $self = shift;
  my $key  = shift;

  my ($id, $hash_ref) = $self->_validate_key($key);
  exists $hash_ref->{$id};
}

# Being able to iterate over the keys is useful, but limited. After version
# 0.04, encapsulation is enforced.



( run in 2.273 seconds using v1.01-cache-2.11-cpan-5c0b1e786e0 )