[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Efficient processing of binary data streams in Ruby?

theosib

3/9/2007 1:30:00 AM

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?

Thanks!

2 Answers

Tim Pease

3/9/2007 2:11:00 AM

0

On 3/8/07, theosib@gmail.com <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

Ara.T.Howard

3/9/2007 3:10:00 AM

0