File Coverage

blib/lib/Data/Comparable.pm
Criterion Covered Total %
statement 50 51 98.0
branch 18 22 81.8
condition 6 6 100.0
subroutine 10 10 100.0
pod 5 5 100.0
total 89 94 94.6


line stmt bran cond sub pod time code
1 1     1   49950 use 5.008;
  1         4  
  1         39  
2 1     1   6 use strict;
  1         2  
  1         32  
3 1     1   6 use warnings;
  1         1  
  1         49  
4              
5             package Data::Comparable;
6             our $VERSION = '1.100840';
7             # ABSTRACT: Present your object for comparison purposes
8 1     1   888 use UNIVERSAL::require;
  1         1744  
  1         10  
9 1     1   969 use parent 'Data::Inherited';
  1         270  
  1         6  
10              
11             sub comparable_scalar {
12 56     56 1 66 my ($self, $scalar, $skip_bless) = @_;
13 56         75 my $class = ref $scalar;
14 56 100       93 unless ($class) {
15              
16             # Convert the value into a string, because eq_or_diff seems to make a
17             # difference between strings and numbers.
18 40 50       193 return defined $scalar ? "$scalar" : $scalar;
19             }
20              
21             # Make sure the class this scalar is referencing is loaded. Suppose you
22             # dump an object that has been serialized (say, from a database). Then it
23             # could happen that the corresponding classes haven't been loaded, and so
24             # it would dump incorrectly.
25 16 100 100     64 if ($class ne 'HASH' && $class ne 'ARRAY') {
26 8 50       44 $class->require or die $@;
27 8 50       235 if (UNIVERSAL::can($scalar, 'prepare_comparable')) {
28 0         0 $scalar->prepare_comparable;
29             }
30             }
31 16 100       52 if (UNIVERSAL::can($scalar, 'comparable')) {
    100          
32 4         14 return $scalar->comparable($skip_bless);
33             } elsif ($class eq 'ARRAY') {
34 4         8 return [ map { $self->comparable_scalar($_, $skip_bless) } @$scalar ];
  16         27  
35             } else {
36              
37             # else it must be a hash - we don't support other forms of blessed
38             # things yet. We could explicitly check for UNIVERSAL::isa($scalar,
39             # 'HASH'), but that's too slow for the typical case where there are
40             # huge structures composed of lists and possibly blessed hashes.
41 8         9 my $hash;
42 8         24 while (my ($key, $value) = each %$scalar) {
43 12         26 $hash->{$key} = $self->comparable_scalar($value, $skip_bless);
44             }
45              
46             # It could be an object of a class that doesn't implement comparable,
47             # so we got into this branch, but we still want to return a properly
48             # blessed object.
49 8 100 100     36 bless $hash, ref $scalar if ref $scalar ne 'HASH' && !$skip_bless;
50 8         31 return $hash;
51             }
52             }
53              
54             sub comparable {
55 4     4 1 8 my ($self, $skip_bless) = @_;
56 4 50       22 if (UNIVERSAL::can($self, 'prepare_comparable')) {
57 4         11 $self->prepare_comparable;
58             }
59 4         34 my %skip_keys = map { $_ => 1 } $self->every_list('SKIP_COMPARABLE_KEYS');
  4         1843  
60 4         7 my $copy = {};
61 4         20 while (my ($key, $value) = each %$self) {
62 32 100       105 next if exists $skip_keys{$key};
63 28         54 $copy->{$key} = $self->comparable_scalar($value, $skip_bless);
64             }
65 4 100       10 bless $copy, ref $self unless $skip_bless;
66 4         23 return $copy;
67             }
68              
69             sub dump_comparable {
70 2     2 1 43854 my ($self, $skip_bless) = @_;
71 2         1035 require Data::Dumper;
72 2         5980 local $Data::Dumper::Indent = 1;
73 2         14 Data::Dumper::Dumper($self->comparable($skip_bless));
74             }
75              
76             sub yaml_dump_comparable {
77 2     2 1 2635 my ($self, $skip_bless) = @_;
78 2         15 require YAML;
79 2         6 YAML::Dump($self->comparable($skip_bless));
80             }
81              
82             # So subclasses can call SUPER:: without worries.
83 4     4 1 23 sub prepare_comparable { }
84             1;
85              
86              
87             __END__