I've put together a couple of subroutines to pack and unpack binary strings. They allow for any length of string by prepending the original string length to the packed string so that the right string length can be used in the unpack template, e.g. b45 rather than b*. That way you don't get extra zeros padding the unpacked binary string. Here is a script that tests packing and unpacking random binary strings of a given length one hundred times. I have tested with strings of 12000 digits with no problem. Here it is
use strict;
use warnings;
# Get and length of binary string to test from
# command line and validate.
#
my $teslLen = shift
or die qq{No string length supplied\n};
die qq{Length supplied not integer\n}
unless $teslLen =~ /^\d+$/;
# Test one hundred strings of requested length.
#
for (1 .. 100)
{
print qq{\nIteration $_\n};
# Create string and print it's length.
#
my $binStr = makeBinStr($teslLen);
print qq{Original length is @{[length $binStr]}\n};
# Pack string, show packed length.
#
my $packedStr = packBinStr($binStr);
print qq{ Packed length is @{[length $packedStr]}\n};
# Reconstruct original, show length again.
#
my $unpackedStr = unpackBinStr($packedStr);
print qq{Unpacked length is @{[length $binStr]}\n};
# Die unless original and reconstructed match.
#
die q{Unpacked does not match original},
qq{\n$binStr\n$unpackedStr\n}
unless $binStr eq $unpackedStr;
}
# Make a random binary string of requested length.
#
sub makeBinStr
{
my $digits = shift;
my $str = q{};
$str .= int rand 2 for 1 .. $digits;
return $str;
}
sub packBinStr
{
# Get binary string and validate.
#
my $unpacked = shift;
die qq{String not binary\n}
unless $unpacked =~ /^[01]+$/;
# Get length of binary string, pack the string using
# correct length in the template. Prepend length and an
# asterisk to packed string so that correct length
# can be used when unpacking later. Return packed string.
#
my $len = length $unpacked;
my $packed = qq{$len*} . pack qq{b$len}, $unpacked;
return $packed;
}
sub unpackBinStr
{
# Get packed string and split on asterisk, use three-
# argument split so that we only get two fields back
# in case the packed string contains an asterisk.
#
my $packed = shift;
my ($len, $packStr) = split /\*/, $packed, 2;
# Unpack using correct length in template, return
# binary string.
#
my $unpacked = unpack qq{b$len}, $packStr;
return $unpacked;
}
Give it an argument of the length of string you want to test. I hope that it is useful. Cheers, JohnGG
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.
|