I think this is more along the lines of what i should have (but i still don't have it working):
On Sun, Nov 10, 2013 at 6:10 PM, shawn wilson <ag4ve...@gmail.com> wrote: > I'm having a bit of trouble writing a trace array for a structure > traversal function. > > Before someone points out Data::Walker and the like, here is my > limitation: this is for a script to generate iptables / ipset save > files - it needs to run on machines with perl 5.10+ without needing > anything else (including MakeMaker - nothing - just runs out of the > box). So, if a module isn't in core, I can't really use it. > > Nevermind the function name 'flatten' - I just want to get $path to > work correctly. > > Thanks > > > #!/usr/bin/env perl > > use strict; > use warnings; > > use Data::Dumper; > > my $deep = { > 'foo' => [qw/ > ugh > umm > arr > /], > 'bar' => [qw/ > aaa > bbb > ccc > /], > 'baz' => [ > 'fi' => [qw/ > one > two > three > /], > 'fo' => [qw/ > four > five > six > /], > 'fum' => [qw/ > seven > eight > nine > /], > ], > }; > > my ($new) = into_me($deep, undef, 'flatten_els'); > > print Dumper($new); > > sub flatten_els > { > my ($var, @etc) = @_; > my ($path, $type) = @etc; > > print "path [" . join('] [', @$path) . "]\n"; > > return $var, @etc unless ($type =~ /^H /); > > $var = join(' ', values %$var); > > return $var, @etc; > } > > > > # Traverse a variable with callbacks > sub into_me > { > my ($vals, $kfunc, $vfunc, @etc) = @_; > no strict 'refs'; > > # This should be private - you probably shouldn't call into_me with a path > my $path; > if (scalar(@etc) >= 1 and ref($etc[-1]) eq 'ARRAY' and $etc[-1]->[0] > eq 'BASE') > { > $path = pop @etc; > } > else > { > push @$path, 'BASE'; > } > > my $rtype = (ref(\$vals) eq 'SCALAR' ? 'SCALAR' : ref($vals)); > > my $ret; > > if ($rtype eq 'ARRAY') > { push @$path, 'A '; for my $num (0 .. $#$vals) { next unless (defined($vals->[$num])); my $val = $vals->[$num]; my ($anum, $aval); ($anum, @etc) = $kfunc->($num, @etc, 'EL') if (defined($kfunc)); $anum //= $num; $path->[-1] =~ s/^A .*/A $anum/; push @etc, $path; ($aval, @etc) = $vfunc->($val, @etc, 'VAL') if (defined($vfunc)); $aval //= $val; ($ret->[$anum], @etc) = into_me($aval, $kfunc, $vfunc, @etc); > } > } > elsif ($rtype eq 'HASH') > { push @$path, 'H '; foreach my $key (keys %$vals) { next unless (defined($vals->{$key})); my $val = $vals->{$key}; my ($akey, $aval); ($akey, @etc) = $kfunc->($key, @etc, 'KEY') if (defined($kfunc)); $akey //= $key; $path->[-1] =~ s/^H .*/H $akey/; push @etc, $path; ($aval, @etc) = $vfunc->($val, @etc, 'VAL') if (defined($vfunc)); $aval //= $val; ($ret->{$akey}, @etc) = into_me($aval, $kfunc, $vfunc, @etc); > } > } > elsif ($rtype eq 'SCALAR') > { > push @$path, "S $vals"; > push @etc, $path; > ($ret, @etc) = $vfunc->($vals, @etc); > pop @$path; > } > else > { > $ret = $vals; > } > pop @$path; > push @etc, $path; > > use strict 'refs'; > return $ret, @etc; > } -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/