50 lines
1.3 KiB
Ruby
50 lines
1.3 KiB
Ruby
class CStruct
|
|
def self.new *p
|
|
pre = p.pop if p.last.kind_of? Hash
|
|
Class.new do
|
|
include CStruct::Mix
|
|
eval <<-EOF
|
|
attr_accessor #{p.map{|n,v| ":#{n}" }.join', '}
|
|
def self._directives
|
|
["#{p.map{|n,v|"#{v}"}.join}", #{post}]
|
|
end
|
|
def initialize data = nil
|
|
#{p.map{|n,v|"@#{n}"}.join', '} = _parse data
|
|
end
|
|
def _create
|
|
super #{p.map{|n,v|"@#{n}"}.join', '}
|
|
end
|
|
EOF
|
|
end
|
|
end
|
|
end
|
|
|
|
module CStruct::Mix
|
|
def _parse data = nil
|
|
return unless data
|
|
pre, pos = self.class._directives
|
|
if pos.nil? or pos == 0 then data.unpack pre
|
|
elsif pos == 1 then data.unpack pre+'a*'
|
|
else
|
|
# Statisch lange Daten, Laengen von var und der Rest in var
|
|
(*dat, var) = data.unpack pre + ('N'*(pos-1)) + 'a*'
|
|
dat[ 0...-pos ] + # Statisch lange Daten
|
|
var.unpack( # Variabel lange Daten
|
|
dat[ -pos...-1 ].inject( data.length-var.length) {|i,j|
|
|
j.push i-j.last # Differenzieren
|
|
}.map {|i| "a#{i}" }.join) # Packstring zusammensetzen
|
|
end
|
|
end
|
|
|
|
def _create *data
|
|
pre, pos = self.class._directives
|
|
if pos.nil? or pos == 0 then data.pack pre
|
|
elsif pos == 1 then data.pack pre+'a*'
|
|
else
|
|
r = data[ 0...-pos ].pack pre
|
|
r += data[ -pos..-1 ].inject( [r.length]) {|i,j| j.push i+j.last}[1...-1].pack 'N*'
|
|
r + data[ -pos..-1 ].pack( 'a*'*(pos-1))
|
|
end
|
|
end
|
|
end
|