From: Tim Pease Date: 2007-03-09T11:11:29+09:00 Subject: Re: Efficient processing of binary data streams in Ruby? On 3/8/07, theosib@gmail.com wrote: > I'm writing a Ruby program that has to process binary data from files > and sockets. Data items are in bytes, 16-bit words, or 32-bit words, > and I cannot predict in advance whether the data will be msb-first or > lsb-first, so I end up writing things like this: > > def unpack_16(x) > @msb_first ? ((x[0]<<8)|x[1]) : ((x[1]<<8)|x[0]) > end > > def pack_16(x) > y = "xx" > if (@msb_first) > y[0] = x>>8 > y[1] = x&255 > else > y[0] = x&255 > y[1] = x>>8 > end > end > > I expect, however, that this will be painfully slow, and I can't > imagine that this hasn't been though of before. Is there a better way > to do this that will result in much better performance? > def unpack_16( str ) @msb_first ? str.unpack('n') : str.unpack('S') end def pack_16( num ) @msb_first ? [num].pack('n') : [num].pack('S') end That will work for little-endian processors (Intel) but not for big-endian processors (PowerPC, Sparc). For these methods to work on the latter you'll have to do something like this ... def unpack_16( str ) str = str.reverse unless @msb_first str.unpack('n') end def pack_16( num ) str = [num].pack('n') str.reverse unless @msb_first end Just define the desired method based on the processor type -- which can be figued out by doing this ... LITTLE_ENDIAN = [42].pack('I')[0] == 42 if LITTLE_ENDIAN # define little endian methods here else # define big endian methods here end Hope that helps Blessings, TwP