3 package Hash::Util::FieldHash::Compat;
8 use Tie::RefHash::Weak;
10 use vars qw(@ISA %EXPORT_TAGS @EXPORT_OK);
26 @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
31 tie %$hash, 'Hash::Util::FieldHash::Compat::Tie::FieldHash', %$hash;
36 sub fieldhashes { map { &fieldhash($_) } @_ }
39 tie %{$_[0]}, 'Hash::Util::FieldHash::Compat::Tie::IdHash', %{$_[0]};
43 sub idhashes { map { &idhash($_) } @_ }
48 if ( defined ( my $refaddr = Tie::RefHash::refaddr($obj) ) ) {
55 tie my %registry, 'Tie::RefHash::Weak';
60 my $registry_by_id = tied(%registry)->[0];
62 if ( my $record = $registry_by_id->{$id} ) {
63 return $record->[0]; # first slot is the key
70 my ( $obj, @args ) = @_;
71 ( $registry{$obj} ||= Hash::Util::FieldHash::Compat::Destroyer->new($obj) )->register(@args);
75 package Hash::Util::FieldHash::Compat::Tie::IdHash;
78 @ISA = qw(Tie::StdHash);
80 # this class always stringifies using id().
83 my ( $class, @args ) = @_;
84 my $self = bless {}, $class;
87 my ( $key, $value ) = splice @args, 0, 2;
88 $self->STORE($key, $value);
95 foreach my $method ( qw(STORE FETCH DELETE EXISTS) ) {
96 eval 'sub '.$method.' {
97 my ( $self, $key, @args ) = @_;
98 $self->SUPER::'.$method.'( Hash::Util::FieldHash::Compat::id($key), @args );
103 package Hash::Util::FieldHash::Compat::Tie::FieldHash;
105 @ISA = qw(Tie::RefHash::Weak);
107 # this subclass retains weakrefs to the objects in the keys, but pretends
108 # the keys are actually strings
111 # always return strings from keys
113 foreach my $method ( qw(FIRSTKEY NEXTKEY) ) {
114 eval 'sub '.$method.' {
115 my ( $self, @args ) = @_;
116 Hash::Util::FieldHash::Compat::id($self->SUPER::'.$method.'(@args));
121 my ( $self, $key ) = @_;
122 my $str_key = Hash::Util::FieldHash::Compat::id($key);
123 exists $_->{$str_key} and return 1 for @{ $self }[0, 1];
128 my($self, $key) = @_;
130 my $str_key = Hash::Util::FieldHash::Compat::id($key);
132 if ( exists $self->[0]{$str_key} ) {
133 return $self->[0]{$str_key}[1];
135 $self->[1]{$str_key};
140 my ( $self, $key, $value ) = @_;
142 my $str_key = Hash::Util::FieldHash::Compat::id($key);
144 delete $self->[1]{$str_key};
146 $self->SUPER::STORE( $key, $value );
150 my ( $self, $key ) = @_;
152 foreach my $key ( $key, Hash::Util::FieldHash::Compat::id($key) ) {
153 if ( defined ( my $ret = $self->SUPER::DELETE($key) ) ) {
160 package Hash::Util::FieldHash::Compat::Destroyer;
161 use Scalar::Util qw(weaken);
164 my ( $class, $obj ) = @_;
166 tie my %hashes, 'Tie::RefHash::Weak';
173 weaken($self->{object});
179 my ( $self, @hashes ) = @_;
180 $self->{hashes}{$_}++ for @hashes;
185 my $object = $self->{object};
186 delete $_->{Hash::Util::FieldHash::Compat::id($object)} for keys %{ $self->{hashes} };
198 Hash::Util::FieldHash::Compat::Heavy - Emulate Hash::Util::FieldHash using
203 # this module will be used automatically by L<Hash::Util::FieldHash::Compat> if necessary
207 See L<Hash::Util::FieldHash::Compat> for the documentation