L
Leslie Viljoen
Hello!
I am pretty new to metaprogramming, this is my first shot. I want to
be able to take some binary data, split it into parts based on a
template and make an object with those parts.
Basically, I have this template array which defines a binary format:
@map =
[["length", "S"],["unit_id", "L"],["date", "L"],["transaction_id", "L"],
["type", "c"], ["subtype", "c"], ["version", "c"],
["body", "a*"]]
Then I have this in my template class:
#Apply the template to a (binary data) string, producing an object
def apply(className, string)
evalString = "class #{className}\n"
@map.each do |attribute|
evalString << "attr_accessor :#{attribute[0]}\n"
end
evalString << "end\n" << "o = #{className}.new"
eval(evalString)
currentPos = 0
@map.each do |attribute|
case attribute[1]
when "L": size = 4
when "S": size = 2
when "c": size = 1
end
if attribute[1] == "a*"
eval("o.#{attribute[0]} =
string[#{currentPos}..-1].unpack(\"#{attribute[1]}\")")
else
eval("o.#{attribute[0]} = string[#{currentPos},
#{size}].unpack(\"#{attribute[1]}\")")
currentPos += size
end
end
return eval("o")
end
...which produces a class with accessors for each "field" in the
binary data. An object is created and returned - exactly what I want.
Two problems though:
1. I use the final eval("o") to return my object from eval-world. How
do I get my class from there? I want the new class I make to be
persistent at the top level so that I can make several objects of that
class later.
2. Once the class is created, I want to be able to go back and parse
another binary string, producing further fields and add those to the
existing class. My object would need to have the initial accessors
plus the new ones, and the new variables must be set.
I was thinking of a method similar to the one above:
def applyMore(object, className, string)
But I don't know how to add accessors to an already created object,
and since the class above is lost in eval-world (where is that??) - I
can't add to it.
I need this because all my binary files have the same header, but
different bodies. I want to apply the header template and then a body
template to produce the finished object.
So, can anyone help with these problems? If I am going completely off
the track here, can anyone suggest a better way to do all this? I am
reading a lot on meta-programming but I'm slow to catch on.
Les
I am pretty new to metaprogramming, this is my first shot. I want to
be able to take some binary data, split it into parts based on a
template and make an object with those parts.
Basically, I have this template array which defines a binary format:
@map =
[["length", "S"],["unit_id", "L"],["date", "L"],["transaction_id", "L"],
["type", "c"], ["subtype", "c"], ["version", "c"],
["body", "a*"]]
Then I have this in my template class:
#Apply the template to a (binary data) string, producing an object
def apply(className, string)
evalString = "class #{className}\n"
@map.each do |attribute|
evalString << "attr_accessor :#{attribute[0]}\n"
end
evalString << "end\n" << "o = #{className}.new"
eval(evalString)
currentPos = 0
@map.each do |attribute|
case attribute[1]
when "L": size = 4
when "S": size = 2
when "c": size = 1
end
if attribute[1] == "a*"
eval("o.#{attribute[0]} =
string[#{currentPos}..-1].unpack(\"#{attribute[1]}\")")
else
eval("o.#{attribute[0]} = string[#{currentPos},
#{size}].unpack(\"#{attribute[1]}\")")
currentPos += size
end
end
return eval("o")
end
...which produces a class with accessors for each "field" in the
binary data. An object is created and returned - exactly what I want.
Two problems though:
1. I use the final eval("o") to return my object from eval-world. How
do I get my class from there? I want the new class I make to be
persistent at the top level so that I can make several objects of that
class later.
2. Once the class is created, I want to be able to go back and parse
another binary string, producing further fields and add those to the
existing class. My object would need to have the initial accessors
plus the new ones, and the new variables must be set.
I was thinking of a method similar to the one above:
def applyMore(object, className, string)
But I don't know how to add accessors to an already created object,
and since the class above is lost in eval-world (where is that??) - I
can't add to it.
I need this because all my binary files have the same header, but
different bodies. I want to apply the header template and then a body
template to produce the finished object.
So, can anyone help with these problems? If I am going completely off
the track here, can anyone suggest a better way to do all this? I am
reading a lot on meta-programming but I'm slow to catch on.
Les