JQ-Lite
view release on metacpan or search on metacpan
lib/JQ/Lite/Filters.pm view on Meta::CPAN
if (my $reduce = JQ::Lite::Util::_parse_reduce_expression($normalized)) {
@next_results = ();
for my $value (@results) {
my $json = JQ::Lite::Util::_encode_json($value);
my @items = $self->run_query($json, $reduce->{generator});
my ($init_values, $init_ok) = JQ::Lite::Util::_evaluate_value_expression($self, $value, $reduce->{init_expr});
my $acc;
if ($init_ok) {
$acc = @$init_values ? $init_values->[0] : undef;
}
else {
my @init_outputs = $self->run_query(JQ::Lite::Util::_encode_json($value), $reduce->{init_expr});
$acc = @init_outputs ? $init_outputs[0] : undef;
}
for my $element (@items) {
my %existing = %{ $self->{_vars} || {} };
local $self->{_vars} = { %existing, $reduce->{var_name} => $element };
my ($updated_values, $updated_ok) = JQ::Lite::Util::_evaluate_value_expression($self, $acc, $reduce->{update_expr});
my $next;
if ($updated_ok) {
$next = @$updated_values ? $updated_values->[0] : undef;
}
else {
my @outputs = $self->run_query(JQ::Lite::Util::_encode_json($acc), $reduce->{update_expr});
$next = @outputs ? $outputs[0] : undef;
}
$acc = $next;
}
push @next_results, $acc;
}
@$out_ref = @next_results;
return 1;
}
# support for .[] iteration
if ($part eq '.[]') {
@next_results = map {
ref $_ eq 'ARRAY' ? @$_
: ref $_ eq 'HASH' ? values %$_
: JQ::Lite::Util::_is_string_scalar($_) ? split(//, "$_")
: ()
} @results;
@$out_ref = @next_results;
return 1;
}
# support for select(...)
if ($part =~ /^select\((.+)\)$/) {
my $cond = $1;
@next_results = ();
my $has_wildcard_array = index($cond, '[]') != -1;
my $has_comparison = ($cond =~ /(==|!=|>=|<=|>|<|\band\b|\bor\b|\bcontains\b|\bhas\b|\bmatch\b)/i);
my $use_streaming_eval = $has_wildcard_array || !$has_comparison;
# allow built-in filters like match() and test() to run so their errors surface
$use_streaming_eval ||= ($cond =~ /^\s*(match|test)\s*\(/);
VALUE: for my $value (@results) {
my $simple = JQ::Lite::Util::_evaluate_condition($value, $cond) ? 1 : 0;
if ($use_streaming_eval) {
my $json = JQ::Lite::Util::_encode_json($value);
my $error;
my @cond_results;
{
local $@;
@cond_results = eval { $self->run_query($json, $cond) };
$error = $@;
}
die $error if $error;
if (@cond_results) {
my $truthy = 0;
for my $cond_value (@cond_results) {
if (JQ::Lite::Util::_is_truthy($cond_value)) {
$truthy++;
}
}
if ($truthy) {
push @next_results, (($value) x $truthy);
}
next VALUE;
}
}
if ($simple) {
push @next_results, $value;
}
}
@$out_ref = @next_results;
return 1;
}
# support for length
if ($part eq 'length') {
@next_results = map {
if (!defined $_) {
0;
}
elsif (ref $_ eq 'ARRAY') {
scalar(@$_);
}
elsif (ref $_ eq 'HASH') {
scalar(keys %$_);
}
elsif (!ref $_ || ref($_) eq 'JSON::PP::Boolean') {
length("$_");
}
else {
0;
}
} @results;
@$out_ref = @next_results;
return 1;
}
( run in 0.677 second using v1.01-cache-2.11-cpan-140bd7fdf52 )