File Coverage

blib/lib/Acme/Hyperindex.pm
Criterion Covered Total %
statement 33 36 91.6
branch 10 14 71.4
condition 6 6 100.0
subroutine 7 7 100.0
pod 0 1 0.0
total 56 64 87.5


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package Acme::Hyperindex;
4              
5             =head1 NAME
6              
7             Acme::Hyperindex - Look deep into structures using a list of indexes
8              
9             =head1 SYNOPSIS
10              
11             use strict;
12             use Acme::Hyperindex;
13              
14             my @struct = (
15             { j_psi => [qw( eta_prime phi kaon )] },
16             { j_psi => [qw( selectron down tau_sneutrino )] },
17             { j_psi => [qw( upsilon gluino photino )] }
18             );
19              
20             print @struct[[ 2, 'j_psi', 1 ]], "\n"; ### Prints gluino
21             my $row = @struct[[ 1, 'j_psi' ]]; ### Row contains [qw( selectron down tau_sneutrino )]
22              
23             =head1 DESCRIPTION
24              
25             When you use dynamic datastructures,
26             the perl index syntax may not be felxible enough.
27             A little examle:
28              
29             my @struct = (
30             {
31             pion => [
32             [qw(strange j_psi positron)],
33             [qw(down_squark electron gluino)],
34             ],
35             w_plus_wino => [
36             [qw(neutralino tau kaon)],
37             [qw(charm_squark photino strange_squark)]
38             ],
39             },
40             );
41              
42             Now to get to the kaon particle, normally we use:
43              
44             my $particle = $struct[0]->{w_plus_wino}->[2];
45             -- or better --
46             my $particle = $struct[0]{w_plus_wino}[2];
47              
48             But what if you don't know how deep your datastructure is
49             at compile time? 'Course this is doable:
50              
51             my $particle = \@struct;
52             $particle = $particle->[$_] for qw(0 pion 2);
53              
54             Two problems here: Perl will tell you 'Not an ARRAY reference'
55             once we try to index in the hash on 'pion' with this array indexing syntax.
56             It's damn ugly and looks complicated.
57              
58             So Acme::Hyperindex lets you index arbitrary deep into data structures:
59              
60             my $particle = @struct[[ 0, 'pion', 2 ]];
61             -- or even --
62             my $particle = @struct[[ @indexes ]];
63             -- or --
64             my $particle = @struct[[ get_index() ]];
65             -- or --
66             my $particle = @struct[[ $particleindexes[[ 3, 42 ]] ]];
67              
68             Acme::Hyperindex now also lets you index on scalars, arrays and hashes:
69              
70             $struct[[ ... ]];
71             @struct[[ ... ]];
72             %struct[[ ... ]];
73              
74             And lists ary auto-derefed in list context:
75              
76             my $struct = [ [qw(a b c)], [qw(d e f)] ];
77              
78             my $foo = $struct[[ 0 ]]; # $foo contains a ref to qw(a b c)
79             my @foo = $struct[[ 0 ]]; # @foo contains qw(a b c)
80              
81             =cut
82              
83 2     2   62957 use strict;
  2         4  
  2         79  
84 2     2   213 use warnings;
  2         6  
  2         78  
85              
86 2     2   13 use base qw(Exporter);
  2         10  
  2         266  
87 2     2   11 use vars qw(@EXPORT $VERSION);
  2         4  
  2         142  
88              
89 2     2   11 use Carp qw(croak);
  2         4  
  2         167  
90 2     2   277093 use Filter::Simple;
  2         531882  
  2         16  
91              
92             @EXPORT = qw(hyperindex);
93              
94             $VERSION = 0.12;
95              
96             FILTER_ONLY
97             code => sub {
98             my $rx;
99             $rx = qr{
100             ([\$\@\%]) \s* (\w+) \s* \[\[
101             (
102             [^\[\]]*
103             (?: \[[^\[]
104             | \][^\]]
105             | (?{{ $rx }}) [^\[\]]*
106             )*
107             )\]\]
108             }x;
109             ### We need while for $a[[ $b[[ ]] ]] situations
110             1 while s/$rx/"hyperindex( ". ($1 eq '$' ? '' : '\\') ."$1$2, $3 )"/eg;
111             };
112              
113             sub hyperindex {
114 9     9 0 1605 my $structure = shift;
115 9         20 my @indexes = @_;
116              
117 9 50       31 if ( ref $structure eq 'SCALAR' ) {
118 0         0 $structure = $$structure;
119             }
120 9         10 my $item = $structure;
121 9         18 for my $index ( @indexes ) {
122 25 100       68 if ( ref $item eq 'HASH' ) {
    50          
123 3         7 $item = $item->{$index};
124             }
125             elsif ( ref $item eq 'ARRAY' ) {
126 22         46 $item = $item->[$index];
127             }
128             else {
129 0 0       0 ref($item) or croak "Hyperindexing on '$index', but datastructure is at maximum depth";
130 0         0 die "Hmm, error in hyperindexing: index => $index item => $item";
131             }
132             }
133              
134 9 100       22 if ( ref $item ) {
135 5 100 100     62 if ( ref($item) eq 'ARRAY' and wantarray ) {
136 2         3 return @{$item};
  2         17  
137             }
138 3 100 100     17 if ( ref($item) eq 'HASH' and wantarray ) {
139 1         14 return %$item;
140             }
141             }
142              
143 6         42 return $item;
144             }
145              
146             =head1 BUGS
147              
148             Perl code is hard to parse, and there are surely
149             situations where my parsing fails to do the right
150             thing.
151              
152             =head1 TODO
153              
154             =over 4
155              
156             =item * make the sourcefilter optionally
157              
158             =item * Scalar references within the datasructure..
159              
160             my $struct = [ \[qw(a b c)] ];
161              
162             There should be some way to get to 'a'
163              
164             =item * Generate nonexisting references optionally
165              
166             When you try to index deeper than the data structure is:
167              
168             my $struct = [];
169             $struct[[ 0, 'foo', 42 ]];
170              
171             =back
172              
173             =head1 AUTHOR
174              
175             Berik Visschers
176              
177             =head1 COPYRIGHT
178              
179             Copyright 2005 by Berik Visschers Eberikv@xs4all.nlE.
180              
181             This program is free software; you can redistribute it and/or
182             modify it under the same terms as Perl itself.
183              
184             See F
185              
186             =cut
187              
188             1