Skip to content

Commit

Permalink
dselect() removed, dtraverse() should be used instead
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-mixas committed Sep 13, 2016
1 parent b617f8a commit d4c5d34
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 233 deletions.
5 changes: 5 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Revision history for Struct-Diff

0.70 2016-09-13
dselect() removed, dtraverse() should be used instead
cosmetic refactoring
docs corrected

0.66 2016-09-06
ref to subdiff passed as fourth arg to callback functions in dtraverse()
dtraverse() expects true value as callback's out value
Expand Down
1 change: 0 additions & 1 deletion MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ t/000-load.t
t/100-diff-primitives.t
t/110-diff-structures.t
t/200-dsplit.t
t/300-dselect.t
t/400-patch.t
t/500-dtraverse.t
t/_common.pm
Expand Down
31 changes: 4 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,21 @@ Struct::Diff - Recursive diff tools for nested perl structures

# VERSION

Version 0.66
Version 0.70

# SYNOPSIS

use Struct::Diff qw(diff dselect dsplit patch);
use Struct::Diff qw(diff dsplit dtraverse patch);

$a = {x => [7,{y => 4}]};
$b = {x => [7,{y => 9}],z => 33};

$diff = diff($a, $b, noO => 1, noU => 1); # omit unchanged and old values for changed items
# $diff == {D => {x => {D => [{I => 1,N => {y => 9}}]},z => {A => 33}}};

@items = dselect($diff, fromD => ['z']); # get status for a particular key
# @items == ({z => {A => 33}});

$href = dsplit($diff); # divide diff
# $dsplit->{a} not exists # unchanged omitted, other items originated from $b
# $dsplit->{b} == {x => [{y => 9}],z => 33};
# $href->{a} not exists # unchanged omitted, other items originated from $b
# $href->{b} == {x => [{y => 9}],z => 33};

dtraverse($d, {callback => sub {print "val $_[0] has status $_[2]"; 1}}); # traverse through diff

Expand Down Expand Up @@ -84,26 +81,6 @@ Diff's keys shows status of each item in passed structures.

Drop removed item's data.

## dselect

Returns items with desired status from diff's first level

