문제

I want to pack various results of expressions with integer overflow checking in Perl (signed, unsigned, big-endian and little-endian). If I try:

$ perl -e 'use warnings; print pack("c", 200)' | hexdump -C

I get:

Character in 'c' format wrapped in pack at -e line 1.
00000000  c8                                                |.|
00000001

Is there a way to check the integer overflow occurred in the pack() function? Or maybe force the function to fail on overflow? If I will check the range for each type before packing (signed 1,2,4,8 bytes, unsigned 1,2,4,8), the code seems slightly ugly.

Thanks.

도움이 되었습니까?

해결책

You can turn on the "pack" warning category and make it fatal. Then an overflow would cause an exception which can be trapped. E.g.:

for my $val (127, 128) {
    print "$val -> ";
    if (eval {
        use warnings FATAL => qw(pack);
        pack("c", $val);
    }) {
        print "no overflow";
    } else {
        print "overflow ($@)";
    }
    print "\n";
}

Another possibility is to use a (preferably local-ized) $SIG{__WARN__} handler and check in the handler if a warning happened.

다른 팁

Fatalizing warnings is the simplest solution, but you could write your own packing functions.

use Carp         qw( croak );
use Scalar::Util qw( looks_like_number );

sub pack_uint32_be {
   my ($n) = @_;
   croak "Not a number" unless looks_like_number($n);
   croak "Overflow"     unless 0 < $n && $n <= 2**32;
   return pack 'L>', $n;
}

$packed .= pack_uint32_be($x);
$packed .= pack_uint32_be($y);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top