From: akbarhome Date: 2007-06-23T22:55:06+09:00 Subject: Re: ruby equivalent of htons or htonl On Jun 23, 6:12 pm, Daniel Martin wrote: > > > You are thinking about too low a level of porting. > > Look, what is this code doing? It is packing up a structure, probably > to be sent over the wire. So let's just do that part, okay? Don't > try to separately do the htonl conversion and the structure-packing. > There's a reason the function isn't in the ruby standard library: the > only time it's needed is when you're packing things up anyway, so it's > built into pack and unpack. > > Here's a rough translation of what I think you're trying to write: > > # A translation of fsp_pkt_write from > #http://csourcesearch.net/package/gftp/2.0.18/gftp-2.0.18/lib/fsplib/f... > > # Note that in ruby we return the new string, and don't worry about > # preallocating a buffer. > > # Also, I'd rename this method to something like "fsp_pkt_make" since > # it doesn't really *write* the data to the output, but that's what > # the function is called in C, so... > > def fsp_pkt_write(fsp_pkt) > > fsp_string = [fsp_pkt.cmd, 0, fsp_pkt.key, > fsp_pkt.seq, fsp_pkt.len, fsp_pkt.pos].pack("CCnnnN") > > # I assume that in the ruby version, p.buf contains both the data > # block and the "extra data" block > > fsp_string += fsp_pkt.buf > > checksum = 0 > fsp_string.each_byte {|i| checksum += i+1} > # Note: adding 1 above at each byte is equivalent to adding the length > fsp_string[1] = (checksum & 0xFF) > return fsp_string > > end > > Now, wasn't that easier than hauling out bitstruct to get a > line-by-line translation? That gives me insight. > Really? Do you have evidence of this, that the htonl as defined in > that ruby-talk message won't work properly on a big endian machine? > Perhaps the problem is how you were intending to use bit-struct? > Actually, big endian machines don't need that htonl function. Here is the code: #if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN) #define htons(A) (A) #define htonl(A) (A) #define ntohs(A) (A) #define ntohl(A) (A) #elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) #define htons(A) ((((uint16)(A) & 0xff00) >> 8) | \ (((uint16)(A) & 0x00ff) << 8)) #define htonl(A) ((((uint32)(A) & 0xff000000) >> 24) | \ (((uint32)(A) & 0x00ff0000) >> 8) | \ (((uint32)(A) & 0x0000ff00) << 8) | \ (((uint32)(A) & 0x000000ff) << 24)) #define ntohs htons #define ntohl htohl #else #error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both." #endif To make it portable we need to make it like this: def htonl(h) if BIG_ENDIAN_MACHINE then h else do the convert end end Is there anyway in ruby to detect type of endianness of machine? Thank you.