First, I'd like to offer my thanks to diotalevi for throwing all sorts of ideas at me early on (which prodded me to continue work on it), bart for giving me last minute feedback (which I haven't forgetten) and anyone else that I may be forgetting.
Data::Dumper::Lite was conceived as a "toy module" to help me grasp the different types of data structures (and references) and how best to get at the data inside of them. I am unhappy with the way that Data::Dumper dumps a subroutine as sub { "DUMMY" } so I added in some extra functionality using B::Deparse. I would also like to eventually be able to view referenced lvalues (i.e. I'd like my $lref = \substr("abc",1,1);print $dumper->Dump($lref); to print substr("abc",1,1) instead of 'b'.)
The documentation is nonexistant at this point since the guts of the module are still being hashed out. </bad pun>
Usage is extremely simple. Create a new instance and then pass a data structure reference to the Dump method of that instance.
#!/usr/bin/perl -w use strict; use Data::Dumper::Lite; my @array = qw(foo bar baz); my %hash = ( foo => \@array, bar => 'none', baz => 42, ); my $dumper = Data::Dumper::Lite->new(); print $dumper->Dump(\%hash);
Without any further adieu, give a nice walm welcome to Data::Dumper::Lite!
package Data::Dumper::Lite; use strict; use warnings; use Scalar::Util qw(blessed reftype looks_like_number); use B::Deparse; use vars qw($VERSION); $VERSION = "0.06"; *isa = \&UNIVERSAL::isa; # import UNIVERSAL::isa sub new { my $invocant = shift; my $class = ref($invocant) || $invocant; my $self = { DEPTH => 0, # data structure (DS) depth ORIG => undef, # original DS reference STRUCT => undef, # DS being examined. May switch to anon. array TYPE => undef, # type of DS being examined. May switch to anon +. array DUMP => undef, # data of the dump }; $self->{REF} = { # store our type handler subroutines SCALAR => sub { $self->{DUMP} .= $self->_quote(${$self->{STRUCT}}); }, CODE => sub { my $deparse = B::Deparse->new("-p", "-sC"); my $code = $deparse->coderef2text($self->{STRUCT}); $self->{DUMP} .= 'sub ' . $code; }, GLOB => sub { $self->{DUMP} .= '*' . *{$self->{STRUCT}}{PACKAGE} . '::' . *{$s +elf->{STRUCT}}{NAME}; }, REF => sub { $self->{DUMP} .= '\\'; $self->Dump(${$self->{STRUCT}}); }, HASH => sub { my %hash = %{$self->{STRUCT}}; $self->_openstruct; foreach my $key (keys %hash) { $self->{DUMP} .= $self->_spacer . $key . ' => '; my $value = $hash{$key}; if (reftype $value) { $self->Dump($value); } else { $self->{DUMP} .= $self->_quote($value) . ",\n"; } } $self->_closestruct('HASH'); }, ARRAY => sub { my @array = @{$self->{STRUCT}}; $self->_openstruct; foreach my $value (@array) { $self->{DUMP} .= $self->_spacer; if (reftype $value) { $self->Dump($value); } else { $self->{DUMP} .= $self->_quote($value) . ",\n"; } } $self->_closestruct('ARRAY'); }, LVALUE => sub { $self->{DUMP} .= "#LVALUE\n" . $self->_quote(${$self->{STRUCT}}) +; }, }; bless ($self, $class); return $self; } sub _spacer() { my $self = shift; return ($self->{DEPTH} == 1) ? '' : ' ' x $self->{DEPTH}; } sub _quote { my $self = shift; my $value = shift; return (!defined $value) ? '' : (looks_like_number $value) ? $value +: qq('$value'); } sub _openstruct { my $self = shift; $self->{DUMP} .= ($self->{TYPE} eq 'HASH' ? '{' : '[') . "\n"; ++$self->{DEPTH}; } sub _closestruct { my $self = shift; my $type = shift; # I need a reminder (but not for long) --$self->{DEPTH}; $self->{DUMP} .= $self->_spacer . ($type eq 'HASH' ? '}' : ']'); } sub Dump { my $self = shift; $self->{STRUCT} = shift; # Get the reference to a data structure $self->{TYPE} = reftype $self->{STRUCT}; # is it a reference? my $blessed = blessed $self->{STRUCT}; die "usage: Dump(REFERENCE)" if (!$self->{TYPE}); # if not, then die + quickly if ($self->{DEPTH} == 0) { $self->{ORIG} = $self->{STRUCT}; # store original reference $self->{DUMP} = '$VAR = '; } else { if ($self->{STRUCT} == $self->{ORIG}) { # see perlref $self->{DUMP} .= "\\\$VAR,\n"; return; } } ++$self->{DEPTH}; $self->{DUMP} .= "bless(" if ($blessed && !exists $self->{REF}{$bles +sed}); if (exists $self->{REF}{$self->{TYPE}}) { &{$self->{REF}{$self->{TYPE}}}; } else { $self->{DUMP} .= "Unknown {TYPE} $self->{TYPE}!\n"; } if ($blessed && !exists $self->{REF}{$blessed}) { $self->{DUMP} .= ", " . $self->_quote($blessed) . ")"; } if ($self->{DEPTH} == 1) { my $last = substr($self->{DUMP}, -2, 2); if ($last eq ",\n") { substr($self->{DUMP}, -2, 1) = ';'; } elsif ($last ne ";\n") { $self->{DUMP} .= ";\n" ; } } $self->{DUMP} .= ",\n" if ($self->{DEPTH} > 1); --$self->{DEPTH}; return $self->{DUMP}; } # end of sub Dump sub AUTOLOAD; 1;
I know that it is not exactly the prettiest module that you have ever seen but it gets the job done and weighs in at 139 lines (including the whitespace!).
This post is a Request For Comments. I.e. reply with questions, comments, suggestions, etc. I would like to upload this to CPAN once all of the kinks are worked out and the documentation has been added.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: RFC: Data::Dumper::Lite
by broquaint (Abbot) on May 27, 2003 at 16:11 UTC | |
by Mr. Muskrat (Canon) on May 27, 2003 at 18:38 UTC | |
|
Re: RFC: Data::Dumper::Lite
by adrianh (Chancellor) on May 27, 2003 at 15:58 UTC | |
by Mr. Muskrat (Canon) on May 27, 2003 at 18:30 UTC | |
by Juerd (Abbot) on May 28, 2003 at 06:37 UTC | |
by Mr. Muskrat (Canon) on May 28, 2003 at 13:13 UTC | |
by John M. Dlugosz (Monsignor) on May 27, 2003 at 22:17 UTC | |
by adrianh (Chancellor) on May 27, 2003 at 22:41 UTC | |
by Mr. Muskrat (Canon) on May 28, 2003 at 13:34 UTC | |
by Mr. Muskrat (Canon) on May 28, 2003 at 13:29 UTC | |
|
Re: RFC: Data::Dumper::Lite
by jryan (Vicar) on May 27, 2003 at 16:36 UTC | |
by Mr. Muskrat (Canon) on May 27, 2003 at 18:55 UTC | |
by Juerd (Abbot) on May 28, 2003 at 06:43 UTC | |
by Mr. Muskrat (Canon) on May 28, 2003 at 15:51 UTC | |
|
Re: RFC: Data::Dumper::Lite
by Mr. Muskrat (Canon) on May 27, 2003 at 18:57 UTC | |
|
Re: RFC: Data::Dumper::Lite
by Mr. Muskrat (Canon) on Jun 03, 2003 at 13:24 UTC |