Module: Snow::CStruct::StructBase

Defined in:
lib/snow-data/c_struct/struct_base.rb

Overview

Struct base class. Not to be used directly, as it does not provide all the constants and methods necessary for a struct.

Defined Under Namespace

Modules: Allocators, MemberInfoSupport

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.define_member_methods(struct_klass) ⇒ 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
184
185
186
187
188
# File 'lib/snow-data/c_struct/struct_base.rb', line 148

def self.define_member_methods(struct_klass)
  struct_klass.class_exec do
    self::MEMBERS.each do |member|

      name        = member.name
      index_range = (0...member.length)
      type_name   = member.type
      type_size   = ::Snow::CStruct::SIZES[member.type]
      offset      = member.offset
      getter      = :"get_#{type_name}"
      setter      = :"set_#{type_name}"
      get_name    = :"get_#{name}"
      set_name    = :"set_#{name}"

      define_method(get_name) do |index = 0|
        if index === index_range
          raise RangeError, "Index #{index} for #{name} is out of range: must be in #{index_range}"
        end
        off = offset + index * type_size
        __send__(getter, off)
      end # get_name


      define_method(set_name) do |value, index = 0|
        if index === index_range
          raise RangeError, "Index #{index} for #{name} is out of range: must be in #{index_range}"
        end
        off = offset + index * type_size
        __send__(setter, off, value)
        value
      end # set_name


      alias_method :"#{name}", get_name
      alias_method :"#{name}=", set_name

      extend MemberInfoSupport

    end # self::MEMBERS.each
  end # self.class_exec
end

.included(struct_klass) ⇒ Object

Upon inclusion, defines the given struct_klass’s member accessors/mutators as well as its allocator functions.



195
196
197
198
199
# File 'lib/snow-data/c_struct/struct_base.rb', line 195

def self.included(struct_klass)
  struct_klass.extend(Allocators)
  struct_klass.extend(MemberInfoSupport)
  define_member_methods(struct_klass)
end

Instance Method Details

#[](name, index = 0) ⇒ Object

Gets the value of the member with the given name and index.



135
136
137
# File 'lib/snow-data/c_struct/struct_base.rb', line 135

def [](name, index = 0)
  __send__(self.class::MEMBERS_GETFN[name], index)
end

#[]=(name, index = 0, value) ⇒ Object

Sets the value of the member with the given name and index.



143
144
145
# File 'lib/snow-data/c_struct/struct_base.rb', line 143

def []=(name, index = 0, value)
  __send__(self.class::MEMBERS_SETFN[name], value, index)
end

#address_of(member) ⇒ Object

Returns the address of a member. This address is only valid for the receiver.



26
27
28
# File 'lib/snow-data/c_struct/struct_base.rb', line 26

def address_of(member)
  self.address + self.class.offset_of(member)
end

#alignment_of(member) ⇒ Object

Returns the alignment of a member.



50
51
52
# File 'lib/snow-data/c_struct/struct_base.rb', line 50

def alignment_of(member)
  self.class.alignment_of(member)
end

#bytesize_of(member) ⇒ Object

Returns the size in bytes of a member.



42
43
44
# File 'lib/snow-data/c_struct/struct_base.rb', line 42

def bytesize_of(member)
  self.class.bytesize_of(member)
end

#inspectObject

Returns a string describing the struct, including its classname, object ID, address, size, and alignment. In addition, if long_inspect is enabled, then it will also include the values of the struct’s members.



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/snow-data/c_struct/struct_base.rb', line 95

def inspect
  id_text     = __id__.to_s(16).rjust(14, ?0)
  addr_text   = self.address.to_s(16).rjust(14, ?0)

  member_text = if ! null? && ::Snow::CStruct.long_inspect
    # Get member text
    all_members_text = (self.class::MEMBERS.map do |member|
      name        = member.name
      type        = member.type
      align       = member.alignment
      length      = member.length
      length_decl = length > 1 ? "[#{length}]" : ''

      values_text = if length > 1
        single_member_text = (0 ... length).map { |index|
            "[#{ index }]=#{ self.__send__(member.name, index).inspect }"
          }.join(', ')

          "{ #{ single_member_text } }"
        else
          self.__send__(member.name).inspect
        end

      "#{ name }:#{ type }#{ length_decl }:#{ align }=#{ values_text }"

    end).join('; ')

    " #{all_members_text}"
  else # member_text = if ...
    # Skip members
    ''
  end # member_text = if ...

  "<#{ self.class }:0x#{ id_text } *0x#{ addr_text }:#{ self.bytesize }:#{ self.alignment }#{member_text}>"
end

#length_of(member) ⇒ Object

Returns the length of a member.



58
59
60
# File 'lib/snow-data/c_struct/struct_base.rb', line 58

def length_of(member)
  self.class.length_of(member)
end

#offset_of(member) ⇒ Object

Returns the offset of a member.



34
35
36
# File 'lib/snow-data/c_struct/struct_base.rb', line 34

def offset_of(member)
  self.class.offset_of(member)
end

#to_hObject

Returns a hash of all of the struct’s member names to their values.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/snow-data/c_struct/struct_base.rb', line 74

def to_h
  self.class::MEMBERS.inject({}) do |hash, member|
    length = member.length
    name   = member.name

    hash[name] = if length > 1
      (0 ... length).map { |index| __send__(name, index) }
    else
      __send__(name)
    end

    hash
  end
end

#type_of(member) ⇒ Object

Returns the type name of a member.



66
67
68
# File 'lib/snow-data/c_struct/struct_base.rb', line 66

def type_of(member)
  self.class.type_of(member)
end