On Jun 23, 6:12 pm, Daniel Martin <mar... / snowplow.org> 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.