From: Young Hyun Date: 2006-09-23T02:51:34+09:00 Subject: Re: 64-bit integers in network byte-order On Sep 22, 2006, at 8:56 AM, Francis Cianfrocca wrote: > On 9/22/06, Francis Cianfrocca wrote: >> All, >> does Ruby have a way to convert 64-bit integers to and from network >> order in a platform-independent way? >> >> For 32-bit ints, I can use [value].pack("N"). The conversion operator >> for 64-bit ints ("Q") doesn't have a network-order variant. (I assume >> this is because the underlying byte-order converters (htons/htonl) >> don't >> have a 64-bit version on 32-bit platforms.) >> > > Thanks, guys. I sort of figured I'd have to hack it. Ara, I thought of > your approach (detecting endian-ness locally) but really hoped I could > avoid it! (Ghostbusters: "I feel so funky.") > > Combining your approach with Dave's (and passing both through several > additional processing stages), I end up with: > > #-------------------------------------- > BigEndian = [1].pack("s") == [1].pack("n") > > def htonq value > BigEndian ? val : ([val].pack("Q").reverse.unpack("Q").first) > end > #-------------------------------------- > > and of course ntohq is identical to htonq. Funny, I wrote almost exactly the above code just recently. But, it may not be necessary. Depending on your situation, you might consider using the "w" (BER-compressed integer) packing directive instead. It guarantees that arbitrarily long integers are stored in a standard way (big endian). The caveats are (1) it produces variable-length packed strings and (2) it only supports positive integers. However, because BER-compressed integers are self- describing, in the sense that you can determine when you've reached the end of the encoded string, you could get around the first limitation (if it proves to be a limitation for your usage scenario) by left justifying the BER-compressed integer in a fixed field. For my situation, I just changed the definition of my wire protocol to support variable-length "w"-encoded strings and didn't bother left justifying. --Young