diff options
Diffstat (limited to 'lib/Config/Tree/Node/Section.pm')
-rw-r--r-- | lib/Config/Tree/Node/Section.pm | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/Config/Tree/Node/Section.pm b/lib/Config/Tree/Node/Section.pm index 8fec46b..25b1bd5 100644 --- a/lib/Config/Tree/Node/Section.pm +++ b/lib/Config/Tree/Node/Section.pm @@ -57,6 +57,61 @@ sub merge { } } +=head2 $h = $cfg->as_hash + +=head2 $h = $cfg->as_hash($map) + +Returns parse tree converted to a hash reference. If B<$map> is supplied, +it must be a reference to a function. For each I<$key>/I<$value> +pair, this function will be called as: + + ($newkey, $newvalue) = &{$map}($what, $key, $value) + +where B<$what> is C<section> or C<value>, depending on the type of the +hash entry being processed. Upon successful return, B<$newvalue> will be +inserted in the hash slot for the key B<$newkey>. + +If B<$what> is C<section>, B<$value> is always a reference to an empty +hash (since the parse tree is traversed in pre-order fashion). In that +case, the B<$map> function is supposed to do whatever initialization that +is necessary for the new subtree and return as B<$newvalue> either B<$value> +itself, or a reference to a hash available inside the B<$value>. For +example: + + sub map { + my ($what, $name, $val) = @_; + if ($name eq 'section') { + $val->{section} = {}; + $val = $val->{section}; + } + ($name, $val); + } + +=cut + +sub as_hash { + my $self = shift; + my $map = shift // sub { shift; @_ }; + my $hroot = {}; + my @ar; + + push @ar, [ '', $self, $hroot ]; + while (my $elt = shift @ar) { + if ($elt->[1]->is_section) { + my $hr0 = {}; + my ($name, $hr) = &{$map}('section', $elt->[0], $hr0); + $elt->[2]{$name} = $hr0; + while (my ($kw, $val) = each %{$elt->[1]->subtree}) { + push @ar, [ $kw, $val, $hr ]; + } + } else { + my ($name, $value) = &{$map}('value', $elt->[0], $elt->[1]->value); + $elt->[2]{$name} = $value; + } + } + return $hroot->{''}; +} + sub as_string { '(section)' } our $AUTOLOAD; |