Catmandu

 view release on metacpan or  search on metacpan

lib/Catmandu/Path/simple.pm  view on Meta::CPAN

package Catmandu::Path::simple;

use Catmandu::Sane;

our $VERSION = '1.2025';

use Catmandu::Util
    qw(is_hash_ref is_array_ref is_value is_natural is_code_ref trim);
use Moo;
use namespace::clean;

with 'Catmandu::Path', 'Catmandu::Emit';

use overload '""' => sub {$_[0]->path};

sub split_path {
    my ($self) = @_;
    my $path = $self->path;
    if (is_value($path)) {
        $path = trim($path);
        $path =~ s/^\$[\.\/]//;
        $path = [map {s/\\(?=[\.\/])//g; $_} split /(?<!\\)[\.\/]/, $path];
        return $path;
    }
    if (is_array_ref($path)) {
        return $path;
    }
    Catmandu::Error->throw("path should be a string or arrayref of strings");
}

sub getter {
    my ($self)   = @_;
    my $path     = $self->split_path;
    my $data_var = $self->_generate_var;
    my $vals_var = $self->_generate_var;

    my $body = $self->_emit_declare_vars($vals_var, '[]') . $self->_emit_get(
        $data_var,
        $path,
        sub {
            my ($var, %opts) = @_;

            # looping goes backwards to keep deletions safe
            "unshift(\@{${vals_var}}, ${var});";
        },
    ) . "return ${vals_var};";

    $self->_eval_sub($body, args => [$data_var]);
}

sub setter {
    my $self     = shift;
    my %opts     = @_ == 1 ? (value => $_[0]) : @_;
    my $path     = $self->split_path;
    my $key      = pop @$path;
    my $data_var = $self->_generate_var;
    my $val_var  = $self->_generate_var;
    my $captures = {};
    my $args     = [$data_var];

    my $body = $self->_emit_get(
        $data_var,
        $path,
        sub {
            my $var = $_[0];
            my $val;
            if (is_code_ref($opts{value})) {
                $captures->{$val_var} = $opts{value};
                $val = "${val_var}->(${var}, ${data_var})";
            }
            elsif (exists $opts{value}) {
                $captures->{$val_var} = $opts{value};
                $val = $val_var;
            }
            else {
                push @$args, $val_var;
                $val
                    = "is_code_ref(${val_var}) ? ${val_var}->(${var}, ${data_var}) : ${val_var}";
            }

            $self->_emit_set_key($var, $key, $val);



( run in 0.748 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )