File Coverage

blib/lib/Data/Peek.pm
Criterion Covered Total %
statement 110 132 83.3
branch 29 50 58.0
condition 17 30 56.6
subroutine 17 18 94.4
pod 5 5 100.0
total 178 235 75.7


line stmt bran cond sub pod time code
1             package Data::Peek;
2              
3 12     12   1297046 use strict;
  12         37  
  12         420  
4 12     12   85 use warnings;
  12         32  
  12         551  
5              
6 12     12   87 use DynaLoader ();
  12         28  
  12         354  
7              
8 12     12   77 use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK );
  12         30  
  12         1984  
9             $VERSION = "0.47";
10             @ISA = qw( DynaLoader Exporter );
11             @EXPORT = qw( DDumper DTidy DDsort DPeek DDisplay DDump DHexDump
12             DDual DGrow );
13             @EXPORT_OK = qw( triplevar :tidy );
14             push @EXPORT, "DDump_IO";
15              
16             bootstrap Data::Peek $VERSION;
17              
18             our $has_perlio;
19             our $has_perltidy;
20              
21             BEGIN {
22 12     12   99 use Config;
  12         35  
  12         1011  
23 12   50 12   1103 $has_perlio = ($Config{useperlio} || "undef") eq "define";
24 12     12   931 $has_perltidy = eval q{use Perl::Tidy; $Perl::Tidy::VERSION};
  12         43565  
  12         2500663  
  12         1519  
25             }
26              
27             ### ############# DDumper () ##################################################
28              
29 12     12   9274 use Data::Dumper;
  12         82746  
  12         19447  
