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