From: Daniel Martin Date: 2007-06-23T20:12:45+09:00 Subject: Re: ruby equivalent of htons or htonl akbarhome writes: > I try to port this c code: > *(uint16_t *)(ptr+FSP_OFFSET_KEY)=htons(p->key); > *(uint16_t *)(ptr+FSP_OFFSET_SEQ)=htons(p->seq); > *(uint16_t *)(ptr+FSP_OFFSET_LEN)=htons(p->len); > *(uint32_t *)(ptr+FSP_OFFSET_POS)=htonl(p->pos); > > About uint16_t, I have bit-struct library. But htons messed up my > head. 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/fsplib.c # 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? > But that is 2001, maybe right now we have the function in standard > library. Another point is that library is not portable. It will mess > up in big endian machine. 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? -- s=%q( Daniel Martin -- martin@snowplow.org puts "s=%q(#{s})",s.to_a.last ) puts "s=%q(#{s})",s.to_a.last