-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathClone.pm
More file actions
278 lines (174 loc) · 6.56 KB
/
Clone.pm
File metadata and controls
278 lines (174 loc) · 6.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
package Clone;
use strict;
require Exporter;
use XSLoader ();
our @ISA = qw(Exporter);
our @EXPORT;
our @EXPORT_OK = qw( clone );
our $VERSION = '0.50';
our $WARN = 1;
XSLoader::load('Clone', $VERSION);
1;
__END__
=head1 NAME
Clone - recursively copy Perl datatypes
=for html
<a href="https://github.com/garu/Clone/actions/workflows/test.yml"><img src="https://github.com/garu/Clone/actions/workflows/test.yml/badge.svg" alt="Build Status"></a>
<a href="https://metacpan.org/pod/Clone"><img src="https://badge.fury.io/pl/Clone.svg" alt="CPAN version"></a>
=head1 SYNOPSIS
use Clone 'clone';
my $data = {
set => [ 1 .. 50 ],
foo => {
answer => 42,
object => SomeObject->new,
},
};
my $cloned_data = clone($data);
$cloned_data->{foo}{answer} = 1;
print $cloned_data->{foo}{answer}; # '1'
print $data->{foo}{answer}; # '42'
You can also add it to your class:
package Foo;
use parent 'Clone';
sub new { bless {}, shift }
package main;
my $obj = Foo->new;
my $copy = $obj->clone;
=head1 DESCRIPTION
This module provides a C<clone()> method which makes recursive
copies of nested hash, array, scalar and reference types,
including tied variables and objects.
C<clone()> takes a scalar argument and duplicates it. To duplicate lists,
arrays or hashes, pass them in by reference, e.g.
my $copy = clone (\@array);
# or
my %copy = %{ clone (\%hash) };
=head1 EXAMPLES
=head2 Cloning Blessed Objects
package Person;
sub new {
my ($class, $name) = @_;
bless { name => $name, friends => [] }, $class;
}
package main;
use Clone 'clone';
my $person = Person->new('Alice');
my $clone = clone($person);
# $clone is a separate object with the same data
push @{$person->{friends}}, 'Bob';
print scalar @{$clone->{friends}}; # 0
=head2 Handling Circular References
Clone properly handles circular references, preventing infinite loops:
my $a = { name => 'A' };
my $b = { name => 'B', ref => $a };
$a->{ref} = $b; # circular reference
my $clone = clone($a);
# Circular structure is preserved in the clone
=head2 Cloning Weakened References
use Scalar::Util 'weaken';
my $obj = { data => 'important' };
my $container = { strong => $obj, weak => $obj };
weaken($container->{weak});
my $clone = clone($container);
# Both strong and weak references are preserved correctly
=head2 Cloning Tied Variables
use Tie::Hash;
tie my %hash, 'Tie::StdHash';
%hash = (a => 1, b => 2);
my $clone = clone(\%hash);
# The tied behavior is preserved in the clone
=head1 LIMITATIONS
=over 4
=item * Maximum Recursion Depth
Clone uses a recursion depth counter to prevent stack overflow.
The default limit is 4000 rdepth units on Linux/macOS and 2000 on
Windows/Cygwin. Each nesting level consumes approximately 2 rdepth
units, so the effective limits are roughly 2000 nesting levels on
Linux/macOS and 1000 on Windows/Cygwin.
When the limit is exceeded, Clone switches to an iterative fallback
that preserves deep-copy semantics without stack overflow. This
covers arrays, hashes, and all reference types (including deeply
nested scalar references).
Non-clonable types (globs, code references, formats, IO handles)
are always shared regardless of depth. If one of these is encountered
past the depth limit, a warning is emitted. To silence it:
$Clone::WARN = 0;
You can override the depth limit by passing it as the second argument
to C<clone()>:
my $copy = clone($data, 8000); # allow deeper recursion
=item * Filehandles and IO Objects
Filehandles and IO objects are not deep-copied. The clone shares the
same underlying filehandle object as the original (reference count is
incremented). For DBI database handles, Clone skips opaque XS magic
to avoid dangling pointers, but the resulting clone should not be used
as a database handle.
=item * Code References
Code references (subroutines) are cloned by reference, not by value.
The cloned coderef points to the same subroutine as the original.
=item * Thread Safety
Clone is not explicitly thread-safe. Use appropriate synchronization
when cloning data structures across threads.
=back
=head1 PERFORMANCE
Clone is implemented in C using Perl's XS interface, making it very fast
for most use cases.
=over 4
=item * When to use Clone
Clone is optimized for speed and works best with:
=over 4
=item * Shallow to medium-depth structures (3 levels or fewer)
=item * Data structures that need fast cloning in hot code paths
=item * Structures containing blessed objects and tied variables
=back
=item * When to use Storable::dclone
L<Storable>'s C<dclone()> may be faster for:
=over 4
=item * Very deep structures (4+ levels)
=item * When you need serialization features
=back
=back
Benchmarking your specific use case is recommended for performance-critical
applications.
=head1 CAVEATS
=over 4
=item * Cloned objects are deep copies
Changes to the clone do not affect the original, and vice versa. This
includes nested references and objects.
=item * Object internals
While Clone handles most blessed objects correctly, objects with XS
components or complex internal state may not clone as expected. Test
thoroughly with your specific object types.
=item * Memory usage
Cloning large data structures creates a complete copy in memory. Ensure
you have sufficient memory available.
=back
=head1 SEE ALSO
L<Storable>'s C<dclone()> is a flexible solution for cloning variables,
albeit slower for average-sized data structures. Simple
and naive benchmarks show that Clone is faster for data structures
with 3 or fewer levels, while C<dclone()> can be faster for structures
4 or more levels deep.
Other modules that may be of interest:
L<Clone::PP> - Pure Perl implementation of Clone
L<Scalar::Util> - For C<weaken()> and other scalar utilities
L<Data::Dumper> - For debugging and inspecting data structures
=head1 SUPPORT
=over 4
=item * Bug Reports and Feature Requests
Please report bugs on GitHub: L<https://github.com/garu/Clone/issues>
=item * Source Code
The source code is available on GitHub: L<https://github.com/garu/Clone>
=back
=head1 COPYRIGHT
Copyright 2001-2026 Ray Finch. All Rights Reserved.
This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=head1 AUTHOR
Ray Finch C<< <rdf@cpan.org> >>
Breno G. de Oliveira C<< <garu@cpan.org> >>,
Nicolas Rochelemagne C<< <atoomic@cpan.org> >>
and
Florian Ragwitz C<< <rafl@debian.org> >> perform routine maintenance
releases since 2012.
=cut