Class: Gogyou::Accessor

Inherits:
Object show all
Defined in:
lib/gogyou/accessor.rb

Overview

構造体データを構造体として参照させるためのクラスです。

このクラスのサブクラスをさらに派生させたクラスが、実際の役目を負います。

クラス関係図

リストの入れ子関係は、クラスの親子関係を表します。

  • Accessor - 基本クラス

    • Accessor::BasicStruct - 構造体の基本クラス

      • Accessor::Struct - 特定の Model に対する構造体クラス

      • Accessor::TemporaryStruct - 汎用的な型情報に対する構造体クラス

      • Accessor::BasicUnion - 共用体の基本クラス

        • Accessor::Union - 特定の Model に対する共用体クラス

        • Accessor::TemporaryUnion - 汎用的な型情報に対する共用体クラス

    • Accessor::BasicArray - 配列型の基本クラス

      • Accessor::Array - 特定の Model に対する配列型クラス

      • Accessor::TemporaryArray - 汎用的な型情報に対する配列型クラス

Direct Known Subclasses

BasicArray, BasicStruct

Defined Under Namespace

Modules: TemporaryMixin Classes: Array, BasicArray, BasicStruct, BasicUnion, Struct, TemporaryArray, TemporaryStruct, TemporaryUnion, Union

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(buffer = String.alloc(self.class::BYTESIZE), offset = 0) ⇒ Accessor

Returns a new instance of Accessor.



29
30
31
32
33
# File 'lib/gogyou/accessor.rb', line 29

def initialize(buffer = String.alloc(self.class::BYTESIZE), offset = 0)
  buffer = String.alloc(buffer.to_i) if buffer.kind_of?(Integer)
  @buffer__GOGYOU__ = buffer
  @offset__GOGYOU__ = offset.to_i
end

Instance Attribute Details

#buffer__GOGYOU__Object (readonly) Also known as: buffer

Returns the value of attribute buffer__GOGYOU__.



23
24
25
# File 'lib/gogyou/accessor.rb', line 23

def buffer__GOGYOU__
  @buffer__GOGYOU__
end

#offset__GOGYOU__Object (readonly) Also known as: offset

Returns the value of attribute offset__GOGYOU__.



24
25
26
# File 'lib/gogyou/accessor.rb', line 24

def offset__GOGYOU__
  @offset__GOGYOU__
end

Class Method Details

.aref(buffer, offset) ⇒ Object

型情報オブジェクトとしてのメソッドです。



188
189
190
# File 'lib/gogyou/accessor.rb', line 188

def self.aref(buffer, offset)
  new(buffer, offset)
end

.aset(buffer, offset, data) ⇒ Object

型情報オブジェクトとしてのメソッドです。

Raises:

  • (NotImplementedError)


195
196
197
# File 'lib/gogyou/accessor.rb', line 195

def self.aset(buffer, offset, data)
  raise NotImplementedError, "IMPLEMENT ME in sub class!"
end

.bind(buffer, offset = 0) ⇒ Object



110
111
112
# File 'lib/gogyou/accessor.rb', line 110

def self.bind(buffer, offset = 0)
  new(buffer, offset)
end

.bytealignObject

型情報オブジェクトとしてのメソッドです。



209
210
211
# File 'lib/gogyou/accessor.rb', line 209

def self.bytealign
  self::BYTEALIGN
end

.bytesizeObject

型情報オブジェクトとしてのメソッドです。



202
203
204
# File 'lib/gogyou/accessor.rb', line 202

def self.bytesize
  self::BYTESIZE
end

.define(model) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/gogyou/accessor.rb', line 118

def self.define(model)
  klass = ::Class.new(self)
  klass.class_eval do
    const_set(:MODEL, model)
    const_set(:BYTESIZE, model.bytesize)
    const_set(:BYTEALIGN, model.bytealign)
    const_set(:EXTENSIBLE, model.extensible?)
  end

  define_accessors(klass, model)

  klass
end

.define_accessors(accessorclass, model) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/gogyou/accessor.rb', line 148

def self.define_accessors(accessorclass, model)
  accessorclass.class_eval do
    namecheck = {}
    fieldsize = model.fields.size
    define_method(:size__GOGYOU__, -> { fieldsize })
    alias_method(:size, :size__GOGYOU__)
    model.fields.each do |field|
      name = field.name
      #raise NameError, "wrong field name - #{name}" unless name =~ /\A[A-Za-z_][A-Za-z_0-9]*\Z/
      name = name.intern
      raise NameError, "already exist field name - #{name}" if namecheck[name]
      namecheck[name] = true

      if field.vector
        subarray = define_subarray(field)
        type = subarray
      else
        subarray = nil
        type = field.type
      end

      define_method(field.name, -> {
        v = type.aref(buffer__GOGYOU__, offset__GOGYOU__ + field.offset)
        v.infect_from(self, buffer) unless v.frozen?
        v.freeze if frozen? || buffer.frozen? || field.const?
        v
      })

      define_method("#{field.name}=", ->(value) {
        raise TypeError, "immutable object (#<%s:0x%08X>.%s)" % [self.class, __id__, field.name], caller(2) if frozen?
        raise TypeError, "immutable field (#<%s:0x%08X>.%s)" % [self.class, __id__, field.name], caller(2) if field.const?
        type.aset(buffer__GOGYOU__, offset__GOGYOU__ + field.offset, value)
      })
    end
  end
