File Coverage

blib/lib/Clone/PP.pm
Criterion Covered Total %
statement 54 55 98.1
branch 31 34 91.1
condition 5 6 83.3
subroutine 9 9 100.0
pod 0 1 0.0
total 99 105 94.2


line stmt bran cond sub pod time code
1             package Clone::PP;
2              
3 7     7   7922 use 5.006;
  7         27  
  7         283  
4 7     7   38 use strict;
  7         14  
  7         264  
5 7     7   39 use warnings;
  7         27  
  7         1612  
6 7     7   40 use vars qw($VERSION @EXPORT_OK);
  7         12  
  7         513  
7 7     7   36 use Exporter;
  7         11  
  7         744  
8              
9             $VERSION = 1.06;
10              
11             @EXPORT_OK = qw( clone );
12 7     7   8769 sub import { goto &Exporter::import } # lazy Exporter
13              
14             # These methods can be temporarily overridden to work with a given class.
15 7     7   36 use vars qw( $CloneSelfMethod $CloneInitMethod );
  7         12  
  7         445  
16             $CloneSelfMethod ||= 'clone_self';
17             $CloneInitMethod ||= 'clone_init';
18              
19             # Used to detect looped networks and avoid infinite recursion.
20 7     7   39 use vars qw( %CloneCache );
  7         16  
  7         3580  
21              
22             # Generic cloning function
23             sub clone {
24 55     55 0 23186 my $source = shift;
25              
26 55 100       162 return undef if not defined($source);
27            
28             # Optional depth limit: after a given number of levels, do shallow copy.
29 52         73 my $depth = shift;
30 52 100 100     177 return $source if ( defined $depth and $depth -- < 1 );
31            
32             # Maintain a shared cache during recursive calls, then clear it at the end.
33 47 100       165 local %CloneCache = ( undef => undef ) unless ( exists $CloneCache{undef} );
34            
35 47 100       187 return $CloneCache{ $source } if ( defined $CloneCache{ $source } );
36            
37             # Non-reference values are copied shallowly
38 39 100       119 my $ref_type = ref $source or return $source;
39            
40             # Extract both the structure type and the class name of referent
41 36         45 my $class_name;
42 36 100       836 if ( "$source" =~ /^\Q$ref_type\E\=([A-Z]+)\(0x[0-9a-f]+\)$/ ) {
43 9         22 $class_name = $ref_type;
44 9         30 $ref_type = $1;
45             # Some objects would prefer to clone themselves; check for clone_self().
46 9 50       113 return $CloneCache{ $source } = $source->$CloneSelfMethod()
47             if $source->can($CloneSelfMethod);
48             }
49            
50             # To make a copy:
51             # - Prepare a reference to the same type of structure;
52             # - Store it in the cache, to avoid looping if it refers to itself;
53             # - Tie in to the same class as the original, if it was tied;
54             # - Assign a value to the reference by cloning each item in the original;
55            
56 36         70 my $copy;
57 36 100 66     162 if ($ref_type eq 'HASH') {
    100          
    50          
58 17         57 $CloneCache{ $source } = $copy = {};
59 17 100       53 if ( my $tied = tied( %$source ) ) { tie %$copy, ref $tied }
  1         6  
60 17 100       62 %$copy = map { ! ref($_) ? $_ : clone($_, $depth) } %$source;
  54         225  
61             } elsif ($ref_type eq 'ARRAY') {
62 9         30 $CloneCache{ $source } = $copy = [];
63 9 100       31 if ( my $tied = tied( @$source ) ) { tie @$copy, ref $tied }
  1         5  
64 9 100       34 @$copy = map { ! ref($_) ? $_ : clone($_, $depth) } @$source;
  23         82  
65             } elsif ($ref_type eq 'REF' or $ref_type eq 'SCALAR') {
66 10         34 $CloneCache{ $source } = $copy = \( my $var = "" );
67 10 100       50 if ( my $tied = tied( $$source ) ) { tie $$copy, ref $tied }
  1         4  
68 10         53 $$copy = clone($$source, $depth);
69             } else {
70             # Shallow copy anything else; this handles a reference to code, glob, regex
71 0         0 $CloneCache{ $source } = $copy = $source;
72             }
73            
74             # - Bless it into the same class as the original, if it was blessed;
75             # - If it has a post-cloning initialization method, call it.
76 36 100       128 if ( $class_name ) {
77 9         21 bless $copy, $class_name;
78 9 50       98 $copy->$CloneInitMethod() if $copy->can($CloneInitMethod);
79             }
80            
81 36         154 return $copy;
82             }
83              
84             1;
85              
86             __END__
87              
88             =head1 NAME
89              
90             Clone::PP - Recursively copy Perl datatypes
91              
92             =head1 SYNOPSIS
93              
94             use Clone::PP qw(clone);
95            
96             $item = { 'foo' => 'bar', 'move' => [ 'zig', 'zag' ] };
97             $copy = clone( $item );
98              
99             $item = [ 'alpha', 'beta', { 'gamma' => 'vlissides' } ];
100             $copy = clone( $item );
101              
102             $item = Foo->new();
103             $copy = clone( $item );
104              
105             Or as an object method:
106              
107             require Clone::PP;
108             push @Foo::ISA, 'Clone::PP';
109            
110             $item = Foo->new();
111             $copy = $item->clone();
112              
113             =head1 DESCRIPTION
114              
115             This module provides a general-purpose clone function to make deep
116             copies of Perl data structures. It calls itself recursively to copy
117             nested hash, array, scalar and reference types, including tied
118             variables and objects.
119              
120             The clone() function takes a scalar argument to copy. To duplicate
121             arrays or hashes, pass them in by reference:
122              
123             my $copy = clone(\@array); my @copy = @{ clone(\@array) };
124             my $copy = clone(\%hash); my %copy = %{ clone(\%hash) };
125              
126             The clone() function also accepts an optional second parameter that
127             can be used to limit the depth of the copy. If you pass a limit of
128             0, clone will return the same value you supplied; for a limit of
129             1, a shallow copy is constructed; for a limit of 2, two layers of
130             copying are done, and so on.
131              
132             my $shallow_copy = clone( $item, 1 );
133              
134             To allow objects to intervene in the way they are copied, the
135             clone() function checks for a couple of optional methods. If an
136             object provides a method named C<clone_self>, it is called and the
137             result returned without further processing. Alternately, if an
138             object provides a method named C<clone_init>, it is called on the
139             copied object before it is returned.
140              
141             =head1 BUGS
142              
143             Some data types, such as globs, regexes, and code refs, are always copied shallowly.
144              
145             References to hash elements are not properly duplicated. (This is why two tests in t/dclone.t that are marked "todo".) For example, the following test should succeed but does not:
146              
147             my $hash = { foo => 1 };
148             $hash->{bar} = \{ $hash->{foo} };
149             my $copy = clone( \%hash );
150             $hash->{foo} = 2;
151             $copy->{foo} = 2;
152             ok( $hash->{bar} == $copy->{bar} );
153              
154             To report bugs via the CPAN web tracking system, go to
155             C<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Clone-PP> or send mail
156             to C<Dist=Clone-PP#rt.cpan.org>, replacing C<#> with C<@>.
157              
158             =head1 SEE ALSO
159              
160             L<Clone> - a baseclass which provides a C<clone()> method.
161              
162             L<MooseX::Clone> - find-grained cloning for Moose objects.
163              
164             The C<dclone()> function in L<Storable>.
165              
166             L<Data::Clone> -
167             polymorphic data cloning (see its documentation for what that means).
168              
169             L<Clone::Any> - use whichever of the cloning methods is available.
170              
171             =head1 REPOSITORY
172              
173             L<https://github.com/neilbowers/Clone-PP>
174              
175             =head1 AUTHOR AND CREDITS
176              
177             Developed by Matthew Simon Cavalletto at Evolution Softworks.
178             More free Perl software is available at C<www.evoscript.org>.
179              
180              
181             =head1 COPYRIGHT AND LICENSE
182              
183             Copyright 2003 Matthew Simon Cavalletto. You may contact the author
184             directly at C<evo@cpan.org> or C<simonm@cavalletto.org>.
185              
186             Code initially derived from Ref.pm. Portions Copyright 1994 David Muir Sharnoff.
187              
188             Interface based by Clone by Ray Finch with contributions from chocolateboy.
189             Portions Copyright 2001 Ray Finch. Portions Copyright 2001 chocolateboy.
190              
191             You may use, modify, and distribute this software under the same terms as Perl.
192              
193             =cut