Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Ruby Programming Language

best DRY solution for this task


Hi,
I have a certain problem here and can't find a proper DRY solution for
this so I wondered if someone here has an idea and could help me.

I'm reading a file byte for byte. This file is structured and I try to
give out each structures element and the meaning of it. So let's pretend
the file content would be this in bytes (you get it e.g. with
file.read(7)): 1 3d 0 233 0 1 2f

now I wanna read the file byte for byte and output if the first 3 bytes
are equal 1 3d 0:
     startflag : good (1 3d 0)
or if the check fails
     startflag : bad (2 3d 0)
now the fourth byte is read and if it is 1
     debg_mode : on
if it is 0 : out and if it is 233 : don't know  ...

My problem with a DRY solution is that some bytes in this file are
grouped together and have just together a meaning as the first three
starting bytes: 1 3d 0 at the beginning and some bytes have alone a
meaning as the fourth byte 233 in the example.
And that everything has another ouput. So the first three bytes meaning
is another than the one of the fourt or the fifth byte.

My solution until now:

target = open('testfile.txt','r')

startflag = target.read(3)
     print("startflag: ")
     if startflag == $startflag # here I took a global var because
"\x13d0" didn't work
      print(" good")
     else
      print(" bad")
     end
     startflag.each_byte  do |x|
     printf("%x ",x)
                          end
puts ""

dbg_mode = target.read(1)
printf("dbg_mode: ")
    if dbg_mode == "\x1"
      print(" on")
    elseif dbg_mode == "\x255"
      print("don't know")
    else
      print(" bad")
    end
dbg_mode.each_byte  {|x| printf("%x ",x) }
puts ""

and so on and on and on...

so how can I do this check and outputting better? Because there are many
bytes with many different meanings and as said sometimes I need to read
in 4 bytes then just one then again 2 bytes... is this at all possible
to do dry-like?

thanks

--
greets

                     one must still have chaos in oneself to be able to
give birth to a dancing star

On Jun 6, 11:57 am, anansi <kaz@oleco.net> wrote:

> I'm reading a file byte for byte. This file is structured and I try to
> give out each structures element and the meaning of it. So let's pretend
> the file content would be this in bytes (you get it e.g. with
> file.read(7)): 1 3d 0 233 0 1 2f

a) You might want to look into the BitStruct library.
b) See the following. It's up to you how much work you want to put in
the common 'eat' method, versus how much you want to leave up to the
proc for each particular matcher.

# Just for no-file testing
require 'stringio'
bytes = [ 1, 0x3d, 0, 233, 0, 1, 0x2f  ]
byte_string = StringIO.new( bytes.map{ |b| b.chr }.join )

class ByteEater
  def initialize( title, num_bytes, &block )
    @title = title
    @num_bytes = num_bytes
    @proc = block
  end
  def eat( file )
    bytes = file.read( @num_bytes )
    print( "#@title: " )
    @proc.call( bytes )
    bytes.each_byte{ |x| print "%x" % x }
    puts ""
  end
end

structure = [
  ByteEater.new( 'startflag', 3 ){ |bytes|
    if bytes == "\01\x3d\0"
      print " good"
    else
      print " bad"
    end
  },
  ByteEater.new( 'dbg_mode', 1 ){ |bytes|
    case bytes
      when 1.chr
        print " on"
      when 255.chr
        print "don't know"
      else
        print "bad"
    end
  },
]

structure.each{ |eater|
  eater.eat( byte_string )

}

#=> startflag:  good13d0
#=> dbg_mode: bade9

> so how can I do this check and outputting better? Because
> there are many
> bytes with many different meanings and as said sometimes I
> need to read
> in 4 bytes then just one then again 2 bytes... is this at all
> possible
> to do dry-like?

Without knowing the details of the file you're trying to parse it's hard
to say, but you might be well-served to write a simple finite state
machine. E.g. something like:

mode = :expect_header
while !(mode == :done || mode == :fail)
  case mode
    when :expect_header
      if target.read(3) == $startflag
        mode = :expect_debug
      else
        mode = :fail
      end
    when :expect_debug
      case target.read(1)
        when "\x1"
          debug = true
          mode = :expect_body
        when "\x255"
          debug = nil
          mode = :expect_body
        else
          mode = :fail
      end
  end
end

- donald

On 06.06.2007 22:12, Ball, Donald A Jr (Library) wrote:

You can even nest cases

mode = :expect_header
while !(mode == :done || mode == :fail)
   case mode
     when :expect_header
       mode = case target.read(3)
         when "\x1\x3d\x0"
           :expect_debug
         else
           :fail
         end
     when :expect_debug
       mode = case target.read(1)
         when "\x1"
           debug = true
           :expect_body
         when "\xff"
           debug = nil
           :expect_body
         else
           :fail
         end
       end
   end
end

If you use nil as :fail then it becomes even simpler because you can
omit "else" branches in "case".  Another alternative is to throw
immediately when an error occurs.

Just some more food for experimening.

Kind regards

        robert

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc