From: Joel VanderWerf Date: 2007-06-24T13:42:36+09:00 Subject: Re: Unpacking signed shorts and integers with specified endianness 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