in reply to pack/unpack woes

Win8 Strawberry 5.30.3.1 (64) Tue 06/14/2022 17:01:38 C:\@Work\Perl\monks >perl use strict; use warnings; use Data::Dump qw/dd pp/; my $ogg_head = pack 'H*', '4F6767530002000000000000000083CA3DC0000000009F59730A0113'; dd $ogg_head; # for debug my ($ogg_magic, $opus_version, $flags, $granule_position, $serial_number, $sequence_number, $checksum, $total_segments, $segment_size) = # unpack('C4 C1 C1 C8 C4 C4 C4 C1 C1', $buf); unpack('a4 C C Q N N N C C', $ogg_head); print "'$ogg_magic' \n"; dd $ogg_magic, $opus_version, $flags, $granule_position, $serial_number, $sequence_number, $checksum, $total_segments, $segment_size; printf "%s %02x %02x %08x %04x %04x %04x %02x %02x \n", $ogg_magic, $opus_version, $flags, $granule_position, $serial_number, $sequence_number, $checksum, $total_segments, $segment_size; ^Z pack("H*","4f6767530002000000000000000083ca3dc0000000009f59730a0113") 'OggS' ("OggS", 0, 2, 0, 2211069376, 0, 2673439498, 1, 19) OggS 00 02 00000000 83ca3dc0 0000 9f59730a 01 13
Note: Check that your version of Perl supports the Q pack/unpack template specifier.


Give a man a fish:  <%-{-{-{-<

Replies are listed 'Best First'.
Re^2: pack/unpack woes
by ikegami (Patriarch) on Jun 14, 2022 at 21:31 UTC

    A little explanation of the changes, with some corrections:

    C4 is the same as C C C C. It extracts 4 numbers.

    $ perl -e'printf "0x%X\n", $_ for unpack "C4", "\x12\x34\x56\x78"' 0x12 0x34 0x56 0x78

    But that's not what you want. You want to extract a single 32-bit unsigned integer in little-endian byte order.[1] After consulting Mini-Tutorial: Formats for Packing and Unpacking Numbers, we determine that we need L< or V for that.

    $ perl -e'printf "0x%X\n", $_ for unpack "L<", "\x12\x34\x56\x78"' 0x78563412

    So, what you want is

    unpack( 'a4 C C Q< L< L< L< C', $ogg_head )

    Note that this is only 27 bytes, not 28. The number of remaining bytes is indicated by that last field (the 27th byte), and may be a number other than one.

    As hinted by the parent, Q is only available on builds of Perl with 64-bit integers (i.e. where perl -V:uvsize aka perl -Mv5.10 -MConfig -e'say $Config{uvsize}' prints 8 or more).


    1. The parent assumed big-endian order and thus used N. But the spec says little-endian byte order is used, which is repeated here.
      I had never read the mini tutorial that you made. After looking at that and then re-reading this comment, everything at least makes sense to me. Not only that, but it actually will help me clean up some code in other modules that ive written. Thanks.

        Also, have you seen perlpacktut?


        Give a man a fish:  <%-{-{-{-<

Re^2: pack/unpack woes
by james289o9 (Acolyte) on Jun 14, 2022 at 21:21 UTC
    Thank you AnomalousMonk, this most definitely solves my original question, and gives me some extra things to study.