=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
