Joel VanderWerf
6/24/2007 4:43:00 AM
Mark Day wrote:
> On Jun 19, 2007, at 11:19 AM, Daniel Berger wrote:
>
>>> 1) I see "l" (lowercase L) which is 4 bytes treated as a signed
>>> integer...but in 'native' endian order. Does String.unpack not provide
>>> a way to unpack a 4-byte signed integer with a specified endianness?
>>>
>>> 2) I see "s" which is 2 bytes treated as a signed integer...but in
>>> 'native' endian order. Does String.unpack not provide a way to unpack
>>> a 2-byte signed integer with a specified endianness?
>>
>> See the 'N', 'n', 'V' and 'v' directives. There are equivalent
>> directives for floats as well - 'E', 'e', 'G' and 'g'.
>
> Those handle endianness, but not signed values. I suppose you could
> unpack as unsigned, then manually test for the sign bit being set and
> correct the value. Even uglier, you could unpack as unsigned with
> desired endianness, repack as unsigned in native order, then unpack as
> signed in native order.
What bit-struct does in these cases is the first kind of ugly:
# Let's say we start with a negative number packed in
# 16 bits, big-endian:
x = -123
s = [x].pack("n")
# Note that the sign is not packed with the number. It packs to the
# same chars as 2**16 + x
bits = 16
max_unsigned = 2 ** bits
max_signed = 2 ** (bits - 1)
to_signed = proc { |n| (n >= max_signed) ? n - max_unsigned : n }
puts to_signed[s.unpack("n").first] # ==> -123
(This has come up a few times on the list -- search for "to_signed", for
example.)
It's still a hack, though, and I'd like to see Gavin's RCR go through,
if the naming issues can be resolved.
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407