use warnings; use strict; use feature 'state'; use Carp; use Config; sub validate_int { my $str = shift; state $max = int(eval $Config{nv_overflows_integers_at} or die); croak "not an integer" unless defined $str && $str=~/\A[0-9]+\z/; $str =~ s/\A0+(?=[1-9])//; croak "integer too big" if length $str > length $max || sprintf("%0*s", length $max, $str) gt $max; return 0+$str; } use Math::BigInt; use Test::More; sub exception (&) { eval { shift->(); 1 } ? undef : ($@ || die) } is validate_int(0), 0; is validate_int(1), 1; is validate_int(3), 3; is validate_int("000000000000000000000000000000000000000001"), 1; ok exception { validate_int(undef) }; ok exception { validate_int("") }; ok exception { validate_int("x") }; ok exception { validate_int("123y") }; ok exception { validate_int(-1) }; ok exception { validate_int("-9999999999999999999999999999999") }; my $x = Math::BigInt->new(eval $Config{nv_overflows_integers_at})-1; is validate_int("$x"), 0+$x->numify, "'$x' works (max-1)"; $x++; is validate_int("$x"), 0+$x->numify, "'$x' works (max)"; $x++; ok exception { validate_int("$x") }, "'$x' fails (max+1)"; ok exception { validate_int("999999999999999999999999999999999999") }; done_testing;