http://www.perlmonks.org?node_id=1035514


in reply to how to unpack a C struct with length array preceding data array

From Re^4: how to unpack a C struct with length array preceding data array (emphases added):

I do agree with ig though, you should avoid [ig's] solution if possible, it's hard to read, and it would be difficult to expand it for a string of three parts or more.

In the spirit of ig's ingenious reply and of Anonymonk's excellent explication, here's a version that unpacks four data items in a single unpack statement (the initial  s4 is optional if you don't care about all the length info):

>perl -wMstrict -MData::Dump -le "my $str = qq{\x05\x00\x08\x00\x05\x00\x06\x00Just Another pack Hacker +}; ;; my $template = q{ ( s4 @0 x[s0] s @0 s0 x[s4] /a @0 x[s1] s @0 s1 x[s3] /x /a @0 x[s2] s @0 s2 x[s2] /x /x /a @0 x[s3] s @0 s3 x[s1] /x /x /x /a ) }; ;; my @ra = unpack $template, $str; dd \@ra; " [5, 8, 5, 6, "Just ", "Another ", "pack ", "Hacker"]

As you can see, this is pretty orthogonal and easily generalized to any number of data items. (I can post the code to generate the unpack template for any array 'type' and any number of data items on my scratch pad if anyone's interested.) It also involves a lot of shuttling back and forth to pick up and use the various unpack elements, and this has the odor of wasted motion. One can also see how such a template could grow rather unwieldy if one were dealing with 400 or 4000 data items rather than just four.

All the admonitions remain in force: this is a trick you should only try at home, never in any public, much less any occupational, venue.

I suspect that a much more concise version of this exists. Ideally, I would like to wind up with a template looking something like
    ((clever unpack template)n)
where n is the number of data items to be unpacked; i.e., to roll up what is effectively an unrolled loop. Unfortunately, I just can't see my way clear to this solution. I'll keep trying...