in reply to Compensate for bad inet checksum routine

Probably slower, but leveraging RE's and getting rid of the copy to $padded makes it more compact.
sub prepchksum { my ($payload) = @_; printf "BEFORE = %s\n", (CORE::unpack "H*", $payload); if (length($payload)%2) { $payload =~ s#(.)$#\0$1#; printf "MID1 = %s\n", (CORE::unpack "H*", $payload); # Compensate off-by-one error if (ord(substr $payload, -1) >= 128) { $payload=~s#(.)(.)$#pack('CC',(ord($1)-1)&255, (ord($2)-1)&255)#e; } } printf "AFTER = %s\n", (CORE::unpack "H*", $payload); }

Replies are listed 'Best First'.
Re^2: Compensate for bad inet checksum routine
by kschwab (Vicar) on Mar 29, 2013 at 17:15 UTC
    Just noticed this...
    In both the original, and my version, there seems to be some wasted logic. See comments that start with ## below.
    if (length($payload)%2) { my $padded = substr $payload, 0, -1; $padded .= "\0"; $padded .= substr $payload, -1; ## above: ok, so the next to the last byte ## is guaranteed to be null since we just ## explicitly set it if (ord(substr $padded, -1) >= 128) { my $end = ord(substr $padded, -2, 1); ## ## above: now we're grabbing the next to the last ## byte, even though we already know it's a null? ## my $endend = ord(substr $padded, -1); $end--; ## now we decrement it, knowing full well it's ## going to be -1? $endend--; ###DEBUG: printf "CMPSAT = %i %i\n", $end, $endend; # if 0 before --, then -1 results in warning to pack below # -1 is in essense \xff or 255 if ($end == -1) { $end = 255 } ## ## above,of course, it's going to == -1, and thus ## at this point, always reset to 255 ## if ($endend == -1) { $endend = 255 } $padded = substr $padded, 0, -2; $padded .= CORE::pack('CC', $end, $endend); } $payload = $padded; }
    It would seem then, that you could simplify all of that out, and just decrement the last byte by one?
    sub prepchksum { my ($payload) = @_; printf "BEFORE = %s\n", (CORE::unpack "H*", $payload); if (length($payload)%2) { $payload =~ s#(.)$#\0$1#; printf "MID1 = %s\n", (CORE::unpack "H*", $payload); # Compensate off-by-one error if (ord(substr $payload, -1) >= 128) { $payload=~s#(.)$#pack('C',(ord($2)-1)&255)#e; } } printf "AFTER = %s\n", (CORE::unpack "H*", $payload); }
    Or perhaps there's a bug somewhere, either in the 'C' implementation you based this on, or your original port?
      Argh. Meant to simplify by decrementing the last byte and explicity setting the the next to last byte to 255
      sub prepchksum { my ($payload) = @_; printf "BEFORE = %s\n", (CORE::unpack "H*", $payload); if (length($payload)%2) { $payload =~ s#(.)$#\0$1#; printf "MID1 = %s\n", (CORE::unpack "H*", $payload); # Compensate off-by-one error if (ord(substr $payload, -1) >= 128) { $payload=~s#(.)(.)$#pack('CC',255, (ord($2)-1)&255)#e; } } printf "AFTER = %s\n", (CORE::unpack "H*", $payload); }

      You know, I thought about that and wasn't sure I had all the cases. I do appreciate you seeing it also and confirming that the logic was extra and able to be eliminated.