Handle circular refs properly
Yuval Kogman
18 years ago
6 | 6 |
use warnings;
|
7 | 7 |
|
8 | 8 |
use Scalar::Util ();
|
|
9 |
use overload ();
|
9 | 10 |
|
10 | 11 |
our $VERSION = "0.01";
|
11 | 12 |
|
12 | 13 |
sub visit {
|
13 | 14 |
my ( $self, $data ) = @_;
|
|
15 |
|
|
16 |
local $self->{_seen} = ($self->{_seen} || {});
|
|
17 |
return $data if ref $data and $self->{_seen}{ overload::StrVal( $data ) }++;
|
14 | 18 |
|
15 | 19 |
if ( Scalar::Util::blessed( $data ) ) {
|
16 | 20 |
return $self->visit_object( $data );
|
|
0 |
#!/usr/bin/perl
|
|
1 |
|
|
2 |
use strict;
|
|
3 |
use warnings;
|
|
4 |
|
|
5 |
use Test::More tests => 3;
|
|
6 |
|
|
7 |
|
|
8 |
my $m; use ok $m = "Data::Visitor";
|
|
9 |
|
|
10 |
my $structure = {
|
|
11 |
foo => {
|
|
12 |
bar => undef,
|
|
13 |
},
|
|
14 |
};
|
|
15 |
|
|
16 |
$structure->{foo}{bar} = $structure;
|
|
17 |
|
|
18 |
my $o = $m->new;
|
|
19 |
|
|
20 |
{
|
|
21 |
alarm 1;
|
|
22 |
$o->visit( $structure );
|
|
23 |
alarm 0;
|
|
24 |
pass( "circular structures don't cause an endless loop" );
|
|
25 |
}
|
|
26 |
|
|
27 |
is_deeply( $o->visit( $structure ), $structure, "Structure recreated" );
|
|
28 |
|