[RCR]: Replace pack and unpack with OO versions

B

Bill Atkins

Rather than having code like this:

flags, ignore, length, name = data.unpack "nnna*"

let's try this:

u = Unpacker.new data
flags, ignore, length, name = u.word, u.word, u.word, u.string

I think this looks a lot neater and is much more maintainable. A
similar thing could be done with pack.

p = Packer.new
p.word 0x01
p.word 0x00
p.word 0x08
p.string "ERERER"

p.to_s => packed version

Any ideas on this before I draft it up into a real RCR?

Bill Atkins
 
J

Jamis Buck

Bill said:
Rather than having code like this:

flags, ignore, length, name = data.unpack "nnna*"

let's try this:

u = Unpacker.new data
flags, ignore, length, name = u.word, u.word, u.word, u.string

I think this looks a lot neater and is much more maintainable. A
similar thing could be done with pack.

p = Packer.new
p.word 0x01
p.word 0x00
p.word 0x08
p.string "ERERER"

p.to_s => packed version

Any ideas on this before I draft it up into a real RCR?

Bill Atkins

.

I'm for it. I actually wrote up a couple of utility classes to (more or
less) do just this for me, for the Net::SSH stuff. Dealing directly with
pack/unpack makes my head hurt after a while.

--
Jamis Buck
(e-mail address removed)
http://www.jamisbuck.org/jamis

ruby -h | ruby -e
'a=[];readlines.join.scan(/-(.)\[e|Kk(\S*)|le.l(..)e|#!(\S*)/) {|r| a <<
r.compact.first };puts "\n>#{a.join(%q/ /)}<\n\n"'
 
H

Hal Fulton

Bill said:
Rather than having code like this:

flags, ignore, length, name = data.unpack "nnna*"

let's try this:

u = Unpacker.new data
flags, ignore, length, name = u.word, u.word, u.word, u.string

I think this looks a lot neater and is much more maintainable. A
similar thing could be done with pack.

p = Packer.new
p.word 0x01
p.word 0x00
p.word 0x08
p.string "ERERER"

p.to_s => packed version

Any ideas on this before I draft it up into a real RCR?

Hmm, looks like it is keeping some internal state? A "file
pointer" so to speak?


Hal
 
M

Martin DeMello

Bill Atkins said:
Rather than having code like this:

flags, ignore, length, name = data.unpack "nnna*"

let's try this:

u = Unpacker.new data
flags, ignore, length, name = u.word, u.word, u.word, u.string

I think this looks a lot neater and is much more maintainable. A
similar thing could be done with pack.

Alternatively, something I've been thinking of is to let pack and unpack
take array arguments, which are 'compiled' into pack/unpack strings.

e.g. flags, ignore, length, name = u.unpack [:word, :word, :word,
:string]

All the compiler would have to do is translate symbols, and pass numbers
through unchanged. Or, if you wanted to construct it in terms of pairs
like [[:string, 3]], just run a flatten first.

martin
 
M

Michael Neumann

Bill Atkins said:
Rather than having code like this:

flags, ignore, length, name = data.unpack "nnna*"

let's try this:

u = Unpacker.new data
flags, ignore, length, name = u.word, u.word, u.word, u.string

I think this looks a lot neater and is much more maintainable. A
similar thing could be done with pack.

Alternatively, something I've been thinking of is to let pack and unpack
take array arguments, which are 'compiled' into pack/unpack strings.

e.g. flags, ignore, length, name = u.unpack [:word, :word, :word,
:string]

All the compiler would have to do is translate symbols, and pass numbers
through unchanged. Or, if you wanted to construct it in terms of pairs
like [[:string, 3]], just run a flatten first.

It would be nice if Packer/Unpacker would work on IO/File objects. I've
written a BinaryReader and BinaryWriter mixin module, with methods like:

read_word8(byte_order=ByteOrder::Native)
read_word8_big ..._network
read_word8_little
read_word8_native

and the same for word16, word32, int8, int16...

int's are signed integers, word are unsigned.

And to use it, you just have to extend your io object:

require 'stringio'
io = StringIO.new("Hello World")
io.extend(BinaryReader)
p io.read_word32

It's easy to add a unpack method:

class BinaryReader
def unpack(*spec)
spec.map {|s| send("read_#{s}")}
end
end

io.unpack:)word8, :word8, :word32_little)


Regards,

Michael
 
B

Bill Atkins

Yeah, that's what I was figuring. I assumed that packing would
prepend rather than append, but I suppose that's configurable.
 
D

Daniel Berger

Rather than having code like this:

flags, ignore, length, name = data.unpack "nnna*"

let's try this:

u = Unpacker.new data
flags, ignore, length, name = u.word, u.word, u.word, u.string

I think this looks a lot neater and is much more maintainable. A
similar thing could be done with pack.

p = Packer.new
p.word 0x01
p.word 0x00
p.word 0x08
p.string "ERERER"

p.to_s => packed version

Any ideas on this before I draft it up into a real RCR?

Bill Atkins

I mentioned this a *long* time ago, but didn't get much feedback. If
I recall, I was inspired in part by the port of
Spreadsheet::WriteExcel, in which there's a lot of pack/unpack going
on.

http://ruby-talk.com/cgi-bin/scat.rb/ruby/ruby-talk/44847

I definitely support the idea.

Regards,

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top