home *** CD-ROM | disk | FTP | other *** search
- 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
-