diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2014-12-10 13:34:52 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2014-12-10 13:34:52 +0000 |
commit | 8fddd4400d09891094843fe9e77fec74e4510c67 (patch) | |
tree | 23dbb27d11e56cf6586d93b091c708fa111a7a2d /lib/Data/Compare | |
download | Data-Compare-tarball-master.tar.gz |
Data-Compare-1.25HEADData-Compare-1.25master
Diffstat (limited to 'lib/Data/Compare')
-rw-r--r-- | lib/Data/Compare/Plugins.pod | 101 | ||||
-rw-r--r-- | lib/Data/Compare/Plugins/Scalar/Properties.pm | 94 |
2 files changed, 195 insertions, 0 deletions
diff --git a/lib/Data/Compare/Plugins.pod b/lib/Data/Compare/Plugins.pod new file mode 100644 index 0000000..97747fb --- /dev/null +++ b/lib/Data/Compare/Plugins.pod @@ -0,0 +1,101 @@ +=head1 NAME + +Data::Compare::Plugins - how to extend Data::Compare + +=head1 DESCRIPTION + +Data::Compare natively handles several built-in data types - scalars, +references to scalars, +references to arrays, references to hashes, references to +subroutines, compiled regular expressions, and globs. For objects, +it tries to Do The Right Thing and compares the underlying data type. +However, this is not always what you want. This is especially true if +you have complex objects which overload stringification and/or +numification. + +Hence we allow for plugins. + +=head1 FINDING PLUGINS + +Data::Compare will try to load any module installed on your system under +the various @INC/Data/Compare/Plugins/ directories. If there is a problem +loading any of them, an appropriate warning will be issued. + +Because of how we find plugins, no plugins are available when running in +"taint" mode. + +=head1 WRITING PLUGINS + +Internally, plugins are C<require>d into Data::Compare. This means that +they need to evaluate to true. We make use of that true value. Where +normally you just put: + + 1; + +at the end of an included file, you should instead ensure that you return +a reference to an array. This is treated as being true so satisfies perl, +and is a damned sight more useful. + +Inside that array should be either a description of what this plugin is to +do, or references to several arrays containing such descriptions. A +description consists of two or three items. First a string telling +us what the first data-type handled by your plugin is. Second, (and +optional, defaulting to the same as the first) the second data-type +to compare. To handle comparisons to ordinary scalars, give the empty string +for the data-type, ie: + + ['MyType', '', sub { ...}] + +Third and last, we need a reference to the +subroutine which does the comparison. +That subroutine should expect to take two parameters, which will be of +the specified type. It should return 1 if they compare +the same, or 0 if they compare different. + +Be aware that while you might give a description like: + + ['Type1', 'Type2', sub { ... }] + +this will handle both comparing Type1 to Type2, and comparing Type2 to +Type1. ie, comparison is commutative. + +If you want to use Data::Compare's own comparison function from within +your handler (to, for example, compare a data structure that you have +stored somewhere in your object) then you will need to call it as +Data::Compare::Compare. However, you must be careful to avoid infinite +recursion by calling D::C::Compare which in turn calls back to your +handler. + +The name of +your plugins does not matter, only that it lives in one of those directories. +Of course, giving it a sensible name means that the usual installation +mechanisms will put it in the right place, and meaningful names will make +it easier to debug your code. + +For an example, look at the plugin that handles Scalar::Properties +objects, which is distributed with Data::Compare. + +=head1 DISTRIBUTION + +Provided that the above rules are followed I see no reason for you to not +upload your plugin to the CPAN yourself. You will need to make Data::Compare +a pre-requisite, so that the CPAN.pm installer does the right thing. + +Alternatively, if you would prefer me to roll your plugin in with the +Data::Compare distribution, I'd be happy to do so provided that the code +is clear and well-commented, and that you include tests and documentation. + +=head1 SEE ALSO + +L<Data::Compare> + +L<Data::Compare::Plugins::Scalar::Properties> + +=head1 AUTHOR + +Copyright (c) 2004 David Cantrell <david@cantrell.org.uk>. +All rights reserved. +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=cut diff --git a/lib/Data/Compare/Plugins/Scalar/Properties.pm b/lib/Data/Compare/Plugins/Scalar/Properties.pm new file mode 100644 index 0000000..0c46b6b --- /dev/null +++ b/lib/Data/Compare/Plugins/Scalar/Properties.pm @@ -0,0 +1,94 @@ +package Data::Compare::Plugins::Scalar::Properties; + +use strict; +use vars qw($VERSION); +use Data::Compare; + +$VERSION = 1.0; + +sub register { + return [ + ['Scalar::Properties', \&sp_scalar_compare], + ['', 'Scalar::Properties', \&sp_scalar_compare], + ]; +} + +# note that when S::Ps are involved we can't use Data::Compare's default +# Compare function, so we use eq to check that values are the same. But +# we *do* use D::C::Compare whenever possible. + +# Compare a S::P and a scalar, or if we figure out that we've got two +# S::Ps, call sp_sp_compare instead + +sub sp_scalar_compare { + my($scalar, $sp) = @_; + + # we don't care what order the two params are, so swap if necessary + ($scalar, $sp) = ($sp, $scalar) if(ref($scalar)); + + # got two S::Ps? + return sp_sp_compare($scalar, $sp) if(ref($scalar)); + + # we've really got a scalar and an S::P, so just compare values + return 1 if($scalar eq $sp); + return 0; +} + +# Compare two S::Ps + +sub sp_sp_compare { + my($sp1, $sp2) = @_; + + # first check the values + return 0 unless($sp1 eq $sp2); + + # now check that we have all the same properties + return 0 unless(Data::Compare::Compare([sort $sp1->get_props()], [sort $sp2->get_props()])); + + # and that all properties have the same values + return 0 if( + grep { !Data::Compare::Compare(eval "\$sp1->$_()", eval "\$sp2->$_()") } $sp1->get_props() + ); + + # if we get here, all is tickety-boo + return 1; +} + +register(); + +=head1 NAME + +Data::Compare::Plugin::Scalar::Properties - plugin for Data::Compare to +handle Scalar::Properties objects. + +=head1 DESCRIPTION + +Enables Data::Compare to Do The Right Thing for Scalar::Properties +objects. + +=over 4 + +=item comparing a Scalar::Properties object and an ordinary scalar + +If you compare +a scalar and a Scalar::Properties, then they will be considered the same +if the two values are the same, regardless of the presence of properties. + +=item comparing two Scalar::Properties objects + +If you compare two Scalar::Properties objects, then they will only be +considered the same if the values and the properties match. + +=back + +=head1 AUTHOR + +Copyright (c) 2004 David Cantrell. All rights reserved. +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=head1 SEE ALSO + +L<Data::Compare> + +=cut |