end

.define_subarray(field) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/gogyou/accessor.rb', line 132

def self.define_subarray(field)
  #sub-array のためのクラスを生成する (多次元配列であれば、それぞれの次元に対して作成)
  #sub-array クラスの MODEL 定数は、Gogyou::Model::Array のインスタンス
  fsize = field.vector.inject(&:*) * field.type.bytesize
  falign = field.type.bytealign
  felements = field.vector[-1]
  raise "BUG: negative element bytesize - #{field.inspect}" unless felements >= 0
  felements = nil if felements == 0
  fvect = field.vector.slice(0 ... -1)
  fvect = nil if fvect.empty?
  subarray = Accessor::Array.define(Model::Array[fsize, falign, [Model::Field[nil, felements, fvect, field.type]]])
  subarray.name # すでに名前が定義されてる場合はこれで固定される
  Accessor.const_set("UserArray_%08X" % subarray.__id__, subarray)
  subarray
end

.extensible?Boolean

型情報オブジェクトとしてのメソッドです。

Returns:

  • (Boolean)


216
217
218
# File 'lib/gogyou/accessor.rb', line 216

def self.extensible?
  self::EXTENSIBLE
end

.modelObject



114
115
116
# File 'lib/gogyou/accessor.rb', line 114

def self.model
  self::MODEL
end

Instance Method Details

#bytesizeObject



83
84
85
# File 'lib/gogyou/accessor.rb', line 83

def bytesize
  self.class::BYTESIZE
end

#initialize_copy(obj) ⇒ Object



35
36
37
38
39
40
# File 'lib/gogyou/accessor.rb', line 35

def initialize_copy(obj)
  super(obj)
  unless obj.frozen?
    @buffer__GOGYOU__ = obj.buffer__GOGYOU__.dup
  end
end

#inspectObject



91
92
93
94
95
# File 'lib/gogyou/accessor.rb', line 91

def inspect
  "#<%s buffer=%p, offset=%p>" % [self.class,
                                  buffer__GOGYOU__.inspect,
                                  offset__GOGYOU__]
end

#pretty_print(q) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/gogyou/accessor.rb', line 97

def pretty_print(q)
  q.group(1, "#<#{self.class}") do
    q.breakable " "
    q.text "buffer="
    q.pp buffer__GOGYOU__
    q.text ","
    q.breakable " "
    q.text "offset="
    q.pp offset__GOGYOU__
    q.text ">"
  end
end

#sizeObject



87
88
89
# File 'lib/gogyou/accessor.rb', line 87

def size
  nil
end

#slide(bytesize = self.class::BYTESIZE) ⇒ Object

call-seq:

slide() -> new_accessor or nil
slide(bytesize) -> new_accessor or nil

自身のデータ領域を指定バイト数ずらした参照体を返します。



64
65
66
# File 'lib/gogyou/accessor.rb', line 64

def slide(bytesize = self.class::BYTESIZE)
  self.class.new(buffer__GOGYOU__, offset__GOGYOU__ + bytesize)
end

#slide!(bytesize = self.class::BYTESIZE) ⇒ Object

call-seq:

slide!() -> self or nil
slide!(bytesize) -> self or nil

詳細は slide を参照して下さい。



75
76
77
78
79
80
81
# File 'lib/gogyou/accessor.rb', line 75

def slide!(bytesize = self.class::BYTESIZE)
  offset = offset__GOGYOU__ + bytesize
  #return nil if offset < 0
  #return nil if offset + buffer__GOGYOU__.bytesize > layout__GOGYOU__.bytesize
  @offset__GOGYOU__ = offset
  self
end

#to_bufferObject



49
50
51
# File 'lib/gogyou/accessor.rb', line 49

def to_buffer
  buffer__GOGYOU__
end

#to_ptrObject



53
54
55
# File 'lib/gogyou/accessor.rb', line 53

def to_ptr
  buffer__GOGYOU__.to_ptr
end

#to_sObject

バイナリデータとして取り出します。



45
46
47
# File 'lib/gogyou/accessor.rb', line 45

def to_s
  buffer__GOGYOU__.byteslice(offset__GOGYOU__, self.class::BYTESIZE)
end