in reply to yet another "reading binary data" question

Maybe not in one pass, since there's no way to unpack a 16-bit signed little-ending ints.

32-bit unsigned little-ending int: unpack('V', $_)
32-bit signed little-ending int: unpack('l', pack('L', unpack('V', $_)))
16-bit unsigned little-ending int: unpack('v', $_)
16-bit signed little-ending int: unpack('s', pack('S', unpack('v', $_)))

However, it's easy to have pack to most of the work, then just touch up the results elegantly.

$_ = "\x32\x54\x76\x98" # 2557891634 as a 32-bit unsigned LE int . "\x32\x54\x76\x98" # -1737075662 as a 32-bit signed LE int . "\x76\x98" # 39030 as a 16-bit unsigned LE int . "\x76\x98"; # -26506 as a 16-bit signed LE int my @nums = unpack('VVvv', $_); $_ = unpack('l', pack('L', $_)) for @nums[1]; # Fix signs of longs. $_ = unpack('s', pack('S', $_)) for @nums[3]; # Fix signs of shorts.

As for the bits, you didn't specify what you wanted to do with them, You could leave them grouped and use masks, or you could seperate them. The former is trivial (unpack('v', $_)). The latter is a bit more complicated, but not that much:

$_ = "\x34\x01"; my @nums = unpack('s', $_); my @flags = ( split //, unpack('B16', pack('n', $nums[0])) )[16-9 .. 1 +6-1];

Tested on a little-endian system, but it should work equally well on a big-endiang system.

Replies are listed 'Best First'.
Re^2: yet another "reading binary data" question
by dwalin (Monk) on May 08, 2008 at 08:45 UTC
    thanks a lot, i never thought of converting unsigned to signed using pack/unpack. :) as for the bits, i need them separated.