robinbowes has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I'm using unpack(..) to decode a mixed binary/ascii record. It's mostly working well, but a couple of the values are two-byte, signed short integer. How do I unpack these?

Here's my current code:
my $packet_template = "B16 s2 A4 A8 A2 A A A3 C2"; # read in next record from STDIN and store in $buffer ($Flags,$x,$y,$Mode3,$Callsign, $Route,$Spare1,$Spare2,$Flight_Level, $Terminator,$Checksum) = unpack ( $packet_template, $buffer );
This all works except the $x and $y values which are big-endian. Any offers?

R.

Replies are listed 'Best First'.
Re: how to unpack a big-endian signed short integer
by BrowserUk (Patriarch) on Oct 15, 2003 at 19:45 UTC

    Instead of 's', use 'n'.

    's' is unsigned short in your platform specific/c-compiler format.

    'n' is unsigned short in "network" (big endian) format.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Hooray!

      Thanks for the suggestion. However the values I'm reading are signed, i.e. signed, big-endian 16-bit integers. There doesn't seem to be a an appropriate format character for this. Bummer!

      -- Robin Bowes | http://robinbowes.com

        Sorry. I misread that. Try this...

        print unpack 's', pack 'S', unpack 'n', $n;

        Unpacking it with 'n' will handle the big-endianess without dropping bits. Repacking it with 'S' should likewise not drop anything, but will get it into a format that 's' will correctly unpack.

        I would use 'n' in the composite unpack and then

        sub utos16{ unpack 's', pack 'S', $_[0] }

        to retrieve the signedness afterwards.

        (Note: Please check I got that right:)


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        Hooray!

Re: how to unpack a big-endian signed short integer
by jmcnamara (Monsignor) on Oct 15, 2003 at 22:10 UTC

    You can usually change endianess by calling reverse on the packed data:
    $x = unpack 's', reverse pack 's', $x;

    The following should also work although it may be architecture dependent:

    $x = unpack 's', pack 'n', $x;

    --
    John.

Re: how to unpack a big-endian signed short integer
by etcshadow (Priest) on Oct 15, 2003 at 20:10 UTC
    You can use the vec builtin function in combination with pack/unpack to do whatever bitwise craziness you desire.

    ------------
    :Wq
    Not an editor command: Wq
Re: how to unpack a big-endian signed short integer
by robinbowes (Beadle) on Oct 15, 2003 at 19:30 UTC
    Ooops. I thought I was logged in when I posted this question. Anyway to assign the node to me? -- Robin Bowes | http://robinbowes.com