30              
31             my %sk = (
32             undef => 0,
33             "" => 0,
34             0 => 0,
35             1 => 1,
36              
37             V => sub { # Sort by value
38             my $r = shift;
39             [ sort { $r->{$a} cmp $r->{$b} } keys %$r ];
40             },
41             VN => sub { # Sort by value numeric
42             my $r = shift;
43             [ sort { $r->{$a} <=> $r->{$b} } keys %$r ];
44             },
45             VNR => sub { # Sort by value numeric reverse
46             my $r = shift;
47             [ sort { $r->{$b} <=> $r->{$a} } keys %$r ];
48             },
49             VR => sub { # Sort by value reverse
50             my $r = shift;
51             [ sort { $r->{$b} cmp $r->{$a} } keys %$r ];
52             },
53             R => sub { # Sort reverse
54             my $r = shift;
55             [ reverse sort keys %$r ];
56             },
57             );
58             my $_sortkeys = 1;
59             our $_perltidy = 0;
60              
61             sub DDsort
62             {
63 6 50   6 1 17 @_ or return;
64              
65 6 50       34 $_sortkeys = exists $sk{$_[0]} ? $sk{$_[0]} : $_[0];
66             } # DDsort
67              
68             sub import
69             {
70 12     12   145 my @exp = @_;
71 12         32 my @etl;
72 12         39 foreach my $p (@exp) {
73 18 50       85 exists $sk{$p} and DDsort ($p), next;
74              
75 18 100       93 if ($p eq ":tidy") {
76 1         3 $_perltidy = $has_perltidy;
77 1         4 next;
78             }
79              
80 17         61 push @etl, $p;
81             }
82 12         23833 __PACKAGE__->export_to_level (1, @etl);
83             } # import
84              
85             sub DDumper
86             {
87 37 100   37 1 19448 $_perltidy and goto \&DTidy;
88              
89 22         39 local $Data::Dumper::Sortkeys = $_sortkeys;
90 22         32 local $Data::Dumper::Indent = 1;
91 22         36 local $Data::Dumper::Quotekeys = 0;
92 22         26 local $Data::Dumper::Deparse = 1;
93 22         31 local $Data::Dumper::Terse = 1;
94 22         31 local $Data::Dumper::Useqq = 0; # I want unicode visible
95              
96 22         66 my $s = Data::Dumper::Dumper @_;
97 22         958 $s =~ s/^(\s*)(.*?)\s*=>/sprintf "%s%-16s =>", $1, $2/gme; # Align =>
  26         114  
98 22 50       58 $s =~ s/\bbless\s*\(\s*/bless (/gm and $s =~ s/\s+\)([;,])$/)$1/gm;
99 22         100 $s =~ s/^(?=\s*[]}](?:[;,]|$))/ /gm;
100 22         118 $s =~ s/^(\s*[{[]) *\n *(?=\S)(?![{[])/$1 /gm;
101 22         142 $s =~ s/^(\s+)/$1$1/gm;
102              
103 22 50       74 defined wantarray or warn $s;
104 22         131 return $s;
105             } # DDumper
106              
107             sub DTidy
108             {
109 15 50   15 1 73 $has_perltidy or goto \&DDumper;
110              
111 15         54 local $Data::Dumper::Sortkeys = $_sortkeys;
112 15         42 local $Data::Dumper::Indent = 1;
113 15         38 local $Data::Dumper::Quotekeys = 1;
114 15         36 local $Data::Dumper::Deparse = 1;
115 15         34 local $Data::Dumper::Terse = 1;
116 15         47 local $Data::Dumper::Useqq = 0;
117              
118 15         105 my $s = Data::Dumper::Dumper @_;
119 15         1448 my $t;
120 15         65 my @opts = (
121             # Disable stupid options in ~/.perltidyrc
122             # people do so, even for root
123             "--no-backup-and-modify-in-place",
124             "--no-check-syntax",
125             "--no-standard-output",
126             "--no-warning-output",
127             );
128             # RT#99514 - Perl::Tidy memoizes .perltidyrc incorrectly
129 15 50       71 $has_perltidy > 20120714 and push @opts, "--no-memoize";
130              
131 15         116 Perl::Tidy::perltidy (source => \$s, destination => \$t, argv => \@opts);
132 15         1789455 $s = $t;
133              
134 15 50       135 defined wantarray or warn $s;
135 15         252 return $s;
136             } # DTidy
137              
138             ### ############# DDump () ####################################################
139              
140             sub _DDump_ref
141             {
142 0     0   0 my (undef, $down) = (@_, 0);
143              
144 0         0 my $ref = ref $_[0];
145 0 0 0     0 if ($ref eq "SCALAR" || $ref eq "REF") {
146 0         0 my %hash = DDump (${$_[0]}, $down);
  0         0  
147 0         0 return { %hash };
148             }
149 0 0       0 if ($ref eq "ARRAY") {
150 0         0 my @list;
151 0         0 foreach my $list (@{$_[0]}) {
  0         0  
152 0         0 my %hash = DDump ($list, $down);
153 0         0 push @list, { %hash };
154             }
155 0         0 return [ @list ];
156             }
157 0 0       0 if ($ref eq "HASH") {
158 0         0 my %hash;
159 0         0 foreach my $key (sort keys %{$_[0]}) {
  0         0  
160 0         0 $hash{DPeek ($key)} = { DDump ($_[0]->{$key}, $down) };
161             }
162 0         0 return { %hash };
163             }
164 0         0 undef;
165             } # _DDump_ref
166              
167             sub _DDump
168             {
169 7     7   25 my (undef, $down, $dump, $fh) = (@_, "");
170              
171 7 100 66 1   117 if ($has_perlio and open $fh, ">", \$dump) {
  1         12  
  1         3  
  1         10  
172             #print STDERR "Using DDump_IO\n";
173 3         1278 DDump_IO ($fh, $_[0], $down);
174 3         16 close $fh;
175             }
176             else {
177             #print STDERR "Using DDump_XS\n";
178 4         170 $dump = DDump_XS ($_[0]);
179             }
180              
181 7         89 return $dump;
182             } # _DDump
183              
184             sub DDump ($;$)
185             {
186 7     7 1 11023 my (undef, $down) = (@_, 0);
187 7 50 66     51 my @dump = split m/[\r\n]+/, _DDump ($_[0], wantarray || $down) or return;
188              
189 7 100       28 if (wantarray) {
190 3         9 my %hash;
191 3         29 ($hash{sv} = $dump[0]) =~ s/^SV\s*=\s*//;
192 3   66     117 m/^\s+(\w+)\s*=\s*(.*)/ and $hash{$1} = $2 for @dump;
193              
194 3 50       17 if (exists $hash{FLAGS}) {
195 3         14 $hash{FLAGS} =~ tr/()//d;
196 3         33 $hash{FLAGS} = { map { $_ => 1 } split m/,/ => $hash{FLAGS} };
  7         32  
197             }
198              
199             $down && ref $_[0] and
200 3 50 0     17 $hash{RV} = _DDump_ref ($_[0], $down - 1) || $_[0];
      33        
201 3         45 return %hash;
202             }
203              
204 4         15 my $dump = join "\n", @dump, "";
205              
206 4 50       15 defined wantarray and return $dump;
207              
208 0         0 warn $dump;
209             } # DDump
210              
211             sub DHexDump
212             {
213 12     12   161 use bytes;
  12         39  
  12         76  
214 6     6 1 3400 my $off = 0;
215 6         16 my @out;
216 6 50       23 my $var = @_ ? $_[0] : $_;
217 6 100       31 defined $var or return;
218 5 100 66     34 my $fmt = @_ > 1 && $_[1] < length ($var) ? "A$_[1]" : "A*";
219 5         30 my $str = pack $fmt, $var; # force stringification
220 5         39 for (unpack "(A32)*", unpack "H*", $str) {
221 5         34 my @b = unpack "(A2)*", $_;
222 5         38 my $out = sprintf "%04x ", $off;
223 5   100     71 $out .= " ".($b[$_]||" ") for 0 .. 7;
224 5         14 $out .= " ";
225 5   100     75 $out .= " ".($b[$_]||" ") for 8 .. 15;
226 5         15 $out .= " ";
227 5 100 100     16 $out .= ($_ < 0x20 || $_ >= 0x7f ? "." : chr $_) for map { hex $_ } @b;
  45         191  
228 5         26 push @out, $out."\n";
229 5         19 $off += 16;
230             }
231              
232 5 50       20 wantarray and return @out;
233              
234 5 50       53 defined wantarray and return join "", @out;
235              
236 0         0 warn join "", @out;
237             } # DHexDump
238              
239             "Indent";
240              
241             __END__
242              
243             =head1 NAME
244              
245             Data::Peek - A collection of low-level debug facilities
246              
247             =head1 SYNOPSIS
248              
249             use Data::Peek;
250              
251             print DDumper \%hash; # Same syntax as Data::Dumper
252             DTidy { ref => $ref };
253              
254             print DPeek \$var;
255             my ($pv, $iv, $nv, $rv, $magic) = DDual ($var [, 1]);
256             print DPeek for DDual ($!, 1);
257             print DDisplay ("ab\nc\x{20ac}\rdef\n");
258             print DHexDump ("ab\nc\x{20ac}\rdef\n");
259              
260             my $dump = DDump $var;
261             my %hash = DDump \@list;
262             DDump \%hash;
263              
264             my %hash = DDump (\%hash, 5); # dig 5 levels deep
265              
266             my $dump;
267             open my $fh, ">", \$dump;
268             DDump_IO ($fh, \%hash, 6);
269             close $fh;
270             print $dump;
271              
272             # Imports
273             use Data::Peek qw( :tidy VNR DGrow triplevar );
274             my $x = ""; DGrow ($x, 10000);
275             my $tv = triplevar ("\N{GREEK SMALL LETTER PI}", 3, "3.1415");
276             DDsort ("R");
277             DDumper [ $x ]; # use of :tidy make DDumper behave as DTidy
278              
279             =head1 DESCRIPTION
280              
281             Data::Peek started off as C<DDumper> being a wrapper module over
282             L<Data::Dumper>, but grew out to be a set of low-level data
283             introspection utilities that no other module provided yet, using the
284             lowest level of the perl internals API as possible.
285              
286             =head2 DDumper ($var, ...)
287              
288             Not liking the default output of Data::Dumper, and always feeling the need
289             to set C<$Data::Dumper::Sortkeys = 1;>, and not liking any of the default
290             layouts, this function is just a wrapper around Data::Dumper::Dumper with
291             everything set as I like it.
292              
293             $Data::Dumper::Sortkeys = 1;
294             $Data::Dumper::Indent = 1;
295              
296             If C<Data::Peek> is C<use>d with import argument C<:tidy>, the result is
297             formatted according to L<Perl::Tidy>, see L<DTidy> below, otherwise the
298             result is further beautified to meet my needs:
299              
300             * quotation of hash keys has been removed (with the disadvantage
301             that the output might not be parseable again).
302             * arrows for hashes are aligned at 16 (longer keys don't align)
303             * closing braces and brackets are now correctly aligned
304              
305             In void context, C<DDumper ()> warn ()'s.
306              
307             Example
308              
309             $ perl -MDP \
310             -e'DDumper { ape => 1, foo => "egg", bar => [ 2, "baz", undef ]};'
311              
312             { ape => 1,
313             bar => [
314             2,
315             'baz',
316             undef
317             ],
318             foo => 'egg'
319             };
320              
321             =head2 DTidy ($var, ...)
322              
323             C<DTidy> is an alternative to C<DDumper>, where the output of C<DDumper>
324             is formatted using C<Perl::Tidy> (if available) according to your
325             C<.perltidyrc> instead of the default behavior, maybe somewhat like (YMMV):
326              
327             $ perl -MDP=:tidy \
328             -we'DDumper { ape => 1, foo => "egg", bar => [ 2, "baz", undef ]};'
329             { 'ape' => 1,
330             'bar' => [2, 'baz', undef],
331             'foo' => 'egg'
332             }
333              
334             If C<Data::Peek> is C<use>d with import argument C<:tidy>, this is the
335             default output method for C<DDumper>.
336              
337             If L<Perl::Tidy> is not available, C<DTidy> will fallback to C<DDumper>.
338              
339             This idea was shamelessly copied from John McNamara's L<Data::Dumper::Perltidy>.
340              
341             =head2 DDsort ( 0 | 1 | R | V | VR | VN | VNR )
342              
343             Set the hash sort algorithm for DDumper. The default is to sort by key value.
344              
345             0 - Do not sort
346             1 - Sort by key
347             R - Reverse sort by key
348             V - Sort by value
349             VR - Reverse sort by value
350             VN - Sort by value numerical
351             VNR - Reverse sort by value numerical
352              
353             These can also be passed to import:
354              
355             $ perl -MDP=VNR \
356             -we'DDumper { foo => 1, bar => 2, zap => 3, gum => 13 }'
357             { gum => 13,
358             zap => 3,
359             bar => 2,
360             foo => 1
361             };
362             $ perl -MDP=V \
363             -we'DDumper { foo => 1, bar => 2, zap => 3, gum => 13 }'
364             { foo => 1,
365             gum => 13,
366             bar => 2,
367             zap => 3
368             };
369              
370             =head2 DPeek
371              
372             =head2 DPeek ($var)
373              
374             Playing with C<sv_dump ()>, I found C<Perl_sv_peek ()>, and it might be
375             very useful for simple checks. If C<$var> is omitted, uses $_.
376              
377             Example
378              
379             print DPeek "abc\x{0a}de\x{20ac}fg";
380              
381             PV("abc\nde\342\202\254fg"\0) [UTF8 "abc\nde\x{20ac}fg"]
382              
383             In void context, C<DPeek ()> prints to C<STDERR> plus a newline.
384              
385             =head2 DDisplay
386              
387             =head2 DDisplay ($var)
388              
389             Show the PV content of a scalar the way perl debugging would have done.
390             UTF-8 detection is on, so this is effectively the same as returning the
391             first part the C<DPeek ()> returns for non-UTF8 PV's or the second part
392             for UTF-8 PV's. C<DDisplay ()> returns the empty string for scalars that
393             no have a valid PV.
394              
395             Example
396              
397             print DDisplay "abc\x{0a}de\x{20ac}fg";
398              
399             "abc\nde\x{20ac}fg"
400              
401             In void context, C<DDisplay ()> uses C<warn> to display the result.
402              
403             =head2 DHexDump
404              
405             =head2 DHexDump ($var)
406              
407             =head2 DHexDump ($var, $length)
408              
409             Show the (stringified) content of a scalar as a hex-dump. If C<$var>
410             is omitted, C<$_> is dumped. Returns C<undef> or an empty list if
411             C<$var> (or C<$_>) is undefined. If C<$length> is given and is lower than
412             the length of the stringified C<$var>, only <$length> bytes are dumped.
413              
414             In void context, the dump is done to STDERR. In scalar context, the
415             complete dump is returned as a single string. In list context, the dump
416             is returned as lines.
417              
418             Example
419              
420             print DHexDump "abc\x{0a}de\x{20ac}fg";
421              
422             0000 61 62 63 0a 64 65 e2 82 ac 66 67 abc.de...fg
423              
424             =head2 my ($pv, $iv, $nv, $rv, $hm) = DDual ($var [, $getmagic])
425              
426             DDual will return the basic elements in a variable, guaranteeing that no
427             conversion takes place. This is very useful for dual-var variables, or
428             when checking is a variable has defined entries for a certain type of
429             scalar. For each String (PV), Integer (IV), Double (NV), and Reference (RV),
430             the current value of C<$var> is returned or undef if it is not set (yet).
431             The 5th element is an indicator if C<$var> has magic, which is B<not> invoked
432             in the returned values, unless explicitly asked for with a true optional
433             second argument.
434              
435             Example
436              
437             print DPeek for DDual ($!, 1);
438              
439             In void context, DDual does the equivalent of
440              
441             { my @d = DDual ($!, 1);
442             print STDERR
443             DPeek ($!), "\n",
444             " PV: ", DPeek ($d[0]), "\n",
445             " IV: ", DPeek ($d[1]), "\n",
446             " NV: ", DPeek ($d[2]), "\n",
447             " RV: ", DPeek ($d[3]), "\n";
448             }
449            
450             =head2 my $len = DGrow ($pv, $size)
451              
452             Fastest way to preallocate space for a PV scalar. Returns the allocated
453             length. If $size is smaller than the already allocated space, it will
454             not shrink.
455              
456             cmpthese (-2, {
457             pack => q{my $x = ""; $x = pack "x20000"; $x = "";},
458             op_x => q{my $x = ""; $x = "x" x 20000; $x = "";},
459             grow => q{my $x = ""; DGrow ($x, 20000); $x = "";},
460             });
461              
462             Rate op_x pack grow 5.8.9 5.10.1 5.12.4 5.14.2
463             op_x 62127/s -- -59% -96% 118606/s 119730/s 352255/s 362605/s
464             pack 152046/s 145% -- -91% 380075/s 355666/s 347247/s 387349/s
465             grow 1622943/s 2512% 967% -- 2818380/s 2918783/s 2672340/s 2886787/s
466              
467             =head2 my $tp = triplevar ($pv, $iv, $nv)
468              
469             When making C<DDual ()> I wondered if it were possible to create triple-val
470             scalar variables. L<Scalar::Util> already gives us C<dualvar ()>, that creates
471             you a scalar with different numeric and string values that return different
472             values in different context. Not that C<triplevar ()> would be very useful,
473             compared to C<dualvar ()>, but at least this shows that it is possible.
474              
475             C<triplevar ()> is not exported by default.
476              
477             Example:
478              
479             print DPeek for DDual
480             Data::Peek::triplevar ("\N{GREEK SMALL LETTER PI}", 3, 3.1415);
481              
482             PV("\317\200"\0) [UTF8 "\x{3c0}"]
483             IV(3)
484             NV(3.1415)
485             SV_UNDEF
486             IV(0)
487              
488             =head2 DDump ($var [, $dig_level])
489              
490             A very useful module when debugging is C<Devel::Peek>, but is has one big
491             disadvantage: it only prints to STDERR, which is not very handy when your
492             code wants to inspect variables at a low level.
493              
494             Perl itself has C<sv_dump ()>, which does something similar, but still
495             prints to STDERR, and only one level deep.
496              
497             C<DDump ()> is an attempt to make the innards available to the script level
498             with a reasonable level of compatibility. C<DDump ()> is context sensitive.
499              
500             In void context, it behaves exactly like C<Perl_sv_dump ()>.
501              
502             In scalar context, it returns what C<Perl_sv_dump ()> would have printed.
503              
504             In list context, it returns a hash of the variable's properties. In this mode
505             you can pass an optional second argument that determines the depth of digging.
506              
507             Example
508              
509             print scalar DDump "abc\x{0a}de\x{20ac}fg"
510              
511             SV = PV(0x723250) at 0x8432b0
512             REFCNT = 1
513             FLAGS = (PADBUSY,PADMY,POK,pPOK,UTF8)
514             PV = 0x731ac0 "abc\nde\342\202\254fg"\0 [UTF8 "abc\nde\x{20ac}fg"]
515             CUR = 11
516             LEN = 16
517              
518             my %h = DDump "abc\x{0a}de\x{20ac}fg";
519             print DDumper \%h;
520              
521             { CUR => '11',
522             FLAGS => {
523             PADBUSY => 1,
524             PADMY => 1,
525             POK => 1,
526             UTF8 => 1,
527             pPOK => 1
528             },
529             LEN => '16',
530             PV => '0x731ac0 "abc\\nde\\342\\202\\254fg"\\0 [UTF8 "abc\\nde\\x{20ac}fg"]',
531             REFCNT => '1',
532             sv => 'PV(0x723250) at 0x8432c0'
533             };
534              
535             my %h = DDump {
536             ape => 1,
537             foo => "egg",
538             bar => [ 2, "baz", undef ],
539             }, 1;
540             print DDumper \%h;
541              
542             { FLAGS => {
543             PADBUSY => 1,
544             PADMY => 1,
545             ROK => 1
546             },
547             REFCNT => '1',
548             RV => {
549             PVIV("ape") => {
550             FLAGS => {
551             IOK => 1,
552             PADBUSY => 1,
553             PADMY => 1,
554             pIOK => 1
555             },
556             IV => '1',
557             REFCNT => '1',
558             sv => 'IV(0x747020) at 0x843a10'
559             },
560             PVIV("bar") => {
561             CUR => '0',
562             FLAGS => {
563             PADBUSY => 1,
564             PADMY => 1,
565             ROK => 1
566             },
567             IV => '1',
568             LEN => '0',
569             PV => '0x720210 ""',
570             REFCNT => '1',
571             RV => '0x720210',
572             sv => 'PVIV(0x7223e0) at 0x843a10'
573             },
574             PVIV("foo") => {
575             CUR => '3',
576             FLAGS => {
577             PADBUSY => 1,
578             PADMY => 1,
579             POK => 1,
580             pPOK => 1
581             },
582             IV => '1',
583             LEN => '8',
584             PV => '0x7496c0 "egg"\\0',
585             REFCNT => '1',
586             sv => 'PVIV(0x7223e0) at 0x843a10'
587             }
588             },
589             sv => 'RV(0x79d058) at 0x843310'
590             };
591              
592             =head2 DDump_IO ($io, $var [, $dig_level])
593              
594             A wrapper function around perl's internal C<Perl_do_sv_dump ()>, which
595             makes C<Devel::Peek> completely superfluous.
596              
597             Example
598              
599             my $dump;
600             open my $eh, ">", \$dump;
601             DDump_IO ($eh, { 3 => 4, ape => [5..8]}, 6);
602             close $eh;
603             print $dump;
604              
605             SV = RV(0x79d9e0) at 0x843f00
606             REFCNT = 1
607             FLAGS = (TEMP,ROK)
608             RV = 0x741090
609             SV = PVHV(0x79c948) at 0x741090
610             REFCNT = 1
611             FLAGS = (SHAREKEYS)
612             IV = 2
613             NV = 0
614             ARRAY = 0x748ff0 (0:7, 2:1)
615             hash quality = 62.5%
616             KEYS = 2
617             FILL = 1
618             MAX = 7
619             RITER = -1
620             EITER = 0x0
621             Elt "ape" HASH = 0x97623e03
622             SV = RV(0x79d9d8) at 0x8440e0
623             REFCNT = 1
624             FLAGS = (ROK)
625             RV = 0x741470
626             SV = PVAV(0x7264b0) at 0x741470
627             REFCNT = 2
628             FLAGS = ()
629             IV = 0
630             NV = 0
631             ARRAY = 0x822f70
632             FILL = 3
633             MAX = 3
634             ARYLEN = 0x0
635             FLAGS = (REAL)
636             Elt No. 0
637             SV = IV(0x7467c8) at 0x7c1aa0
638             REFCNT = 1
639             FLAGS = (IOK,pIOK)
640             IV = 5
641             Elt No. 1
642             SV = IV(0x7467b0) at 0x8440f0
643             REFCNT = 1
644             FLAGS = (IOK,pIOK)
645             IV = 6
646             Elt No. 2
647             SV = IV(0x746810) at 0x75be00
648             REFCNT = 1
649             FLAGS = (IOK,pIOK)
650             IV = 7
651             Elt No. 3
652             SV = IV(0x746d38) at 0x7799d0
653             REFCNT = 1
654             FLAGS = (IOK,pIOK)
655             IV = 8
656             Elt "3" HASH = 0xa400c7f3
657             SV = IV(0x746fd0) at 0x7200e0
658             REFCNT = 1
659             FLAGS = (IOK,pIOK)
660             IV = 4
661              
662             =head1 INTERNALS
663              
664             C<DDump ()> uses an XS wrapper around C<Perl_sv_dump ()> where the
665             STDERR is temporarily caught to a pipe. The internal XS helper functions
666             are not meant for user space
667              
668             =head2 DDump_XS (SV *sv)
669              
670             Base interface to internals for C<DDump ()>.
671              
672             =head1 BUGS
673              
674             Windows and AIX might be using a build where not all symbols that were
675             supposed to be exported in the public API are not. Perl_pv_peek () is
676             one of them.
677              
678             Not all types of references are supported.
679              
680             No idea how far back this goes in perl support, but Devel::PPPort has
681             proven to be a big help.
682              
683             =head1 SEE ALSO
684              
685             L<Devel::Peek>, L<Data::Dumper>, L<Data::Dump>, L<Devel::Dumpvar>,
686             L<Data::Dump::Streamer>, L<Data::Dumper::Perltidy>, L<Perl::Tidy>.
687              
688             =head1 AUTHOR
689              
690             H.Merijn Brand <h.m.brand@xs4all.nl>
691              
692             =head1 COPYRIGHT AND LICENSE
693              
694             Copyright (C) 2008-2017 H.Merijn Brand
695              
696             This library is free software; you can redistribute it and/or modify
697             it under the same terms as Perl itself.
698              
699             =cut