@added = dselect($diff, states => { 'A' => 1 } # something added?
@items = dselect($diff, states => { 'A' => 1, 'U' => 1 }, 'fromD' => [ 'a', 'b', 'c' ]) # from D hash
@items = dselect($diff, states => { 'D' => 1, 'N' => 1 }, 'fromD' => [ 0, 1, 3, 5, 9 ]) # from D array

### Available options

- fromD

Select items from diff's 'D'. Expects list of positions (indexes for arrays and keys for hashes). All items with
specified states will be returned if opt exists, but not defined or is an empty list.

- states

Expects hash with desired states as keys with values in some true value. Items with all states will be returned if
opt not defined.

## dsplit

Divide diff to pseudo original structures
Expand Down
86 changes: 12 additions & 74 deletions lib/Struct/Diff.pm
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ use warnings FATAL => 'all';
use parent qw(Exporter);
use Carp qw(croak);

our @EXPORT_OK = qw(diff dselect dsplit dtraverse patch);
our @EXPORT_OK = qw(diff dsplit dtraverse patch);

sub _validate_meta($) {
my $d = shift;
croak "Unsupported diff struct passed" if (ref $d ne 'HASH');
if (exists $d->{'D'}) {
croak "Unsupported diff struct passed" if (ref $_[0] ne 'HASH');
if (exists $_[0]->{'D'}) {
croak "Value for 'D' status must be hash or array"
unless (ref $d->{'D'} eq 'HASH' or ref $d->{'D'} eq 'ARRAY');
unless (ref $_[0]->{'D'} eq 'HASH' or ref $_[0]->{'D'} eq 'ARRAY');
}
return 1;
}
Expand All @@ -24,28 +23,25 @@ Struct::Diff - Recursive diff tools for nested perl structures
=head1 VERSION
Version 0.66
Version 0.70
=cut

our $VERSION = '0.66';
our $VERSION = '0.70';

=head1 SYNOPSIS
use Struct::Diff qw(diff dselect dsplit patch);
use Struct::Diff qw(diff dsplit dtraverse patch);
$a = {x => [7,{y => 4}]};
$b = {x => [7,{y => 9}],z => 33};
$diff = diff($a, $b, noO => 1, noU => 1); # omit unchanged and old values for changed items
# $diff == {D => {x => {D => [{I => 1,N => {y => 9}}]},z => {A => 33}}};
@items = dselect($diff, fromD => ['z']); # get status for a particular key
# @items == ({z => {A => 33}});
$href = dsplit($diff); # divide diff
# $dsplit->{a} not exists # unchanged omitted, other items originated from $b
# $dsplit->{b} == {x => [{y => 9}],z => 33};
# $href->{a} not exists # unchanged omitted, other items originated from $b
# $href->{b} == {x => [{y => 9}],z => 33};
dtraverse($d, {callback => sub {print "val $_[0] has status $_[2]"; 1}}); # traverse through diff
Expand Down Expand Up @@ -151,15 +147,15 @@ sub diff($$;@) {
$hidden = 1;
} else {
$s->{'R'} = 1;
map { push @{$d->{'D'}}, { 'R' => $opts{'trimR'} ? undef : $_ } } @{$a}[@{$b}..$#{$a}];
map { push @{$d->{'D'}}, { 'R' => $opts{'trimR'} ? undef : $_ } } @{$a}[@{$b} .. $#{$a}];
}
}
if (@{$a} < @{$b}) {
if ($opts{'noA'}) {
$hidden = 1;
} else {
$s->{'A'} = 1;
map { push @{$d->{'D'}}, { 'A' => $_ } } @{$b}[@{$a}..$#{$b}];
map { push @{$d->{'D'}}, { 'A' => $_ } } @{$b}[@{$a} .. $#{$b}];
}
}

Expand Down Expand Up @@ -209,64 +205,6 @@ sub diff($$;@) {
return $d;
}

=head2 dselect
Returns items with desired status from diff's first level
@added = dselect($diff, states => { 'A' => 1 } # something added?
@items = dselect($diff, states => { 'A' => 1, 'U' => 1 }, 'fromD' => [ 'a', 'b', 'c' ]) # from D hash
@items = dselect($diff, states => { 'D' => 1, 'N' => 1 }, 'fromD' => [ 0, 1, 3, 5, 9 ]) # from D array
=head3 Available options
=over 4
=item fromD
Select items from diff's 'D'. Expects list of positions (indexes for arrays and keys for hashes). All items with
specified states will be returned if opt exists, but not defined or is an empty list.
=item states
Expects hash with desired states as keys with values in some true value. Items with all states will be returned if
opt not defined.
=back
=cut

sub dselect(@) {
my ($d, %opts) = @_;
_validate_meta($d);
my @out;

if (exists $opts{'fromD'}) {
croak "'fromD' defined, but no 'D' state found" unless (exists $d->{'D'});
if (ref $d->{'D'} eq 'ARRAY') {
for my $i (($opts{'fromD'} and @{$opts{'fromD'}}) ? @{$opts{'fromD'}} : 0..$#{$d->{'D'}}) {
croak "Requested index $i not in diff's array range" unless ($i >= 0 and $i < @{$d->{'D'}});
push @out, {
map { $_ => $d->{'D'}->[$i]->{$_} }
grep { not $opts{'states'} or exists $opts{'states'}->{$_} }
keys %{$d->{'D'}->[$i]}
};
}
} else { # HASH
for my $k (($opts{'fromD'} and @{$opts{'fromD'}}) ? @{$opts{'fromD'}} : keys %{$d->{'D'}}) {
push @out, {
map { $k => { $_ => $d->{'D'}->{$k}->{$_} } }
grep { not $opts{'states'} or exists $opts{'states'}->{$_} }
keys %{$d->{'D'}->{$k}}
};
}
}
} else {
@out = { map { $_ => $d->{$_} } grep { not $opts{'states'} or exists $opts{'states'}->{$_} } keys %{$d} };
}

return grep { keys %{$_} } @out;
}

=head2 dsplit
Divide diff to pseudo original structures
Expand Down Expand Up @@ -391,7 +329,7 @@ sub patch($$) {

if (exists $d->{'D'}) {
if (ref $d->{'D'} eq 'ARRAY') {
for my $i (0..$#{$d->{'D'}}) {
for my $i (0 .. $#{$d->{'D'}}) {
my $si = exists $d->{'D'}->[$i]->{'I'} ? $d->{'D'}->[$i]->{'I'} : $i; # use provided index
if (exists $d->{'D'}->[$i]->{'D'} or exists $d->{'D'}->[$i]->{'N'}) {
patch(ref $s->[$si] ? $s->[$si] : \$s->[$si], $d->{'D'}->[$i]);
Expand Down
131 changes: 0 additions & 131 deletions t/300-dselect.t

This file was deleted.

0 comments on commit d4c5d34

Please sign in to comment.