NAME
Data::Peek - A collection of low-level debug facilities
SYNOPSIS
use Data::Peek;
print DDumper \%hash; # Same syntax as Data::Dumper
DTidy { ref => $ref };
print DPeek \$var;
my ($pv, $iv, $nv, $rv, $magic) = DDual ($var [, 1]);
print DPeek for DDual ($!, 1);
print DDisplay ("ab\nc\x{20ac}\rdef\n");
print DHexDump ("ab\nc\x{20ac}\rdef\n");
my $dump = DDump $var;
my %hash = DDump \@list;
DDump \%hash;
my %hash = DDump (\%hash, 5); # dig 5 levels deep
my $dump;
open my $fh, ">", \$dump;
DDump_IO ($fh, \%hash, 6);
close $fh;
print $dump;
# Imports
use Data::Peek qw( :tidy VNR DGrow triplevar );
my $x = ""; DGrow ($x, 10000);
my $tv = triplevar ("\N{GREEK SMALL LETTER PI}", 3, "3.1415");
DDsort ("R");
DDumper [ $x ]; # use of :tidy makes DDumper behave like DTidy
DESCRIPTION
Data::Peek started off as DDumper
being a wrapper module over Data::Dumper, but grew out to be a set of low-level data introspection utilities that no other module provided yet, using the lowest level of the perl internals API as possible.
DDumper ($var, ...)
Not liking the default output of Data::Dumper, and always feeling the need to set $Data::Dumper::Sortkeys = 1;
, and not liking any of the default layouts, this function is just a wrapper around Data::Dumper::Dumper with everything set as I like it.
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Indent = 1;
If Data::Peek
is use
d with import argument :tidy
, the result is formatted according to Perl::Tidy, see DTidy below, otherwise the result is further beautified to meet my needs:
* quotation of hash keys has been removed (with the disadvantage
that the output might not be parseable again).
* arrows for hashes are aligned at 16 (longer keys don't align)
* closing braces and brackets are now correctly aligned
In void context, DDumper
warn
's.
Example
$ perl -MDP \
-e'DDumper { ape => 1, foo => "egg", bar => [ 2, "baz", undef ]};'
{ ape => 1,
bar => [
2,
'baz',
undef
],
foo => 'egg'
};
DTidy ($var, ...)
DTidy
is an alternative to DDumper
, where the output of DDumper
is formatted using Perl::Tidy
(if available) according to your .perltidyrc
instead of the default behavior, maybe somewhat like (YMMV):
$ perl -MDP=:tidy \
-we'DDumper { ape => 1, foo => "egg", bar => [ 2, "baz", undef ]};'
{ 'ape' => 1,
'bar' => [2, 'baz', undef],
'foo' => 'egg'
}
If Data::Peek
is use
d with import argument :tidy
, this is the default output method for DDumper
.
If Perl::Tidy is not available, DTidy
will fallback to DDumper
.
This idea was shamelessly copied from John McNamara's Data::Dumper::Perltidy.
DDsort ( 0 | 1 | R | N | NR | V | VR | VN | VNR )
Set the hash sort algorithm for DDumper. The default is to sort by key value.
0 - Do not sort
1 - Sort by key
R - Reverse sort by key
N - Sort by key numerical
NR - Sort by key numerical descending
V - Sort by value
VR - Reverse sort by value
VN - Sort by value numerical
VNR - Reverse sort by value numerical
These can also be passed to import:
$ perl -MDP=VNR \
-we'DDumper { foo => 1, bar => 2, zap => 3, gum => 13 }'
{ gum => 13,
zap => 3,
bar => 2,
foo => 1
};
$ perl -MDP=V \
-we'DDumper { foo => 1, bar => 2, zap => 3, gum => 13 }'
{ foo => 1,
gum => 13,
bar => 2,
zap => 3
};
DPeek
DPeek ($var)
Playing with sv_dump
, I found Perl_sv_peek
, and it might be very useful for simple checks. If $var
is omitted, uses $_.
Example
print DPeek "abc\x{0a}de\x{20ac}fg";
PV("abc\nde\342\202\254fg"\0) [UTF8 "abc\nde\x{20ac}fg"]
In void context, DPeek
prints to STDERR
plus a newline.
DDisplay
DDisplay ($var)
Show the PV content of a scalar the way perl debugging would have done. UTF-8 detection is on, so this is effectively the same as returning the first part the DPeek
returns for non-UTF8 PV's or the second part for UTF-8 PV's. DDisplay
returns the empty string for scalars that no have a valid PV.
Example
print DDisplay "abc\x{0a}de\x{20ac}fg";
"abc\nde\x{20ac}fg"
In void context, DDisplay
uses warn
to display the result.
DHexDump
DHexDump ($var)
DHexDump ($var, $length)
Show the (stringified) content of a scalar as a hex-dump. If $var
is omitted, $_
is dumped. Returns undef
or an empty list if $var
(or $_
) is undefined. If $length
is given and is lower than the length of the stringified $var
, only <$length> bytes are dumped.
In void context, the dump is done to STDERR. In scalar context, the complete dump is returned as a single string. In list context, the dump is returned as lines.
Example
print DHexDump "abc\x{0a}de\x{20ac}fg";
0000 61 62 63 0a 64 65 e2 82 ac 66 67 abc.de...fg
my ($pv, $iv, $nv, $rv, $hm) = DDual ($var [, $getmagic])
DDual will return the basic elements in a variable, guaranteeing that no conversion takes place. This is very useful for dual-var variables, or when checking is a variable has defined entries for a certain type of scalar. For each String (PV), Integer (IV), Double (NV), and Reference (RV), the current value of $var
is returned or undef if it is not set (yet). The 5th element is an indicator if $var
has magic, which is not invoked in the returned values, unless explicitly asked for with a true optional second argument.
Example
print DPeek for DDual ($!, 1);
In void context, DDual does the equivalent of
{ my @d = DDual ($!, 1);
print STDERR
DPeek ($!), "\n",
" PV: ", DPeek ($d[0]), "\n",
" IV: ", DPeek ($d[1]), "\n",
" NV: ", DPeek ($d[2]), "\n",
" RV: ", DPeek ($d[3]), "\n";
}
my $len = DGrow ($pv, $size)
Fastest way to preallocate space for a PV scalar. Returns the allocated length. If $size is smaller than the already allocated space, it will not shrink.
cmpthese (-2, {
pack => q{my $x = ""; $x = pack "x20000"; $x = "";},
op_x => q{my $x = ""; $x = "x" x 20000; $x = "";},
grow => q{my $x = ""; DGrow ($x, 20000); $x = "";},
});
Rate op_x pack grow 5.8.9 5.10.1 5.12.4 5.14.2
op_x 62127/s -- -59% -96% 118606/s 119730/s 352255/s 362605/s
pack 152046/s 145% -- -91% 380075/s 355666/s 347247/s 387349/s
grow 1622943/s 2512% 967% -- 2818380/s 2918783/s 2672340/s 2886787/s
my $tp = triplevar ($pv, $iv, $nv)
When making DDual
I wondered if it were possible to create triple-val scalar variables. Scalar::Util already gives us dualvar
, that creates you a scalar with different numeric and string values that return different values in different context. Not that triplevar
would be very useful, compared to dualvar
, but at least this shows that it is possible.
triplevar
is not exported by default.
Example:
DDual Data::Peek::triplevar ("\N{GREEK SMALL LETTER PI}", 3, 3.1415);
PVNV("\317\200"\0) [UTF8 "\x{3c0}"]
PV: PV("\317\200"\0) [UTF8 "\x{3c0}"]
IV: IV(3)
NV: NV(3.1415)
RV: SV_UNDEF
DDump ([$var [, $dig_level]])
A very useful module when debugging is Devel::Peek
, but is has one big disadvantage: it only prints to STDERR, which is not very handy when your code wants to inspect variables at a low level.
Perl itself has sv_dump
, which does something similar, but still prints to STDERR, and only one level deep.
DDump
is an attempt to make the innards available to the script level with a reasonable level of compatibility. DDump
is context sensitive.
In void context, it behaves exactly like Perl_sv_dump
.
In scalar context, it returns what Perl_sv_dump
would have printed.
The default for the first argument is $_
.
In list context, it returns a hash of the variable's properties. In this mode you can pass an optional second argument that determines the depth of digging.
Example
print scalar DDump "abc\x{0a}de\x{20ac}fg"
SV = PV(0x723250) at 0x8432b0
REFCNT = 1
FLAGS = (PADBUSY,PADMY,POK,pPOK,UTF8)
PV = 0x731ac0 "abc\nde\342\202\254fg"\0 [UTF8 "abc\nde\x{20ac}fg"]
CUR = 11
LEN = 16
my %h = DDump "abc\x{0a}de\x{20ac}fg";
print DDumper \%h;
{ CUR => '11',
FLAGS => {
PADBUSY => 1,
PADMY => 1,
POK => 1,
UTF8 => 1,
pPOK => 1
},
LEN => '16',
PV => '0x731ac0 "abc\\nde\\342\\202\\254fg"\\0 [UTF8 "abc\\nde\\x{20ac}fg"]',
REFCNT => '1',
sv => 'PV(0x723250) at 0x8432c0'
};
my %h = DDump {
ape => 1,
foo => "egg",
bar => [ 2, "baz", undef ],
}, 1;
print DDumper \%h;
{ FLAGS => {
PADBUSY => 1,
PADMY => 1,
ROK => 1
},
REFCNT => '1',
RV => {
PVIV("ape") => {
FLAGS => {
IOK => 1,
PADBUSY => 1,
PADMY => 1,
pIOK => 1
},
IV => '1',
REFCNT => '1',
sv => 'IV(0x747020) at 0x843a10'
},
PVIV("bar") => {
CUR => '0',
FLAGS => {
PADBUSY => 1,
PADMY => 1,
ROK => 1
},
IV => '1',
LEN => '0',
PV => '0x720210 ""',
REFCNT => '1',
RV => '0x720210',
sv => 'PVIV(0x7223e0) at 0x843a10'
},
PVIV("foo") => {
CUR => '3',
FLAGS => {
PADBUSY => 1,
PADMY => 1,
POK => 1,
pPOK => 1
},
IV => '1',
LEN => '8',
PV => '0x7496c0 "egg"\\0',
REFCNT => '1',
sv => 'PVIV(0x7223e0) at 0x843a10'
}
},
sv => 'RV(0x79d058) at 0x843310'
};
DDump_IO ($io, $var [, $dig_level])
A wrapper function around perl's internal Perl_do_sv_dump
, which makes Devel::Peek
completely superfluous.
Example
my $dump;
open my $eh, ">", \$dump;
DDump_IO ($eh, { 3 => 4, ape => [5..8]}, 6);
close $eh;
print $dump;
SV = RV(0x79d9e0) at 0x843f00
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x741090
SV = PVHV(0x79c948) at 0x741090
REFCNT = 1
FLAGS = (SHAREKEYS)
IV = 2
NV = 0
ARRAY = 0x748ff0 (0:7, 2:1)
hash quality = 62.5%
KEYS = 2
FILL = 1
MAX = 7
RITER = -1
EITER = 0x0
Elt "ape" HASH = 0x97623e03
SV = RV(0x79d9d8) at 0x8440e0
REFCNT = 1
FLAGS = (ROK)
RV = 0x741470
SV = PVAV(0x7264b0) at 0x741470
REFCNT = 2
FLAGS = ()
IV = 0
NV = 0
ARRAY = 0x822f70
FILL = 3
MAX = 3
ARYLEN = 0x0
FLAGS = (REAL)
Elt No. 0
SV = IV(0x7467c8) at 0x7c1aa0
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 5
Elt No. 1
SV = IV(0x7467b0) at 0x8440f0
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 6
Elt No. 2
SV = IV(0x746810) at 0x75be00
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 7
Elt No. 3
SV = IV(0x746d38) at 0x7799d0
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 8
Elt "3" HASH = 0xa400c7f3
SV = IV(0x746fd0) at 0x7200e0
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 4
INTERNALS
DDump
uses an XS wrapper around Perl_sv_dump
where the STDERR is temporarily caught to a pipe. The internal XS helper functions are not meant for user space
DDump_XS (SV *sv)
Base interface to internals for DDump
.
BUGS
Windows and AIX might be using a build where not all symbols that were supposed to be exported in the public API are not. Perl_pv_peek
is one of them.
Not all types of references are supported.
No idea how far back this goes in perl support, but Devel::PPPort has proven to be a big help.
SEE ALSO
Devel::Peek, Data::Dumper, Data::Dump, Devel::Dumpvar, Data::Dump::Streamer, Data::Dumper::Perltidy, Perl::Tidy.
AUTHOR
H.Merijn Brand <hmbrand@cpan.org>
COPYRIGHT AND LICENSE
Copyright (C) 2008-2023 H.Merijn Brand
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.