class SDL2::Struct

BadQuanta: sdl2_ffi messes with the FFI::Struct class for some useful additions.

Public Class Methods

cast(something) click to toggle source

Default cast handler.

BadQuanta says:

Casting means to take something and try to make it into a Structure
- Other instances of the same class (simply returns that instance)
- Any hash, this structure will be "created" with the has specifying members.
- A nil object, which will return the same nil object assuming that is o.k.
# File lib/sdl2/struct.rb, line 124
def self.cast(something)
  if something.kind_of? self
    Debug.log(self){'No casting required.'}
    return something
  elsif something.kind_of? Hash
    Debug.log(self){'Attempting to construct from hash.'}
    return self.create(something)
  elsif something.nil?
    Debug.log(self){'Something is nil, returning nil.'}
    return something #TODO: Assume NUL is ok?
  else
    # No need for a debug message, exception will act as one.
    raise "#{self} can't cast #{something.insepct}"
  end
end
create(values = {}) click to toggle source

Placeholder for Structs that need to initialize values.

# File lib/sdl2/struct.rb, line 22
def self.create(values = {})
  Debug.log(self){"Constructing with values: #{values.inspect}"}
  created = self.new
  created.update_members(values)
  created
end
new(*args) { |self| ... } click to toggle source

Allows creation and use within block, automatically freeing pointer after block.

Calls superclass method
# File lib/sdl2/struct.rb, line 8
def initialize(*args, &block)
  Debug.log(self){"Initializing with args: #{args.inspect}"}
  super(*args)
  if block_given?
    Debug.log(self){'Block given, will be disposed of later'}
    throw 'Release must be defined to use block' unless self.class.respond_to?(:release)
    yield self
    Debug.log(self){'Block returned, now disposing.'}
    self.class.release(self.pointer)
  end
end
release(pointer) click to toggle source

A default release scheme is defined, but should be redefined where appropriate.

# File lib/sdl2/struct.rb, line 31
def self.release(pointer)
  Debug.log(self){"Freeing pointer: #{pointer.inspect}"}
  pointer.free
end

Public Instance Methods

==(other) click to toggle source

Compare two structures by class and values. This will return true when compared to a “partial hash” and all the key/value pairs the hash defines equal the corrisponding members in the structure. Otherwise all values must match between structures. TODO: CLEAN UP THIS COMPARISON CODE!!!

# File lib/sdl2/struct.rb, line 70
def ==(other)
  Debug.log(self){
    "COMPARING #{self} to #{other}"
  }

  result = catch(:result) do
    unless self.class == other.class or other.kind_of? Hash
      Debug.log(self){"Class Mismatch"}
      throw :result, false
    end

    if (other.kind_of? Hash) and (other.keys - members).any?
      Debug.log(self){"Extra Keys: #{other.keys-members}"}
      thorw :result, false
    end

    if (other.respond_to?:null?) and (self.null? or other.null?)
      unless self.null? and other.null?
        Debug.log(self){"AHHHAOne is null and the other is not"}
        throw :result, false
      end
    else
      fields = other.kind_of?(Hash) ? members & other.keys : members
      fields.each do |field|
        Debug.log(self){"#{field}:#{self[field].class} = "}

        unless self[field] == other[field]

          Debug.log(self){"NO MATCH: #{self[field].to_s} #{other[field].to_s}"}
          throw :result, false
        end
        Debug.log(self){"MATCH"}
      end
    end

    # Everything passed
    throw :result, true

  end
  Debug.log(self){
    "RESULT = #{result}"
  }
  return result
end
free() click to toggle source

A default free operation, but should be redefined where appropriate. TODO: Is this wrong to do in conjuction with release?

# File lib/sdl2/struct.rb, line 39
def free()
  if self.pointer.autorelease?
    Debug.log(self){"Freeing autorelease pointer: #{pointer.inspect}"}
    self.pointer.free
  else
    Debug.log(self){"Not freeing pointer"}
    binding.pry
  end
end
to_s() click to toggle source

Human readable translation of a structure

# File lib/sdl2/struct.rb, line 175
def to_s
  null = self.to_ptr.null?
  values = members.map do |member|
    "#{member}=#{null ? 'null' : self[member]}"
  end unless null
  "<#{self.class.to_s} #{null ? 'NULL' : values.join(' ')}>"
end
update_members(values) click to toggle source

Set members to values contained within hash.

# File lib/sdl2/struct.rb, line 142
def update_members(values)
  Debug.log(self){"Updating members from values: #{values.inspect}"}
  if values.kind_of? Array
    raise "#{self} has less fields then #{values.inspect}" if values.count > members.count
    Debug.log(self){"Field to value map: #{Hash.new(members.first(values.count).zip(values)).inspect}"}
    members.first(values.count).each_with_index do |field, idx|
      self[field] = values[idx]
    end
  elsif values.kind_of? Hash
    common = (self.members & values.keys)
    Debug.log(self){
      ignored_keys = values.keys - common
      ignored_keys.empty? ? "All hash keys mapped to struct members." : "Ignored these value keys: #{ignored_keys.inspect}"
    }
    common.each do |field|
      unless self[field].kind_of?(Struct)
        self[field] = values[field]
      else
        self[field] = self[field].class.cast(values[field])
      end
    end
  elsif values.kind_of? self.class
    Debug.log(self){'Coping values from another instance.'}
    members.each do |member|
      self[member] = values[member]
    end
  else
    raise "#{self}#update_members unable to update from #{values.inspect}"
  end
end