File Coverage

blib/lib/Data/Traverse.pm
Criterion Covered Total %
statement 48 48 100.0
branch 11 12 91.6
condition n/a
subroutine 10 10 100.0
pod 0 3 0.0
total 69 73 94.5


line stmt bran cond sub pod time code
1             package Data::Traverse;
2              
3 1     1   38124 use strict;
  1         3  
  1         39  
4 1     1   6 use warnings;
  1         3  
  1         31  
5              
6 1     1   6 use Exporter;
  1         6  
  1         46  
7 1     1   5 use Carp qw(croak);
  1         1  
  1         86  
8 1     1   6 use Scalar::Util qw(reftype);
  1         2  
  1         329  
9              
10             our @ISA = qw(Exporter);
11              
12             # Items to export into callers namespace by default. Note: do not export
13             # names by default without a very good reason. Use EXPORT_OK instead.
14             # Do not simply export all your public functions/methods/constants.
15             our @EXPORT_OK = ('&traverse');
16              
17              
18             our $VERSION = '0.03';
19              
20             my $IGNORE_BAD_REFS = 0;
21              
22             sub ignore_unsupported_refs {
23 1     1 0 530 my $class = shift;
24 1         5 $IGNORE_BAD_REFS = shift;
25             }
26              
27             # Preloaded methods go here.
28              
29             # Use this sub to do the prototype only. The real fun
30             # happens in real_traverse.
31             sub traverse(&$) {
32 4     4 0 1344 my ( $callback, $ref ) = @_;
33 4 50       19 my $type = reftype $ref or
34             croak "Second argument to traverse must be a reference";
35              
36 4         16 real_traverse( $callback, $ref, $type, caller );
37             }
38              
39              
40             sub real_traverse {
41 16     16 0 25 my ( $callback, $ref, $type, $caller ) = @_;
42              
43 1     1   6 no strict 'refs';
  1         1  
  1         299  
44 16         18 local(*{$caller."::a"}) = \my $a;
  16         45  
45 16         19 local(*{$caller."::b"}) = \my $b;
  16         36  
46 1     1   6 use strict 'refs';
  1         2  
  1         238  
47              
48 16 100       37 if ( $type eq 'ARRAY' ) {
    100          
49 8         14 foreach my $item( @$ref ) {
50 23         73 $_ = $type;
51 23         43 my $st = reftype( $item );
52 23 100       33 if( $st ) {
53 11         38 real_traverse( $callback, $item, $st, $caller );
54             } else {
55 12         13 $a = $item;
56 12         24 $callback->();
57             }
58             }
59             } elsif ( $type eq 'HASH' ) {
60 6         24 while( my ( $key, $val ) = each %$ref ) {
61 8         19 $_ = $type;
62 8         13 my $st = reftype( $val );
63 8 100       35 if( $st ) {
64 1         4 real_traverse( $callback, $val, $st, $caller );
65             } else {
66 7         8 $a = $key;
67 7         6 $b = $val;
68 7         14 $callback->();
69             }
70             }
71             } else {
72 2 100       320 croak "Encountered unsupported type $type in traverse"
73             unless $IGNORE_BAD_REFS;
74             }
75             }
76              
77              
78             1;
79             __END__