lib/gogyou/model.rb in gogyou-0.2.4 vs lib/gogyou/model.rb in gogyou-0.2.5

- old
+ new

@@ -358,29 +358,32 @@ # def parse!(args) raise ArgumentError, "nothing argument" if args.empty? name = nil vector = nil - while arg = args.shift + args.each do |arg| case arg + when ::Array # pointer field + yield(name, vector) if name + name = nil + vector = nil + parse!(arg) do |name1, elements| + raise ArgumentError, "wrong pointer definision" if name + name = Model::Pointer.create(name1, elements) + end when Symbol, String yield(name, vector) if name raise ArgumentError, "informal field name (#{arg.to_s})" unless arg =~ FIELDNAME_PATTERN name = arg.intern vector = nil when Integer raise ArgumentError, "first argument is field name only (#{arg})" unless name - raise ArgumentError, "given negative number (#{arg})" unless arg >= 0 + raise ArgumentError, "can't internal extensible in multi-dimentional array" if vector && vector[-1] < 1 + v = arg.to_i + raise ArgumentError, "given negative number (#{arg})" unless v >= 0 vector ||= [] - vector << arg.to_i - if vector[-1] == 0 - yield(name, vector) - unless args.empty? - raise ArgumentError, "given fields after extensible vector" - end - return nil - end + vector << v else raise ArgumentError, "given any object (#{arg.inspect})" end end @@ -397,28 +400,35 @@ addfield!(typeobj, packexp, args) end def addfield!(typeobj, packexp, args) - #p typeobj - # check extensible field >>> creator.fields[-1].vector[-1] - if (x = fields[-1]) && (x = x.vector) && x[-1] == 0 - raise ArgumentError, "not given fields after extensible vector" - end + typesize = typealign = nil # 自己参照構造体を実現するために必要な時に取得する - typesize = typeobj.bytesize - typealign = [typeobj.bytealign, 1 << packexp].min - tmpfields = [] parse!(args) do |name, vect| - self.offset = offset.align_ceil(typealign) unless kind_of?(Model::Union::Creator) - fields << f = Field[offset, name, vect, typeobj, 0 | packexp] - tmpfields << f - unless kind_of?(Model::Union::Creator) - elements = vect ? vect.inject(1, &:*) : 1 - self.offset += typesize * elements + if name.kind_of?(Model::Pointer::Creator) + (name, ptrtype) = name.create(typeobj) + self.offset = offset.align_ceil(Primitives::SIZE_T.bytealign) unless kind_of?(Model::Union::Creator) + fields << f = Field[offset, name, vect, ptrtype, 0 | packexp] + tmpfields << f + unless kind_of?(Model::Union::Creator) + elements = vect ? vect.inject(1, &:*) : 1 + self.offset += Primitives::SIZE_T.bytesize * elements + end + else + typesize ||= typeobj.bytesize + typealign ||= [typeobj.bytealign, 1 << packexp].min + + self.offset = offset.align_ceil(typealign) unless kind_of?(Model::Union::Creator) + fields << f = Field[offset, name, vect, typeobj, 0 | packexp] + tmpfields << f + unless kind_of?(Model::Union::Creator) + elements = vect ? vect.inject(1, &:*) : 1 + self.offset += typesize * elements + end end end tmpfields end @@ -466,9 +476,30 @@ if creator.respond_to?(:padding) define_method(:padding, ->(bytesize, &block) { creator.padding(bytesize, &block); nil }) end end end + end + end + + class Pointer < Model + class Creator < ::Struct.new(:token, :elements) + def create(typeobj) + name = token + if name.kind_of?(Creator) + # multiple pointer + (name, typeobj) = name.create(typeobj) + end + if elements && !elements.empty? + typeobj = Accessor.define_subarray(Model::Field[0, nil, elements, typeobj, 0]) + end + model = Accessor.define_subpointer(typeobj) + [name, model] + end + end + + def self.create(token, elements) + Creator.new(token, elements) end end class Struct < Model class Creator < Model::BasicCreator