Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • So here's a thought: most uses of pack should be wrapped up in a small subroutine, shouldn't they? I mean, if you are unpacking a struct, make two routines (to convert either direction) that take binary data on one end and an array, hash, or object on the other.
    Eh... I have to confess, I've written pretty much such a module... I haven't released it to the public, and likely I never will, because, well, you can read the responses from other people here.

    I wrote it, when trying to convert the utility program macfont [tug.org], which is originally written in C, to Perl. A huge part of that program is reading structures from the font file, interpreting the data, and following pointers. It would have been much harder to write, without the help from this little module.

    So how does it work? You create a Pack::Struct object, while specifying the structure you're trying to handle. This specification gets used for a template for both pack() and unpack(). There's no real saving there, you still have to learn about the basic templates for pack. But: it also doubles as a list of keys for the hash, so when you unpack the structure into a record, it returns a hash filled with the unpacked data. The main advantage is that it reduces redundancy. As a drawback, it poses some restrictions on the kind of structures you can read. Most of all, the basic templates must act symmetrically in pack() and unpack(). Variable length data is out, fixed length records only. Included arrays and even nested structures are possible. There's even a callback mechanism to be able to provide strangely formatted fields, such as a 3 byte integer.

    As a result, the perl code is at least as readable as the C source code — fare more so, if you ask me, but I'm biased. Let me give you a code example, a snippet from my script...

    use Pack::Struct;
    my $RsrcHdrStruct = new Pack::Struct(
      DataOffset => 'N',
      MapOffset => 'N',
      DataLen => 'N',
      MapLen => 'N',
      OSReserved => ['x96'],
      AppReserved => ['x128']
    );

    read INPUT, $_, $RsrcHdrStruct->length;
    my $Mac_header = $RsrcHdrStruct->unpack($_);  # This returns a hash ref

    seek INPUT, $Mac_header->{MapOffset}, 0;

    my $RsrcMapStruct = new Pack::Struct (
      MapCopy => ['N' => 4 ],
      NextMap => 'N',
      FileRef => 'n',
      FileAttr => 'n',
      TypeOffset => 'n',
      NameOffset => 'n'
    );
    read INPUT, $_, $RsrcMapStruct->length;
    my $Mac_map = $RsrcMapStruct->unpack($_);

    seek INPUT, $Mac_header->{MapOffset} + $Mac_map->{TypeOffset}, 0;
    read INPUT, $_, 2;
    my $Mac_typeCount = 1 + unpack 'n', $_;
    # etc...
    You can compare this to the C structs of the same name in mactypes.h [tug.org] (lines 31-47); to the code to read the structs from the file, in macio.c [tug.org] containing the definitions of the functions read_mac_header() and read_mac_map() (lines 80-114); and the snippet that knits it all together by calling these two functions, in macfont.c [tug.org] (lines 721-732).

    Hmm... Now that I look at it again, despite everything, perhaps it might be an interesting module to release, anyway?

    • Eh... I have to confess, I've written pretty much such a module... I haven't released it to the public, and likely I never will, because, well, you can read the responses from other people here.

      Why not????? Don't let the opinions of people sway your view of how useful the module is, nor let you pass up a chance to submit it to others to see how useful they think it is. We operate on the economy of ideas. Just because your idea doesn't work for some people doesn't mean everyone will dislike it. That'

      --
      J. David works really hard, has a passion for writing good software, and knows many of the world's best Perl programmers
    • I think it sounds like a good idea. It also sounds a lot like the newly released Win32::API where I think you can do something similar when calling funcions with C structs.