akbarhome <akbarhome / gmail.com> 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