Hash-Wrap

 view release on metacpan or  search on metacpan

lib/Hash/Wrap.pm  view on Meta::CPAN

    }

    if ( $attr->{-defined} ) {
        $dict{defined} = $attr->{-defined} =~ PerlIdentifier ? $1 : 'defined';
        push @BODY, q[ sub <<DEFINED>> { defined $_[0]->{$_[1] } } ];
        $rentry->{methods}{ $dict{defined} } = undef;
    }

    if ( $attr->{-immutable} ) {
        $dict{set} = <<'END';
  Hash::Wrap::_croak( q[Modification of a read-only value attempted])
    if @_;
END
    }

    if ( $attr->{-recurse} ) {

        # decrement recursion limit.  It's infinite recursion if
        # -recurse < 0; always set to -1 so we keep using the same
        # class.  Note that -recurse will never be zero upon entrance
        # of this block, as -recurse => 0 is removed from the
        # attributes way upstream.

        $dict{recurse_limit} = --$attr->{-recurse} < 0 ? -1 : $attr->{-recurse};

        $dict{quoted_key} = 'q[\<<KEY>>]';
        $dict{hash_value} = '$self->{<<QUOTED_KEY>>}';

        $dict{recurse_wrap_hash} = '$<<CLASS>>::recurse_into_hash->( <<HASH_VALUE>> )';

        $dict{return_value} = <<'END';
 'HASH' eq (Scalar::Util::reftype( <<HASH_VALUE>> ) // q{})
        && ! Scalar::Util::blessed( <<HASH_VALUE>> )
      ? <<WRAP_HASH_ENTRY>>
      : <<HASH_VALUE>>;
END
        if ( $attr->{-copy} ) {

            if ( $attr->{-immutable} ) {
                $dict{wrap_hash_entry} = <<'END';
                 do { Hash::Util::unlock_ref_value( $self, <<QUOTED_KEY>> );
                      <<HASH_VALUE>> = <<RECURSE_WRAP_HASH>>;
                      Hash::Util::lock_ref_value( $self, <<QUOTED_KEY>> );
                      <<HASH_VALUE>>;
                    }
END
            }
            else {
                $dict{wrap_hash_entry} = '<<HASH_VALUE>> = <<RECURSE_WRAP_HASH>>';
            }

        }
        else {
            $dict{wrap_hash_entry} = '<<RECURSE_WRAP_HASH>>';
        }

        # do a two-step initialization of the constructor.  If
        # the initialization sub is stored in $recurse_into_hash, and then
        # $recurse_into_hash is set to the actual constructor I worry that
        # Perl may decide to garbage collect the setup subroutine while it's
        # busy setting $recurse_into_hash.  So, store the
        # initialization sub in something other than $recurse_into_hash.

        $dict{recursion_constructor} = <<'END';
our $recurse_into_hash;
our $setup_recurse_into_hash = sub {
      require Hash::Wrap;
      ( $recurse_into_hash ) = Hash::Wrap->import ( { %$attr, -as => '-return',
                                                      -recurse => <<RECURSE_LIMIT>> } );
      goto &$recurse_into_hash;
};
$recurse_into_hash = $setup_recurse_into_hash;
END

        my %attr = ( %$attr, -recurse => --$attr->{-recurse} < 0 ? -1 : $attr->{-recurse}, );
        delete @attr{qw( -as_scalar_ref -class -base -as )};
        $closures{'$attr'} = \%attr;
    }

    if ( $attr->{-predicate} ) {
        $dict{predicate_template} = <<'END';
our $predicate_template = q[
  package \<<CLASS>>;

  use Scalar::Util ();

  sub has_\<<KEY>> {
    my $self = shift;

    Hash::Wrap::_croak_class_method( $self, 'has_\<<KEY>>' )
        unless Scalar::Util::blessed( $self );

   return exists $self->{\<<KEY>>};
  }

  $Hash::Wrap::REGISTRY{methods}{'has_\<<KEY>>'} = undef;

  \&has_\<<KEY>>;
];
END
    }

    my $class_template = <<'END';
package <<CLASS>>;

<<CLOSURES>>

use Scalar::Util ();

our $validate = sub {
    my ( $self, $key ) = @_;
    return <<VALIDATE_METHOD>>;
};

<<RECURSION_CONSTRUCTOR>>

our $accessor_template = q[
  package \<<CLASS>>;

  use Scalar::Util ();



( run in 1.809 second using v1.01-cache-2.11-cpan-39bf76dae61 )