--- /dev/null
+#!/usr/bin/perl -w
+
+use Benchmark qw(timethese cmpthese countit timestr);
+use CGI::Ex::Validate;
+use Data::FormValidator;
+
+my $form = {
+ username => "++foobar++",
+ password => "123",
+ password2 => "1234",
+};
+
+my $val_hash_ce = {
+ username => {
+ required => 1,
+ match => 'm/^\w+$/',
+ match_error => '$name may only contain letters and numbers',
+ untaint => 1,
+ },
+ password => {
+ required => 1,
+ match => 'm/^[ -~]{6,30}$/',
+# min_len => 6,
+# max_len => 30,
+# match => 'm/^[ -~]+$/',
+ untaint => 1,
+ },
+ password2 => {
+ validate_if => 'password',
+ equals => 'password',
+ },
+ email => {
+ required => 1,
+ match => 'm/^[\w\.\-]+\@[\w\.\-]+$/',
+ untaint => 1,
+ },
+};
+
+my $val_hash_df = {
+ required => [qw(username password email)],
+ dependencies => {
+ password => [qw(password2)],
+ },
+ constraints => {
+ email => qr/^[\w\.\-]+\@[\w\.\-]+$/,
+ password => qr/^[ -~]{6,30}$/,
+ username => qr/^\w+$/,
+ },
+ untaint_all_constraints => 1,
+ msgs => {
+ format => '%s',
+ prefix => 'error_',
+ },
+};
+
+sub check_form {
+ my $form = shift;
+ my $hash = {};
+ if (! exists $form->{'username'}) {
+ push @{ $hash->{'username_error'} }, 'Username required';
+ } elsif ($form->{'username'} !~ m/^(\w+)$/) {
+ push @{ $hash->{'username_error'} }, 'Username may only contain letters and numbers';
+ } else {
+ $form->{'username'} = $1;
+ }
+ if (! exists $form->{'password'}) {
+ push @{ $hash->{'password_error'} }, 'Password required';
+ } else {
+ if ($form->{'password'} !~ m/^([ -~]+)$/) {
+ push @{ $hash->{'password_error'} }, 'Password contained bad characters';
+ } else {
+ $form->{'password'} = $1;
+ }
+ if (length($form->{'password'}) < 6) {
+ push @{ $hash->{'password_error'} }, 'Password must be more than 6 characters';
+ } elsif (length($form->{'password'}) > 30) {
+ push @{ $hash->{'password_error'} }, 'Password must be less than 30 characters';
+ }
+
+ if (! defined($form->{'password2'})
+ || $form->{'password2'} ne $form->{'password'}) {
+ push @{ $hash->{'password2_error'} }, 'Password2 and password must be the same';
+ }
+ }
+
+ if (! exists $form->{'email'}) {
+ push @{ $hash->{'email_error'} }, 'Email required';
+ } elsif ($form->{'email'} !~ m/^[\w\.\-]+\@[\w\.\-]+$/) {
+ push @{ $hash->{'email_error'} }, 'Please type a valid email address';
+ }
+
+ return $hash;
+}
+
+
+cmpthese (-2,{
+ cgi_ex => sub { my $t = CGI::Ex::Validate->validate($form, $val_hash_ce) },
+ data_val => sub { my $t = Data::FormValidator->check($form, $val_hash_df) },
+ homegrown => sub { my $t = scalar keys %{ check_form($form) } },
+},'auto');
+
+cmpthese (-2,{
+ cgi_ex => sub { my $t = CGI::Ex::Validate->validate($form, $val_hash_ce)->as_hash },
+ data_val => sub { my $t = Data::FormValidator->check($form, $val_hash_df)->msgs },
+ homegrown => sub { my $t = check_form($form) },
+},'auto');
+
+
+### Home grown solution blows the others away - but lacks features
+#
+# Benchmark: running cgi_ex, data_val, homegrown for at least 2 CPU seconds...
+# cgi_ex: 2 wallclock secs ( 2.12 usr + 0.00 sys = 2.12 CPU) @ 1430.66/s (n=3033)
+# data_val: 2 wallclock secs ( 2.01 usr + 0.00 sys = 2.01 CPU) @ 2588.56/s (n=5203)
+# homegrown: 2 wallclock secs ( 2.19 usr + 0.01 sys = 2.20 CPU) @ 54733.18/s (n=120413)
+# Rate cgi_ex data_val homegrown
+# cgi_ex 1431/s -- -45% -97%
+# data_val 2589/s 81% -- -95%
+# homegrown 54733/s 3726% 2014% --
+# Benchmark: running cgi_ex, data_val, homegrown for at least 2 CPU seconds...
+# cgi_ex: 2 wallclock secs ( 2.10 usr + 0.00 sys = 2.10 CPU) @ 1218.57/s (n=2559)
+# data_val: 2 wallclock secs ( 2.14 usr + 0.00 sys = 2.14 CPU) @ 2092.99/s (n=4479)
+# homegrown: 2 wallclock secs ( 2.14 usr + 0.00 sys = 2.14 CPU) @ 56267.76/s (n=120413)
+# Rate cgi_ex data_val homegrown
+# cgi_ex 1219/s -- -42% -98%
+# data_val 2093/s 72% -- -96%
+# homegrown 56268/s 4518% 2588% --