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
|
#!/usr/bin/perl
#
# recurse2txt routines
#
# version 1.08, 12-20-12, michael@bizsystems.com
#
# 10-3-11 updated to bless into calling package
# 10-10-11 add SCALAR ref support
# 1.06 12-16-12 add hexDumper
# 1.07 12-19-12 added wantarray return of data and elements
# 1.08 12-20-12 add wantarray to hexDumper
#
#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 hexDumper {
if (wantarray) {
($data,$count) = Dumper($_[0]);
$data =~ s/(\b\d+)/sprintf("0x%x",$1)/ge;
return ($data,$count);
}
(my $x = Dumper($_[0])) =~ s/(\b\d+)/sprintf("0x%x",$1)/ge;
$x;
}
sub Dumper {
unless (defined $_[0]) {
return ("undef\n",'undef') if wantarray;
return "undef\n";
}
my $ref = ref $_[0];
return "not a reference\n" unless $ref;
unless ($ref eq 'HASH' or $ref eq 'ARRAY' or $ref eq 'SCALAR') {
($ref) = (overload::StrVal($_[0]) =~ /^(?:.*\=)?([^=]*)\(/);
}
my $p = {
depth => 0,
elements => 0,
};
(my $pkg = (caller(0))[3]) =~ s/(.+)::Dumper/$1/;
bless $p,$pkg;
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 = $p->scalar_recurse($_[0]);
}
$data =~ s/,\n$/;\n/;
return ($data,$p->{elements}) if wantarray;
return $p->{elements} ."\t= ". $data;
}
# input: pointer to scalar, terminator
# returns data
#
sub scalar_recurse {
my($p,$ptr,$n) = @_;
$n = '' unless $n;
my $data = "\\";
$data .= _dump($p,$$ptr);
$data .= "\n";
}
# 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;
return($p->scalar_recurse($item,$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;
|