summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md789
1 files changed, 789 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..59b86fa
--- /dev/null
+++ b/README.md
@@ -0,0 +1,789 @@
+NAME
+
+ Params::Validate - Validate method/function parameters
+
+VERSION
+
+ version 1.20
+
+SYNOPSIS
+
+ use Params::Validate qw(:all);
+
+ # takes named params (hash or hashref)
+ sub foo {
+ validate(
+ @_, {
+ foo => 1, # mandatory
+ bar => 0, # optional
+ }
+ );
+ }
+
+ # takes positional params
+ sub bar {
+ # first two are mandatory, third is optional
+ validate_pos( @_, 1, 1, 0 );
+ }
+
+ sub foo2 {
+ validate(
+ @_, {
+ foo =>
+ # specify a type
+ { type => ARRAYREF },
+ bar =>
+ # specify an interface
+ { can => [ 'print', 'flush', 'frobnicate' ] },
+ baz => {
+ type => SCALAR, # a scalar ...
+ # ... that is a plain integer ...
+ regex => qr/^\d+$/,
+ callbacks => { # ... and smaller than 90
+ 'less than 90' => sub { shift() < 90 },
+ },
+ }
+ }
+ );
+ }
+
+ sub callback_with_custom_error {
+ validate(
+ @_,
+ {
+ foo => callbacks => {
+ 'is an integer' => sub {
+ return 1 if $_[0] =~ /^-?[1-9][0-9]*$/;
+ die "$_[0] is not a valid integer value";
+ },
+ }
+ }
+ );
+ }
+
+ sub with_defaults {
+ my %p = validate(
+ @_, {
+ # required
+ foo => 1,
+ # $p{bar} will be 99 if bar is not given. bar is now
+ # optional.
+ bar => { default => 99 }
+ }
+ );
+ }
+
+ sub pos_with_defaults {
+ my @p = validate_pos( @_, 1, { default => 99 } );
+ }
+
+ sub sets_options_on_call {
+ my %p = validate_with(
+ params => \@_,
+ spec => { foo => { type => SCALAR, default => 2 } },
+ normalize_keys => sub { $_[0] =~ s/^-//; lc $_[0] },
+ );
+ }
+
+DESCRIPTION
+
+ The Params::Validate module allows you to validate method or function
+ call parameters to an arbitrary level of specificity. At the simplest
+ level, it is capable of validating the required parameters were given
+ and that no unspecified additional parameters were passed in.
+
+ It is also capable of determining that a parameter is of a specific
+ type, that it is an object of a certain class hierarchy, that it
+ possesses certain methods, or applying validation callbacks to
+ arguments.
+
+ EXPORT
+
+ The module always exports the validate() and validate_pos() functions.
+
+ It also has an additional function available for export, validate_with,
+ which can be used to validate any type of parameters, and set various
+ options on a per-invocation basis.
+
+ In addition, it can export the following constants, which are used as
+ part of the type checking. These are SCALAR, ARRAYREF, HASHREF,
+ CODEREF, GLOB, GLOBREF, and SCALARREF, UNDEF, OBJECT, BOOLEAN, and
+ HANDLE. These are explained in the section on Type Validation.
+
+ The constants are available via the export tag :types. There is also an
+ :all tag which includes all of the constants as well as the
+ validation_options() function.
+
+PARAMETER VALIDATION
+
+ The validation mechanisms provided by this module can handle both named
+ or positional parameters. For the most part, the same features are
+ available for each. The biggest difference is the way that the
+ validation specification is given to the relevant subroutine. The other
+ difference is in the error messages produced when validation checks
+ fail.
+
+ When handling named parameters, the module will accept either a hash or
+ a hash reference.
+
+ Subroutines expecting named parameters should call the validate()
+ subroutine like this:
+
+ validate(
+ @_, {
+ parameter1 => validation spec,
+ parameter2 => validation spec,
+ ...
+ }
+ );
+
+ Subroutines expecting positional parameters should call the
+ validate_pos() subroutine like this:
+
+ validate_pos( @_, { validation spec }, { validation spec } );
+
+ Mandatory/Optional Parameters
+
+ If you just want to specify that some parameters are mandatory and
+ others are optional, this can be done very simply.
+
+ For a subroutine expecting named parameters, you would do this:
+
+ validate( @_, { foo => 1, bar => 1, baz => 0 } );
+
+ This says that the "foo" and "bar" parameters are mandatory and that
+ the "baz" parameter is optional. The presence of any other parameters
+ will cause an error.
+
+ For a subroutine expecting positional parameters, you would do this:
+
+ validate_pos( @_, 1, 1, 0, 0 );
+
+ This says that you expect at least 2 and no more than 4 parameters. If
+ you have a subroutine that has a minimum number of parameters but can
+ take any maximum number, you can do this:
+
+ validate_pos( @_, 1, 1, (0) x (@_ - 2) );
+
+ This will always be valid as long as at least two parameters are given.
+ A similar construct could be used for the more complex validation
+ parameters described further on.
+
+ Please note that this:
+
+ validate_pos( @_, 1, 1, 0, 1, 1 );
+
+ makes absolutely no sense, so don't do it. Any zeros must come at the
+ end of the validation specification.
+
+ In addition, if you specify that a parameter can have a default, then
+ it is considered optional.
+
+ Type Validation
+
+ This module supports the following simple types, which can be exported
+ as constants:
+
+ * SCALAR
+
+ A scalar which is not a reference, such as 10 or 'hello'. A parameter
+ that is undefined is not treated as a scalar. If you want to allow
+ undefined values, you will have to specify SCALAR | UNDEF.
+
+ * ARRAYREF
+
+ An array reference such as [1, 2, 3] or \@foo.
+
+ * HASHREF
+
+ A hash reference such as { a => 1, b => 2 } or \%bar.
+
+ * CODEREF
+
+ A subroutine reference such as \&foo_sub or sub { print "hello" }.
+
+ * GLOB
+
+ This one is a bit tricky. A glob would be something like *FOO, but
+ not \*FOO, which is a glob reference. It should be noted that this
+ trick:
+
+ my $fh = do { local *FH; };
+
+ makes $fh a glob, not a glob reference. On the other hand, the return
+ value from Symbol::gensym is a glob reference. Either can be used as
+ a file or directory handle.
+
+ * GLOBREF
+
+ A glob reference such as \*FOO. See the GLOB entry above for more
+ details.
+
+ * SCALARREF
+
+ A reference to a scalar such as \$x.
+
+ * UNDEF
+
+ An undefined value
+
+ * OBJECT
+
+ A blessed reference.
+
+ * BOOLEAN
+
+ This is a special option, and is just a shortcut for UNDEF | SCALAR.
+
+ * HANDLE
+
+ This option is also special, and is just a shortcut for GLOB |
+ GLOBREF. However, it seems likely that most people interested in
+ either globs or glob references are likely to really be interested in
+ whether the parameter in question could be a valid file or directory
+ handle.
+
+ To specify that a parameter must be of a given type when using named
+ parameters, do this:
+
+ validate(
+ @_, {
+ foo => { type => SCALAR },
+ bar => { type => HASHREF }
+ }
+ );
+
+ If a parameter can be of more than one type, just use the bitwise or
+ (|) operator to combine them.
+
+ validate( @_, { foo => { type => GLOB | GLOBREF } );
+
+ For positional parameters, this can be specified as follows:
+
+ validate_pos( @_, { type => SCALAR | ARRAYREF }, { type => CODEREF } );
+
+ Interface Validation
+
+ To specify that a parameter is expected to have a certain set of
+ methods, we can do the following:
+
+ validate(
+ @_, {
+ foo =>
+ # just has to be able to ->bar
+ { can => 'bar' }
+ }
+ );
+
+ ... or ...
+
+ validate(
+ @_, {
+ foo =>
+ # must be able to ->bar and ->print
+ { can => [qw( bar print )] }
+ }
+ );
+
+ Class Validation
+
+ A word of warning. When constructing your external interfaces, it is
+ probably better to specify what methods you expect an object to have
+ rather than what class it should be of (or a child of). This will make
+ your API much more flexible.
+
+ With that said, if you want to validate that an incoming parameter
+ belongs to a class (or child class) or classes, do:
+
+ validate(
+ @_,
+ { foo => { isa => 'My::Frobnicator' } }
+ );
+
+ ... or ...
+
+ validate(
+ @_,
+ # must be both, not either!
+ { foo => { isa => [qw( My::Frobnicator IO::Handle )] } }
+ );
+
+ Regex Validation
+
+ If you want to specify that a given parameter must match a specific
+ regular expression, this can be done with "regex" spec key. For
+ example:
+
+ validate(
+ @_,
+ { foo => { regex => qr/^\d+$/ } }
+ );
+
+ The value of the "regex" key may be either a string or a pre-compiled
+ regex created via qr.
+
+ If the value being checked against a regex is undefined, the regex is
+ explicitly checked against the empty string ('') instead, in order to
+ avoid "Use of uninitialized value" warnings.
+
+ The Regexp::Common module on CPAN is an excellent source of regular
+ expressions suitable for validating input.
+
+ Callback Validation
+
+ If none of the above are enough, it is possible to pass in one or more
+ callbacks to validate the parameter. The callback will be given the
+ value of the parameter as its first argument. Its second argument will
+ be all the parameters, as a reference to either a hash or array.
+ Callbacks are specified as hash reference. The key is an id for the
+ callback (used in error messages) and the value is a subroutine
+ reference, such as:
+
+ validate(
+ @_,
+ {
+ foo => {
+ callbacks => {
+ 'smaller than a breadbox' => sub { shift() < $breadbox },
+ 'green or blue' => sub {
+ return 1 if $_[0] eq 'green' || $_[0] eq 'blue';
+ die "$_[0] is not green or blue!";
+ }
+ }
+ }
+ }
+ );
+
+ validate(
+ @_, {
+ foo => {
+ callbacks => {
+ 'bigger than baz' => sub { $_[0] > $_[1]->{baz} }
+ }
+ }
+ }
+ );
+
+ The callback should return a true value if the value is valid. If not,
+ it can return false or die. If you return false, a generic error
+ message will be thrown by Params::Validate.
+
+ If your callback dies instead you can provide a custom error message.
+ If the callback dies with a plain string, this string will be appended
+ to an exception message generated by Params::Validate. If the callback
+ dies with a reference (blessed or not), then this will be rethrown
+ as-is by Params::Validate.
+
+ Untainting
+
+ If you want values untainted, set the "untaint" key in a spec hashref
+ to a true value, like this:
+
+ my %p = validate(
+ @_, {
+ foo => { type => SCALAR, untaint => 1 },
+ bar => { type => ARRAYREF }
+ }
+ );
+
+ This will untaint the "foo" parameter if the parameters are valid.
+
+ Note that untainting is only done if all parameters are valid. Also,
+ only the return values are untainted, not the original values passed
+ into the validation function.
+
+ Asking for untainting of a reference value will not do anything, as
+ Params::Validate will only attempt to untaint the reference itself.
+
+ Mandatory/Optional Revisited
+
+ If you want to specify something such as type or interface, plus the
+ fact that a parameter can be optional, do this:
+
+ validate(
+ @_, {
+ foo => { type => SCALAR },
+ bar => { type => ARRAYREF, optional => 1 }
+ }
+ );
+
+ or this for positional parameters:
+
+ validate_pos(
+ @_,
+ { type => SCALAR },
+ { type => ARRAYREF, optional => 1 }
+ );
+
+ By default, parameters are assumed to be mandatory unless specified as
+ optional.
+
+ Dependencies
+
+ It also possible to specify that a given optional parameter depends on
+ the presence of one or more other optional parameters.
+
+ validate(
+ @_, {
+ cc_number => {
+ type => SCALAR,
+ optional => 1,
+ depends => [ 'cc_expiration', 'cc_holder_name' ],
+ },
+ cc_expiration => { type => SCALAR, optional => 1 },
+ cc_holder_name => { type => SCALAR, optional => 1 },
+ }
+ );
+
+ In this case, "cc_number", "cc_expiration", and "cc_holder_name" are
+ all optional. However, if "cc_number" is provided, then "cc_expiration"
+ and "cc_holder_name" must be provided as well.
+
+ This allows you to group together sets of parameters that all must be
+ provided together.
+
+ The validate_pos() version of dependencies is slightly different, in
+ that you can only depend on one other parameter. Also, if for example,
+ the second parameter 2 depends on the fourth parameter, then it implies
+ a dependency on the third parameter as well. This is because if the
+ fourth parameter is required, then the user must also provide a third
+ parameter so that there can be four parameters in total.
+
+ Params::Validate will die if you try to depend on a parameter not
+ declared as part of your parameter specification.
+
+ Specifying defaults
+
+ If the validate() or validate_pos() functions are called in a list
+ context, they will return a hash or containing the original parameters
+ plus defaults as indicated by the validation spec.
+
+ If the function is not called in a list context, providing a default in
+ the validation spec still indicates that the parameter is optional.
+
+ The hash or array returned from the function will always be a copy of
+ the original parameters, in order to leave @_ untouched for the calling
+ function.
+
+ Simple examples of defaults would be:
+
+ my %p = validate( @_, { foo => 1, bar => { default => 99 } } );
+
+ my @p = validate_pos( @_, 1, { default => 99 } );
+
+ In scalar context, a hash reference or array reference will be
+ returned, as appropriate.
+
+USAGE NOTES
+
+ Validation failure
+
+ By default, when validation fails Params::Validate calls
+ Carp::confess(). This can be overridden by setting the on_fail option,
+ which is described in the "GLOBAL" OPTIONS section.
+
+ Method calls
+
+ When using this module to validate the parameters passed to a method
+ call, you will probably want to remove the class/object from the
+ parameter list before calling validate() or validate_pos(). If your
+ method expects named parameters, then this is necessary for the
+ validate() function to actually work, otherwise @_ will not be usable
+ as a hash, because it will first have your object (or class) followed
+ by a set of keys and values.
+
+ Thus the idiomatic usage of validate() in a method call will look
+ something like this:
+
+ sub method {
+ my $self = shift;
+
+ my %params = validate(
+ @_, {
+ foo => 1,
+ bar => { type => ARRAYREF },
+ }
+ );
+ }
+
+ Speeding Up Validation
+
+ In most cases, the validation spec will remain the same for each call
+ to a subroutine. In that case, you can speed up validation by defining
+ the validation spec just once, rather than on each call to the
+ subroutine:
+
+ my %spec = ( ... );
+ sub foo {
+ my %params = validate( @_, \%spec );
+ }
+
+ You can also use the state feature to do this:
+
+ use feature 'state';
+
+ sub foo {
+ state $spec = { ... };
+ my %params = validate( @_, $spec );
+ }
+
+"GLOBAL" OPTIONS
+
+ Because the API for the validate() and validate_pos() functions does
+ not make it possible to specify any options other than the validation
+ spec, it is possible to set some options as pseudo-'globals'. These
+ allow you to specify such things as whether or not the validation of
+ named parameters should be case sensitive, for one example.
+
+ These options are called pseudo-'globals' because these settings are
+ only applied to calls originating from the package that set the
+ options.
+
+ In other words, if I am in package Foo and I call validation_options(),
+ those options are only in effect when I call validate() from package
+ Foo.
+
+ While this is quite different from how most other modules operate, I
+ feel that this is necessary in able to make it possible for one
+ module/application to use Params::Validate while still using other
+ modules that also use Params::Validate, perhaps with different options
+ set.
+
+ The downside to this is that if you are writing an app with a standard
+ calling style for all functions, and your app has ten modules, each
+ module must include a call to validation_options(). You could of course
+ write a module that all your modules use which uses various trickery to
+ do this when imported.
+
+ Options
+
+ * normalize_keys => $callback
+
+ This option is only relevant when dealing with named parameters.
+
+ This callback will be used to transform the hash keys of both the
+ parameters and the parameter spec when validate() or validate_with()
+ are called.
+
+ Any alterations made by this callback will be reflected in the
+ parameter hash that is returned by the validation function. For
+ example:
+
+ sub foo {
+ return validate_with(
+ params => \@_,
+ spec => { foo => { type => SCALAR } },
+ normalize_keys =>
+ sub { my $k = shift; $k =~ s/^-//; return uc $k },
+ );
+
+ }
+
+ %p = foo( foo => 20 );
+
+ # $p{FOO} is now 20
+
+ %p = foo( -fOo => 50 );
+
+ # $p{FOO} is now 50
+
+ The callback must return a defined value.
+
+ If a callback is given then the deprecated "ignore_case" and
+ "strip_leading" options are ignored.
+
+ * allow_extra => $boolean
+
+ If true, then the validation routine will allow extra parameters not
+ named in the validation specification. In the case of positional
+ parameters, this allows an unlimited number of maximum parameters
+ (though a minimum may still be set). Defaults to false.
+
+ * on_fail => $callback
+
+ If given, this callback will be called whenever a validation check
+ fails. It will be called with a single parameter, which will be a
+ string describing the failure. This is useful if you wish to have
+ this module throw exceptions as objects rather than as strings, for
+ example.
+
+ This callback is expected to die() internally. If it does not, the
+ validation will proceed onwards, with unpredictable results.
+
+ The default is to simply use the Carp module's confess() function.
+
+ * stack_skip => $number
+
+ This tells Params::Validate how many stack frames to skip when
+ finding a subroutine name to use in error messages. By default, it
+ looks one frame back, at the immediate caller to validate() or
+ validate_pos(). If this option is set, then the given number of
+ frames are skipped instead.
+
+ * ignore_case => $boolean
+
+ DEPRECATED
+
+ This is only relevant when dealing with named parameters. If it is
+ true, then the validation code will ignore the case of parameter
+ names. Defaults to false.
+
+ * strip_leading => $characters
+
+ DEPRECATED
+
+ This too is only relevant when dealing with named parameters. If this
+ is given then any parameters starting with these characters will be
+ considered equivalent to parameters without them entirely. For
+ example, if this is specified as '-', then -foo and foo would be
+ considered identical.
+
+PER-INVOCATION OPTIONS
+
+ The validate_with() function can be used to set the options listed
+ above on a per-invocation basis. For example:
+
+ my %p = validate_with(
+ params => \@_,
+ spec => {
+ foo => { type => SCALAR },
+ bar => { default => 10 }
+ },
+ allow_extra => 1,
+ );
+
+ In addition to the options listed above, it is also possible to set the
+ option "called", which should be a string. This string will be used in
+ any error messages caused by a failure to meet the validation spec.
+
+ This subroutine will validate named parameters as a hash if the "spec"
+ parameter is a hash reference. If it is an array reference, the
+ parameters are assumed to be positional.
+
+ my %p = validate_with(
+ params => \@_,
+ spec => {
+ foo => { type => SCALAR },
+ bar => { default => 10 }
+ },
+ allow_extra => 1,
+ called => 'The Quux::Baz class constructor',
+ );
+
+ my @p = validate_with(
+ params => \@_,
+ spec => [
+ { type => SCALAR },
+ { default => 10 }
+ ],
+ allow_extra => 1,
+ called => 'The Quux::Baz class constructor',
+ );
+
+DISABLING VALIDATION
+
+ If the environment variable PERL_NO_VALIDATION is set to something
+ true, then validation is turned off. This may be useful if you only
+ want to use this module during development but don't want the speed hit
+ during production.
+
+ The only error that will be caught will be when an odd number of
+ parameters are passed into a function/method that expects a hash.
+
+ If you want to selectively turn validation on and off at runtime, you
+ can directly set the $Params::Validate::NO_VALIDATION global variable.
+ It is strongly recommended that you localize any changes to this
+ variable, because other modules you are using may expect validation to
+ be on when they execute. For example:
+
+ {
+ local $Params::Validate::NO_VALIDATION = 1;
+
+ # no error
+ foo( bar => 2 );
+ }
+
+ # error
+ foo( bar => 2 );
+
+ sub foo {
+ my %p = validate( @_, { foo => 1 } );
+ ...;
+ }
+
+ But if you want to shoot yourself in the foot and just turn it off, go
+ ahead!
+
+TAINT MODE
+
+ The XS implementation of this module has some problems Under taint mode
+ with version of Perl before 5.14. If validation fails, then instead of
+ getting the expected error message you'll get a message like "Insecure
+ dependency in eval_sv". This can be worked around by either untainting
+ the arguments yourself, using the pure Perl implementation, or
+ upgrading your Perl.
+
+LIMITATIONS
+
+ Right now there is no way (short of a callback) to specify that
+ something must be of one of a list of classes, or that it must possess
+ one of a list of methods. If this is desired, it can be added in the
+ future.
+
+ Ideally, there would be only one validation function. If someone
+ figures out how to do this, please let me know.
+
+SUPPORT
+
+ Please submit bugs and patches to the CPAN RT system at
+ http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Params%3A%3AValidate or
+ via email at bug-params-validate@rt.cpan.org.
+
+ Support questions can be sent to Dave at autarch@urth.org.
+
+DONATIONS
+
+ If you'd like to thank me for the work I've done on this module, please
+ consider making a "donation" to me via PayPal. I spend a lot of free
+ time creating free software, and would appreciate any support you'd
+ care to offer.
+
+ Please note that I am not suggesting that you must do this in order for
+ me to continue working on this particular software. I will continue to
+ do so, inasmuch as I have in the past, for as long as it interests me.
+
+ Similarly, a donation made in this way will probably not make me work
+ on this software much more, unless I get so many donations that I can
+ consider working on free software full time, which seems unlikely at
+ best.
+
+ To donate, log into PayPal and send money to autarch@urth.org or use
+ the button on this page: http://www.urth.org/~autarch/fs-donation.html
+
+AUTHORS
+
+ * Dave Rolsky <autarch@urth.org>
+
+ * Ilya Martynov <ilya@martynov.org>
+
+CONTRIBUTORS
+
+ * Ivan Bessarabov <ivan@bessarabov.ru>
+
+ * J.R. Mash <jmash.code@gmail.com>
+
+ * Noel Maddy <zhtwnpanta@gmail.com>
+
+ * Olivier Mengué <dolmen@cpan.org>
+
+ * Vincent Pit <perl@profvince.com>
+
+COPYRIGHT AND LICENSE
+
+ This software is Copyright (c) 2001 - 2015 by Dave Rolsky and Ilya
+ Martynov.
+
+ This is free software, licensed under:
+
+ The Artistic License 2.0 (GPL Compatible)
+