home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Acorn User 10
/
AU_CD10.iso
/
Updates
/
Perl
/
Non-RPC
/
!Perl
/
riscos
/
RISCOS
/
Clone.pm
< prev
next >
Wrap
Text File
|
1998-07-31
|
3KB
|
113 lines
package RISCOS::Clone;
require Exporter;
use strict;
use vars qw (@ISA @EXPORT_OK $VERSION);
@ISA = qw(Exporter);
@EXPORT_OK = qw(Clone clone);
$VERSION = 0.01;
sub Clone { # aka clone-hash
my ($new, $old) = ({}, $_[0]);
# This is where we break if someone makes a class which doesn't
# store stuff in a hash
while (my ($key, $value) = each %$old) {
# This is where we break if key is supposed to be
# stringifed version of value (where value is a hash)
$$new{$key} = clone ($value);
}
ref ($old) eq 'HASH' ? $new : bless ($new, ref $old)
}
sub clone {
# Beware:
# 0 Will loop on structures that refer to themselves
# 1 Will copy things that may not want duplication (eg RISCOS::Font objects
# have a dummy clone method to stop this)
# 2 Will screw up if hashes are supposed to be keyed with a stringified
# reference.
# 3 Will screw up if blessed references are not hash references.
#
# For all of the above define a more clever cloner.
my @result = @_; # Copy it so as not to scribble all over it
foreach my $thing (@result) {
if ((not ref $thing) or ref ($thing) eq 'CODE'
or ref ($thing) eq 'GLOB')
{
# undef, scalars, code refs and globs are unchanged
# hum. globs.
} elsif (ref ($thing) eq 'SCALAR' or ref ($thing) eq 'LVALUE') {
$thing = $$thing;
$thing = \$thing;
} elsif (ref ($thing) eq 'ARRAY') {
$thing = [clone (@$thing)];
} else {
# Assume its a hash
if (ref ($thing) ne 'HASH' and $thing->can('Clone')) {
$thing = $thing->Clone();
} else {
$thing = Clone ($thing);
}
}
}
wantarray ? @result : $result[0];
}
__END__
=head1 NAME
RISCOS::Clone -- copy nested structures.
=head1 SYNOPSIS
use RISCOS::Clone qw(clone);
@copy = clone (@original);
$copy = $original->Clone();
=head1 DESCRIPTION
This module provides functions to copy structures.
=over 4
=item Clone <hash_ref>
copies a hash reference, C<bless>ing the returned hash with the class (if any)
of the original. C<Clone> uses <clone> to copy each hash value.
=item clone <object> ...
recursively copies the objects passed in. In list contest returns the copied
objects, in scalar context returns the first object. C<clone> copies C<undef>,
scalars, code referencess and globs unchanged, scalar references are copied as
a reference to scalar containing the identical value. Array references are
passed recursively to C<clone>, hash references to C<Clone>. Blessed references
that posses a C<Clone> method have this method called, else C<Clone> is called
to make a copy.
C<clone> is simpleminded and will go wrong as follows.
clone will loop on structures that refer to themselves
clone will copy things that may not want duplication
(eg RISCOS::Font objects have a dummy Clone method to stop this)
clone will not work correctly if hashes are supposed to be keyed with a
stringified reference.
Clone will C<die> if blessed references are not hash references.
For objects these problems can be overcome by writing a custom C<Clone> method.
=back
=head1 BUGS
Caveats as noted above. Not tested enough yet.
=head1 AUTHOR
Nicholas Clark <F<nick@unfortu.net>>
=cut