.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Peek 3pm" .TH Peek 3pm "2018-11-01" "perl v5.28.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Data::Peek \- A collection of low\-level debug facilities .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Data::Peek; \& \& print DDumper \e%hash; # Same syntax as Data::Dumper \& DTidy { ref => $ref }; \& \& print DPeek \e$var; \& my ($pv, $iv, $nv, $rv, $magic) = DDual ($var [, 1]); \& print DPeek for DDual ($!, 1); \& print DDisplay ("ab\enc\ex{20ac}\erdef\en"); \& print DHexDump ("ab\enc\ex{20ac}\erdef\en"); \& \& my $dump = DDump $var; \& my %hash = DDump \e@list; \& DDump \e%hash; \& \& my %hash = DDump (\e%hash, 5); # dig 5 levels deep \& \& my $dump; \& open my $fh, ">", \e$dump; \& DDump_IO ($fh, \e%hash, 6); \& close $fh; \& print $dump; \& \& # Imports \& use Data::Peek qw( :tidy VNR DGrow triplevar ); \& my $x = ""; DGrow ($x, 10000); \& my $tv = triplevar ("\eN{GREEK SMALL LETTER PI}", 3, "3.1415"); \& DDsort ("R"); \& DDumper [ $x ]; # use of :tidy make DDumper behave as DTidy .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Data::Peek started off as \f(CW\*(C`DDumper\*(C'\fR 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 \s-1API\s0 as possible. .SS "DDumper ($var, ...)" .IX Subsection "DDumper ($var, ...)" Not liking the default output of Data::Dumper, and always feeling the need to set \f(CW\*(C`$Data::Dumper::Sortkeys = 1;\*(C'\fR, 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. .PP .Vb 2 \& $Data::Dumper::Sortkeys = 1; \& $Data::Dumper::Indent = 1; .Ve .PP If \f(CW\*(C`Data::Peek\*(C'\fR is \f(CW\*(C`use\*(C'\fRd with import argument \f(CW\*(C`:tidy\*(C'\fR, the result is formatted according to Perl::Tidy, see DTidy below, otherwise the result is further beautified to meet my needs: .PP .Vb 4 \& * 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\*(Aqt align) \& * closing braces and brackets are now correctly aligned .Ve .PP In void context, \f(CW\*(C`DDumper\*(C'\fR \f(CW\*(C`warn\*(C'\fR's. .PP Example .PP .Vb 2 \& $ perl \-MDP \e \& \-e\*(AqDDumper { ape => 1, foo => "egg", bar => [ 2, "baz", undef ]};\*(Aq \& \& { ape => 1, \& bar => [ \& 2, \& \*(Aqbaz\*(Aq, \& undef \& ], \& foo => \*(Aqegg\*(Aq \& }; .Ve .SS "DTidy ($var, ...)" .IX Subsection "DTidy ($var, ...)" \&\f(CW\*(C`DTidy\*(C'\fR is an alternative to \f(CW\*(C`DDumper\*(C'\fR, where the output of \f(CW\*(C`DDumper\*(C'\fR is formatted using \f(CW\*(C`Perl::Tidy\*(C'\fR (if available) according to your \&\f(CW\*(C`.perltidyrc\*(C'\fR instead of the default behavior, maybe somewhat like (\s-1YMMV\s0): .PP .Vb 6 \& $ perl \-MDP=:tidy \e \& \-we\*(AqDDumper { ape => 1, foo => "egg", bar => [ 2, "baz", undef ]};\*(Aq \& { \*(Aqape\*(Aq => 1, \& \*(Aqbar\*(Aq => [2, \*(Aqbaz\*(Aq, undef], \& \*(Aqfoo\*(Aq => \*(Aqegg\*(Aq \& } .Ve .PP If \f(CW\*(C`Data::Peek\*(C'\fR is \f(CW\*(C`use\*(C'\fRd with import argument \f(CW\*(C`:tidy\*(C'\fR, this is the default output method for \f(CW\*(C`DDumper\*(C'\fR. .PP If Perl::Tidy is not available, \f(CW\*(C`DTidy\*(C'\fR will fallback to \f(CW\*(C`DDumper\*(C'\fR. .PP This idea was shamelessly copied from John McNamara's Data::Dumper::Perltidy. .SS "DDsort ( 0 | 1 | R | V | \s-1VR\s0 | \s-1VN\s0 | \s-1VNR\s0 )" .IX Subsection "DDsort ( 0 | 1 | R | V | VR | VN | VNR )" Set the hash sort algorithm for DDumper. The default is to sort by key value. .PP .Vb 7 \& 0 \- Do not sort \& 1 \- Sort by key \& R \- Reverse sort by key \& V \- Sort by value \& VR \- Reverse sort by value \& VN \- Sort by value numerical \& VNR \- Reverse sort by value numerical .Ve .PP These can also be passed to import: .PP .Vb 10 \& $ perl \-MDP=VNR \e \& \-we\*(AqDDumper { foo => 1, bar => 2, zap => 3, gum => 13 }\*(Aq \& { gum => 13, \& zap => 3, \& bar => 2, \& foo => 1 \& }; \& $ perl \-MDP=V \e \& \-we\*(AqDDumper { foo => 1, bar => 2, zap => 3, gum => 13 }\*(Aq \& { foo => 1, \& gum => 13, \& bar => 2, \& zap => 3 \& }; .Ve .SS "DPeek" .IX Subsection "DPeek" .SS "DPeek ($var)" .IX Subsection "DPeek ($var)" Playing with \f(CW\*(C`sv_dump\*(C'\fR, I found \f(CW\*(C`Perl_sv_peek\*(C'\fR, and it might be very useful for simple checks. If \f(CW$var\fR is omitted, uses \f(CW$_\fR. .PP Example .PP .Vb 1 \& print DPeek "abc\ex{0a}de\ex{20ac}fg"; \& \& PV("abc\ende\e342\e202\e254fg"\e0) [UTF8 "abc\ende\ex{20ac}fg"] .Ve .PP In void context, \f(CW\*(C`DPeek\*(C'\fR prints to \f(CW\*(C`STDERR\*(C'\fR plus a newline. .SS "DDisplay" .IX Subsection "DDisplay" .SS "DDisplay ($var)" .IX Subsection "DDisplay ($var)" Show the \s-1PV\s0 content of a scalar the way perl debugging would have done. \&\s-1UTF\-8\s0 detection is on, so this is effectively the same as returning the first part the \f(CW\*(C`DPeek\*(C'\fR returns for non\-UTF8 \s-1PV\s0's or the second part for \&\s-1UTF\-8 PV\s0's. \f(CW\*(C`DDisplay\*(C'\fR returns the empty string for scalars that no have a valid \s-1PV.\s0 .PP Example .PP .Vb 1 \& print DDisplay "abc\ex{0a}de\ex{20ac}fg"; \& \& "abc\ende\ex{20ac}fg" .Ve .PP In void context, \f(CW\*(C`DDisplay\*(C'\fR uses \f(CW\*(C`warn\*(C'\fR to display the result. .SS "DHexDump" .IX Subsection "DHexDump" .SS "DHexDump ($var)" .IX Subsection "DHexDump ($var)" .ie n .SS "DHexDump ($var, $length)" .el .SS "DHexDump ($var, \f(CW$length\fP)" .IX Subsection "DHexDump ($var, $length)" Show the (stringified) content of a scalar as a hex-dump. If \f(CW$var\fR is omitted, \f(CW$_\fR is dumped. Returns \f(CW\*(C`undef\*(C'\fR or an empty list if \&\f(CW$var\fR (or \f(CW$_\fR) is undefined. If \f(CW$length\fR is given and is lower than the length of the stringified \f(CW$var\fR, only <$length> bytes are dumped. .PP In void context, the dump is done to \s-1STDERR.\s0 In scalar context, the complete dump is returned as a single string. In list context, the dump is returned as lines. .PP Example .PP .Vb 1 \& print DHexDump "abc\ex{0a}de\ex{20ac}fg"; \& \& 0000 61 62 63 0a 64 65 e2 82 ac 66 67 abc.de...fg .Ve .ie n .SS "my ($pv, $iv, $nv, $rv, $hm) = DDual ($var [, $getmagic])" .el .SS "my ($pv, \f(CW$iv\fP, \f(CW$nv\fP, \f(CW$rv\fP, \f(CW$hm\fP) = DDual ($var [, \f(CW$getmagic\fP])" .IX Subsection "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 (\s-1PV\s0), Integer (\s-1IV\s0), Double (\s-1NV\s0), and Reference (\s-1RV\s0), the current value of \f(CW$var\fR is returned or undef if it is not set (yet). The 5th element is an indicator if \f(CW$var\fR has magic, which is \fBnot\fR invoked in the returned values, unless explicitly asked for with a true optional second argument. .PP Example .PP .Vb 1 \& print DPeek for DDual ($!, 1); .Ve .PP In void context, DDual does the equivalent of .PP .Vb 8 \& { my @d = DDual ($!, 1); \& print STDERR \& DPeek ($!), "\en", \& " PV: ", DPeek ($d[0]), "\en", \& " IV: ", DPeek ($d[1]), "\en", \& " NV: ", DPeek ($d[2]), "\en", \& " RV: ", DPeek ($d[3]), "\en"; \& } .Ve .ie n .SS "my $len = DGrow ($pv, $size)" .el .SS "my \f(CW$len\fP = DGrow ($pv, \f(CW$size\fP)" .IX Subsection "my $len = DGrow ($pv, $size)" Fastest way to preallocate space for a \s-1PV\s0 scalar. Returns the allocated length. If \f(CW$size\fR is smaller than the already allocated space, it will not shrink. .PP .Vb 5 \& 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 .Ve .ie n .SS "my $tp = triplevar ($pv, $iv, $nv)" .el .SS "my \f(CW$tp\fP = triplevar ($pv, \f(CW$iv\fP, \f(CW$nv\fP)" .IX Subsection "my $tp = triplevar ($pv, $iv, $nv)" When making \f(CW\*(C`DDual\*(C'\fR I wondered if it were possible to create triple-val scalar variables. Scalar::Util already gives us \f(CW\*(C`dualvar\*(C'\fR, that creates you a scalar with different numeric and string values that return different values in different context. Not that \f(CW\*(C`triplevar\*(C'\fR would be very useful, compared to \f(CW\*(C`dualvar\*(C'\fR, but at least this shows that it is possible. .PP \&\f(CW\*(C`triplevar\*(C'\fR is not exported by default. .PP Example: .PP .Vb 2 \& print DPeek for DDual \& Data::Peek::triplevar ("\eN{GREEK SMALL LETTER PI}", 3, 3.1415); \& \& PV("\e317\e200"\e0) [UTF8 "\ex{3c0}"] \& IV(3) \& NV(3.1415) \& SV_UNDEF \& IV(0) .Ve .ie n .SS "DDump ([$var [, $dig_level]])" .el .SS "DDump ([$var [, \f(CW$dig_level\fP]])" .IX Subsection "DDump ([$var [, $dig_level]])" A very useful module when debugging is \f(CW\*(C`Devel::Peek\*(C'\fR, but is has one big disadvantage: it only prints to \s-1STDERR,\s0 which is not very handy when your code wants to inspect variables at a low level. .PP Perl itself has \f(CW\*(C`sv_dump\*(C'\fR, which does something similar, but still prints to \s-1STDERR,\s0 and only one level deep. .PP \&\f(CW\*(C`DDump\*(C'\fR is an attempt to make the innards available to the script level with a reasonable level of compatibility. \f(CW\*(C`DDump\*(C'\fR is context sensitive. .PP In void context, it behaves exactly like \f(CW\*(C`Perl_sv_dump\*(C'\fR. .PP In scalar context, it returns what \f(CW\*(C`Perl_sv_dump\*(C'\fR would have printed. .PP The default for the first argument is \f(CW$_\fR. .PP 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. .PP Example .PP .Vb 1 \& print scalar DDump "abc\ex{0a}de\ex{20ac}fg" \& \& SV = PV(0x723250) at 0x8432b0 \& REFCNT = 1 \& FLAGS = (PADBUSY,PADMY,POK,pPOK,UTF8) \& PV = 0x731ac0 "abc\ende\e342\e202\e254fg"\e0 [UTF8 "abc\ende\ex{20ac}fg"] \& CUR = 11 \& LEN = 16 \& \& my %h = DDump "abc\ex{0a}de\ex{20ac}fg"; \& print DDumper \e%h; \& \& { CUR => \*(Aq11\*(Aq, \& FLAGS => { \& PADBUSY => 1, \& PADMY => 1, \& POK => 1, \& UTF8 => 1, \& pPOK => 1 \& }, \& LEN => \*(Aq16\*(Aq, \& PV => \*(Aq0x731ac0 "abc\e\ende\e\e342\e\e202\e\e254fg"\e\e0 [UTF8 "abc\e\ende\e\ex{20ac}fg"]\*(Aq, \& REFCNT => \*(Aq1\*(Aq, \& sv => \*(AqPV(0x723250) at 0x8432c0\*(Aq \& }; \& \& my %h = DDump { \& ape => 1, \& foo => "egg", \& bar => [ 2, "baz", undef ], \& }, 1; \& print DDumper \e%h; \& \& { FLAGS => { \& PADBUSY => 1, \& PADMY => 1, \& ROK => 1 \& }, \& REFCNT => \*(Aq1\*(Aq, \& RV => { \& PVIV("ape") => { \& FLAGS => { \& IOK => 1, \& PADBUSY => 1, \& PADMY => 1, \& pIOK => 1 \& }, \& IV => \*(Aq1\*(Aq, \& REFCNT => \*(Aq1\*(Aq, \& sv => \*(AqIV(0x747020) at 0x843a10\*(Aq \& }, \& PVIV("bar") => { \& CUR => \*(Aq0\*(Aq, \& FLAGS => { \& PADBUSY => 1, \& PADMY => 1, \& ROK => 1 \& }, \& IV => \*(Aq1\*(Aq, \& LEN => \*(Aq0\*(Aq, \& PV => \*(Aq0x720210 ""\*(Aq, \& REFCNT => \*(Aq1\*(Aq, \& RV => \*(Aq0x720210\*(Aq, \& sv => \*(AqPVIV(0x7223e0) at 0x843a10\*(Aq \& }, \& PVIV("foo") => { \& CUR => \*(Aq3\*(Aq, \& FLAGS => { \& PADBUSY => 1, \& PADMY => 1, \& POK => 1, \& pPOK => 1 \& }, \& IV => \*(Aq1\*(Aq, \& LEN => \*(Aq8\*(Aq, \& PV => \*(Aq0x7496c0 "egg"\e\e0\*(Aq, \& REFCNT => \*(Aq1\*(Aq, \& sv => \*(AqPVIV(0x7223e0) at 0x843a10\*(Aq \& } \& }, \& sv => \*(AqRV(0x79d058) at 0x843310\*(Aq \& }; .Ve .ie n .SS "DDump_IO ($io, $var [, $dig_level])" .el .SS "DDump_IO ($io, \f(CW$var\fP [, \f(CW$dig_level\fP])" .IX Subsection "DDump_IO ($io, $var [, $dig_level])" A wrapper function around perl's internal \f(CW\*(C`Perl_do_sv_dump\*(C'\fR, which makes \f(CW\*(C`Devel::Peek\*(C'\fR completely superfluous. .PP Example .PP .Vb 5 \& my $dump; \& open my $eh, ">", \e$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 .Ve .SH "INTERNALS" .IX Header "INTERNALS" \&\f(CW\*(C`DDump\*(C'\fR uses an \s-1XS\s0 wrapper around \f(CW\*(C`Perl_sv_dump\*(C'\fR where the \s-1STDERR\s0 is temporarily caught to a pipe. The internal \s-1XS\s0 helper functions are not meant for user space .SS "DDump_XS (\s-1SV\s0 *sv)" .IX Subsection "DDump_XS (SV *sv)" Base interface to internals for \f(CW\*(C`DDump\*(C'\fR. .SH "BUGS" .IX Header "BUGS" Windows and \s-1AIX\s0 might be using a build where not all symbols that were supposed to be exported in the public \s-1API\s0 are not. \f(CW\*(C`Perl_pv_peek\*(C'\fR is one of them. .PP Not all types of references are supported. .PP No idea how far back this goes in perl support, but Devel::PPPort has proven to be a big help. .SH "SEE ALSO" .IX Header "SEE ALSO" Devel::Peek, Data::Dumper, Data::Dump, Devel::Dumpvar, Data::Dump::Streamer, Data::Dumper::Perltidy, Perl::Tidy. .SH "AUTHOR" .IX Header "AUTHOR" H.Merijn Brand .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2008\-2018 H.Merijn Brand .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.