[Dub-pm] Quick pack question.

Fergal Daly fergal at esatclear.ie
Wed Oct 13 09:01:00 CDT 2004

On Wed, Oct 13, 2004 at 02:17:06PM +0100, Aidan Kehoe wrote:
>  Ar an tri? l? d?ag de m? Deireadh F?mhair, scr?obh Mcnamara John: 
>  > Here is one way to do it (if I have understood correctly):
> Hmm, thanks for that, but there's relatively little pack magic compared to
> what I had a gut feeling, was possible. Ah well. Pack seems more oriented to
> quanities greater than a byte.

pack does have some bit oriented features but it always takes a list and
unpack always returns a list so it would be out of character for pack to
take one kind of string and produce another.

You can do what you're after with an unpack, a substitution and then a pack.
Here's a subroutine to do it, another to undo it and some code to show it in
action. I don't know about the performance. I'd guess it's fairly snappy
although very long strings might chew memory a bit. If you need to handle
long strings, you could always split them into smaller chunks.

Not sure how it ports to PHP, 


sub seven2eight
  my $in = shift;
  $in = unpack("b*", $in); # turns it into a string of 1s and 0s
  $in =~ s/(.{7})/${1}0/g; # slip a 0 in after every 7th bit
  return pack("b*", $in);  # turn it back into binary

sub eight2seven
  my $in = shift;
  $in = unpack("b*", $in);
  $in =~ s/(.{7})./${1}/g; # remove the 0 that comes after every 7th bit
  return pack("b*", $in);

my $string = "abcdefgh";

print unpack("b*", $string)."\n";

my $new_string = eight2seven($string);
print unpack("b*", $new_string)."\n";
my $undone = seven2eight($new_string);

print "reversing the process\n";
print "'$undone' eq '$string'\n";

if ($undone eq $string)
  print "ok\n";
  print "not ok!!!\n";

More information about the Dublin-pm mailing list