J
J. Romano
Dear All,
I recently got burned with some code that I wrote, so I thought I
might share it with you all (at least to raise awareness):
I was packing a string with a line like:
$packedString = pack("a10",$text);
and unpacking with a line like:
$text2 = unpack("A10",$packedString);
I packed the text with "a" because I wanted to pad the remaining
spaces with null characters, and I unpacked the same string with "A"
because, according to the documentation, "A" strips trailing spaces
and nulls.
So as long as the $text variable doesn't have any trailing spaces
(and assuming it's not longer than 10 characters), $text2 should
always be the same as $text, right?
Well, no, it's not. Apparently, if $text ends with any number of
newlines (like "Hello!\n\n\n\n"), the newlines will get stripped off
when it is unpacked with "A", even though the documentation only says
that trailing spaces and null will be stripped off (while making no
mention of other types of whitespace). I tried this on Linux and
Win32, and they both behave the same way. It took me a while to
figure this out when I was hunting down a bug in one of my scripts.
Another thing I found that was not correct was in the perldoc for
"pack". It explicitly says: 'When packing, "a", and "Z" are
equivalent.' However, I found (at least on Linux and
Win32-ActiveState) that "Z" will always null-terminate a string, even
if it means an extra character of the string gets cut off.
Here's a short perl script to demontrate:
#!/usr/bin/perl -w
use strict;
my $text = "1234567890";
my $a_packed = pack('a5', $text);
my $Z_packed = pack('Z5', $text);
my $a_len = length($a_packed);
my $Z_len = length($Z_packed);
print "\$a_packed: \"$a_packed\" (length = $a_len)\n";
print "\$Z_packed: \"$Z_packed\" (length = $Z_len)\n";
__END__
This script prints:
$a_packed: "12345" (length = 5)
$Z_packed: "1234" (length = 5)
According to the perldoc, "a" and "Z" are equivalent when used with
"pack", yet apparently they are not here, or else $a_packed and
$z_packed would be identical strings. Apparently "Z" always
null-terminates the string, even if the string is longer than the
length of the field to pack it in.
So this is either a bug with the pack function or else the perldoc
documentation is a little wrong. I would like to use packing with "Z"
in one of my scripts, but I'm a little hesitant to do so until I know
how it's supposed to work (and that it's working correctly).
Does anybody know what the correct behavior of pack("Z5",$text)
should be?
(And is unpacking with "A" supposed to strip off any trailing
newlines or whitespace?)
Thanks.
-- J.
I recently got burned with some code that I wrote, so I thought I
might share it with you all (at least to raise awareness):
I was packing a string with a line like:
$packedString = pack("a10",$text);
and unpacking with a line like:
$text2 = unpack("A10",$packedString);
I packed the text with "a" because I wanted to pad the remaining
spaces with null characters, and I unpacked the same string with "A"
because, according to the documentation, "A" strips trailing spaces
and nulls.
So as long as the $text variable doesn't have any trailing spaces
(and assuming it's not longer than 10 characters), $text2 should
always be the same as $text, right?
Well, no, it's not. Apparently, if $text ends with any number of
newlines (like "Hello!\n\n\n\n"), the newlines will get stripped off
when it is unpacked with "A", even though the documentation only says
that trailing spaces and null will be stripped off (while making no
mention of other types of whitespace). I tried this on Linux and
Win32, and they both behave the same way. It took me a while to
figure this out when I was hunting down a bug in one of my scripts.
Another thing I found that was not correct was in the perldoc for
"pack". It explicitly says: 'When packing, "a", and "Z" are
equivalent.' However, I found (at least on Linux and
Win32-ActiveState) that "Z" will always null-terminate a string, even
if it means an extra character of the string gets cut off.
Here's a short perl script to demontrate:
#!/usr/bin/perl -w
use strict;
my $text = "1234567890";
my $a_packed = pack('a5', $text);
my $Z_packed = pack('Z5', $text);
my $a_len = length($a_packed);
my $Z_len = length($Z_packed);
print "\$a_packed: \"$a_packed\" (length = $a_len)\n";
print "\$Z_packed: \"$Z_packed\" (length = $Z_len)\n";
__END__
This script prints:
$a_packed: "12345" (length = 5)
$Z_packed: "1234" (length = 5)
According to the perldoc, "a" and "Z" are equivalent when used with
"pack", yet apparently they are not here, or else $a_packed and
$z_packed would be identical strings. Apparently "Z" always
null-terminates the string, even if the string is longer than the
length of the field to pack it in.
So this is either a bug with the pack function or else the perldoc
documentation is a little wrong. I would like to use packing with "Z"
in one of my scripts, but I'm a little hesitant to do so until I know
how it's supposed to work (and that it's working correctly).
Does anybody know what the correct behavior of pack("Z5",$text)
should be?
(And is unpacking with "A" supposed to strip off any trailing
newlines or whitespace?)
Thanks.
-- J.