Packing signed long in a portable fashion

Is there a way to pack() a signed long in a portable fashion (i.e. it
should work on both little endian and big endian machines)?

The pack() function has these options:
‘l’ => { :signed => true, :network => false }
‘N’ => { :signed => false, :network => true }

But I cannot find an option that is { :signed => true, :network => true }!

So if I pack with ‘l’, it won’t work on different architectures. And
if I pack with ‘N’, it won’t allow negative numbers.

For now, I think I have to pack with ‘N’, but add 232 before packing
and subtract 2
32 after unpacking, but I think there ought to be a
better way?

Philip Mak wrote:

Is there a way to pack() a signed long in a portable fashion (i.e. it
should work on both little endian and big endian machines)?

The pack() function has these options:
‘l’ => { :signed => true, :network => false }
‘N’ => { :signed => false, :network => true }

But I cannot find an option that is { :signed => true, :network => true }!

So if I pack with ‘l’, it won’t work on different architectures. And
if I pack with ‘N’, it won’t allow negative numbers.

For now, I think I have to pack with ‘N’, but add 232 before packing
and subtract 2
32 after unpacking, but I think there ought to be a
better way?

Will this do?

if [1].pack(“N”) == [1].pack(“I”) # big endian
array.pack(“l*”).reverse
else
array.pack(“l*”)
end

Regards,

Dan

···


a = [74, 117, 115, 116, 32, 65, 110, 111, 116, 104, 101, 114, 32, 82]
a.push(117,98, 121, 32, 72, 97, 99, 107, 101, 114)
puts a.pack(“C*”)

Won’t this transform the number into a Bignum?
Believe it’s 2**31 (remember Fixnum’s length), but am not really sure…

···

On Wed, Apr 09, 2003 at 05:46:03AM +0900, Philip Mak wrote:

Is there a way to pack() a signed long in a portable fashion (i.e. it
should work on both little endian and big endian machines)?

The pack() function has these options:
‘l’ => { :signed => true, :network => false }
‘N’ => { :signed => false, :network => true }

But I cannot find an option that is { :signed => true, :network => true }!

So if I pack with ‘l’, it won’t work on different architectures. And
if I pack with ‘N’, it won’t allow negative numbers.

For now, I think I have to pack with ‘N’, but add 232 before packing
and subtract 2
32 after unpacking, but I think there ought to be a
better way?


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

lp1 on fire
– One of the more obfuscated kernel messages

[-1].pack(“N”)
=> “\377\377\377\377”

Looks OK to me for packing. Unpacking treats this as unsigned though; you
could just test for values >= 231 and subtract 232

···

On Wed, Apr 09, 2003 at 05:46:03AM +0900, Philip Mak wrote:

So if I pack with ‘l’, it won’t work on different architectures. And
if I pack with ‘N’, it won’t allow negative numbers.

Why not pack it as:

m = -1 # => -1
n = [m < 0 ? 1 : 0, m.abs].pack(“N*”)
# => “\001\000\000\000\001\000\000\000”
o = n.unpack(“N*”)
p = o[1] * (o[0] ? -1 : 1)

Yes, it means you have to know the encoding on both sides, but it
seems less risky than adding 2**32.

-austin
– Austin Ziegler, austin@halostatue.ca on 2003.04.08 at 22:45:34

···

On Wed, 9 Apr 2003 05:46:03 +0900, Philip Mak wrote:

Is there a way to pack() a signed long in a portable fashion (i.e.
it should work on both little endian and big endian machines)?

The pack() function has these options:
‘l’ => { :signed => true, :network => false }
‘N’ => { :signed => false, :network => true }

But I cannot find an option that is { :signed => true, :network =>
true }!

So if I pack with ‘l’, it won’t work on different architectures.
And if I pack with ‘N’, it won’t allow negative numbers.

For now, I think I have to pack with ‘N’, but add 232 before
packing and subtract 2
32 after unpacking, but I think there
ought to be a better way?