File: in.pm

package info (click to toggle)
libcatmandu-perl 1.2024-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,552 kB
  • sloc: perl: 17,037; makefile: 24; sh: 1
file content (137 lines) | stat: -rw-r--r-- 3,322 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package Catmandu::Fix::Condition::in;

use Catmandu::Sane;

our $VERSION = '1.2024';

use Moo;
use Catmandu::Util::Path qw(as_path);
use namespace::clean;
use Catmandu::Fix::Has;
use Data::Compare;

has path1 => (fix_arg => 1);
has path2 => (fix_arg => 1);

with 'Catmandu::Fix::Condition::Builder';

sub _build_tester {
    my ($self)       = @_;
    my $path1_getter = as_path($self->path1)->getter;
    my $path2_getter = as_path($self->path2)->getter;
    sub {
        my $data  = $_[0];
        my $vals1 = $path1_getter->($data);
        my $vals2 = $path2_getter->($data);
        return 0 unless @$vals1 && @$vals2 && @$vals1 == @$vals2;
        for (my $i = 0; $i < @$vals1; $i++) {
            return 0 unless in($vals1->[$i], $vals2->[$i]);
        }
        return 1;
    }
}

sub in {
    my ($a, $b) = @_;

    return 1 if (!(defined($a) && defined($b)));
    return 0 if (!defined($a) || !defined($b));

    # scalar vs scalar
    if (ref($a) eq "" && ref($b) eq "") {
        return $a eq $b;
    }

    # scalar vs list
    elsif (ref($a) eq "" && ref($b) eq "ARRAY") {
        return scalar grep({$_ eq $a} @$b);
    }

    # scalar vs hash
    elsif (ref($a) eq "" && ref($b) eq "HASH") {
        return exists $b->{$a};
    }

    # array vs array
    elsif (ref($a) eq "ARRAY" && ref($b) eq "ARRAY") {
        return Compare($a, $b);
    }

    # hash vs hash
    elsif (ref($a) eq "HASH" && ref($b) eq "HASH") {
        return Compare($a, $b);
    }

    # hash vs array
    elsif (ref($a) eq "HASH" && ref($b) eq "ARRAY") {
        my @h = %$a;
        return Compare(\@h, $b);
    }

    # array vs hash
    elsif (ref($a) eq "ARRAY" && ref($b) eq "HASH") {
        my @h = %$b;
        return Compare($a, @h);
    }
    else {
        return 0;
    }
}

1;

__END__

=pod

=head1 NAME

Catmandu::Fix::Condition::in - only execute fixes the data in one path is contained in another

=head1 SYNOPSIS

   #-------------------------------------------------------------------
   # Compare single values
   # foo => 42 , bar => 42 => in(foo,bar) -> true
   if in(foo,bar)
      add_field(forty_two,ok)
   end
   
   # When comparing single values to an array: test if the value is 
   # contained in the array  

   # foo => 1 , bar => [3,2,1]  => in(foo,bar) -> true
   if in(foo,bar)
      add_field(test,ok)
   end

   # foo => 42 , bar => [1,2,3] => in(foo,bar) -> false
   unless in(foo,bar)
      add_field(test,ok)
   end

   # In the following examples we'll write in pseudo code the true/false
   # values of some 'in()' comparissons

   # scalars vs arrays - check if the value is in the array
   foo: 42 , bar: [1,2,3]                   in(foo,bar) -> false
   foo: 1  , bar: [1,2,3]                   in(foo,bar) -> true

   # scalars vs hashes - check if the key is in the hash
   foo: name , bar: { name => 'Patrick' }           in(foo,bar) -> true
   foo: name , bar: { deep => {name => 'Nicolas'}}  in(foo,bar) -> false

   # array vs array - check if the contents is equal
   foo: [1,2] , bar: [1,2]                  in(foo,bar) -> true
   foo: [1,2] , bar: [1,2,3]                in(foo,bar) -> false
   foo: [1,2] , bar: [[1,2],3]              in(foo,bar) -> false

=head1 STATUS

Be aware this function is experimental in many perl versions

=head1 SEE ALSO

L<Catmandu::Fix>

=cut