#!/usr/bin/perl # # recurse2txt routines # # version 1.03, 5-19-06, michael@bizsystems.com # #use strict; #use diagnostics; use overload; # generate a unique signature for a particular hash # # Data::Dumper actually does much more than this, however, it # does not stringify hash's in a consistent manner. i.e. no SORT # # The routine below, while not covering recursion loops, non ascii # characters, etc.... does produce text that can be eval'd and is # consistent with each rendering. # sub Dumper { return "undef\n" unless defined $_[0]; my $ref = ref $_[0]; return "not a reference\n" unless $ref; unless ($ref eq 'HASH' or $ref eq 'ARRAY') { ($ref) = (overload::StrVal($_[0]) =~ /^(?:.*\=)?([^=]*)\(/); } my $p = { depth => 0, elements => 0, }; bless $p,__PACKAGE__; my $data; if ($ref eq 'HASH') { $data = $p->hash_recurse($_[0],"\n"); } elsif ($ref eq 'ARRAY') { $data = $p->array_recurse($_[0]); } else { return $ref ." unsupported\n"; } $data =~ s/,\n$/;\n/; return $p->{elements} ."\t= ". $data; } # input: pointer to hash, terminator # returns: data # sub hash_recurse { my($p,$ptr,$n) = @_; $n = '' unless $n; my $data = "{\n"; foreach my $key (sort keys %$ptr) { $data .= "\t'". $key ."'\t=> "; $data .= _dump($p,$ptr->{$key},"\n"); } $data .= '},'.$n; } # generate a unique signature for a particular array # # input: pointer to array, terminator # returns: data sub array_recurse { my($p,$ptr,$n) = @_; $n = '' unless $n; my $data = '['; foreach my $item (@$ptr) { $data .= _dump($p,$item); } $data .= "],\n"; } # input: self, item, append # return: data # sub _dump { my($p,$item,$n) = @_; $p->{elements}++; $n = '' unless $n; my $ref = ref $item; if ($ref eq 'HASH') { return tabout($p->hash_recurse($item,"\n")); } elsif($ref eq 'ARRAY') { return $p->array_recurse($item,$n); } elsif($ref eq 'SCALAR') { return q|\$SCALAR,|.$n; } elsif ($ref eq 'GLOB') { my $g = *{$item}; return "\\$g" .','.$n; } elsif(do {my $g = \$item; ref $g eq 'GLOB'}) { return "$item" .','.$n; } elsif($ref eq 'CODE') { return q|sub {'DUMMY'},|.$n; } elsif (defined $item) { return wrap_data($item) .','.$n; } else { return 'undef,'.$n; } } sub tabout { my @data = split(/\n/,shift); my $data = shift @data; $data .= "\n"; foreach(@data) { $data .= "\t$_\n"; } $data; } sub wrap_data { my $data = shift; return ($data =~ /\D/ || $data =~ /^$/) ? q|'|. $data .q|'| : $data; } 1;