I need pack examples for the Camel

I'm working on the pack section in Programming Perl and learning about all the templates things that I've never used.

Does anyone have examples (or know where some are) that use:

  • @ with a repeat count
  • . with a repeat count
  • ( with a repeat count

Also, which modules make extensive use of pack? I used to in my Mac::iTunes (now outdated) module, but I was going very rudimentary things that I now see I could have done much better with other pack features.

Google Code Search for "pack(" turns up a lot of everyone's favorite CGI parameter undo-er, many Perl/Tk things, and lots of simple templates for pack. I want to see the really knarly and mind bending ones. Send me a good one that we put in the book, and I'll send you the book for free.

7 Comments

I don't have any of those, though I did write some fun last week writing these:

my ($magic, $version, $index_offset, $index_length, $number_of_reads, $header_length, $key_length, $number_of_flows_per_read, $flowgram_format_code) = unpack 'a4NQ>NNnnnC', substr $content, 0, 31;
my ($flow_chars, $key_sequence) = unpack sprintf('A%dA%d', $number_of_flows_per_read, $key_length), substr $content, 31 ,$header_length;
.

Spreadsheet::WriteExcel makes extensive use of pack() . It uses it around 800 times to construct a variety of binary records that comprise an Excel file.


It doesn't use any particularly interesting pack templates though. It is all fairly vanilla.


Here is a simple but useful pack construct that I use in testing a lot to convert some hexdumped data back to the original structure:


my $data = pack 'H*', join '', qw (
FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 60
00 60 00 00 FF DB 00 43 00 06 04 05 06 05 04 06
06 05 06 07 07 06 08 0A 10 0A 0A 09 09 0A 14 0E
0F 0C 10 17 14 18 18 17 14 16 16 1A 1D 25 1F 1A
);

On the mind bending front here is a old JAPH of mine that writes the usual phrase to an Excel binary file. Probably not suitable for publication though.

open Japh,">Just_Another_Perl_Hacker.xls" and binmode Japh;
$/= pack "C2v2V2VdC2V2v", 9,8,8,5,16,0,10,0,4,2,32,0,24;
$\= pack "V", +1 +1 +1 +1 +1 +1 +1 +1 +1 +1;
print Japh $/. 'Just Another Perl Hacker';

I don't have a good example using @ or any of the things you asked for, but I do have an example that's interesting in its own way.

Years ago, in Freenode #perl, I was working with someone who was getting the output of a mysql query from the mysql CLI. They insisted that, due to reasons beyond their control, they couldn't possibly run the query using DBI, or change the output options on the CLI, or anything that would be sensible. So the task was to parse data looking like:


+-----+-----+-----+
| foo | bar | baz |
+-----+-----+-----+
|   1 |   2 |   3 |
|  23 |  42 | 413 | 
+-----+-----+-----+

Which was accomplished using something like


my @widths = map length, $first_line =~ /(-+)/g;
my $template = join "", map "xA$_", @widths;
my @columns = unpack $template, ;
<$fh>;
while (<$fh>) {
    my %row;
    @row{@columns} = unpack $template, $_;
    process(\%row);
}

Except with more polish on it :)

Does anyone else see a "pack of Camels" joke here? No one? Ok fine.

A stackoverflow search might be:
http://stackoverflow.com/search?q=%5Bperl%5D+body%3Apack&submit=search

brian d foy asks

Also, which modules make extensive use of pack?

Any of the pure-Perl image parsing modules does. For example, Image::ExifTools, in particular Image::ExifTools::PNG. See also Image::PNG::Rewriter, Image::Pngslimmer.

A pure-Perl png decoder/encoder using pack and unpack would make a nice example of parsing binary formats for an advanced Perl book.

The older, pre-Encode modules for handling multibyte characters, e.g. Japanese characters, used pack/unpack a lot but those are mostly obsolete now.

Leave a comment

About brian d foy

user-pic I'm the author of Mastering Perl, and the co-author of Learning Perl (6th Edition), Intermediate Perl, Programming Perl (4th Edition) and Effective Perl Programming (2nd Edition).