lib/struct_packing/base.rb in struct_packing-0.0.2 vs lib/struct_packing/base.rb in struct_packing-0.0.3

- old
+ new

@@ -8,84 +8,142 @@ private def self.included(base) base.extend ClassMethods + base.attr_mapped_struct + + base.instance_eval { @selfclass = base } + base.instance_eval { def selfclass ; @selfclass ; end } end - - public + protected + + # get self class or eign class. + def selfclass + if defined?(self.class.selfclass) + self.class.selfclass + else + eign = (class << self; self ; end) + eign.selfclass + end + end + # Get structure format string used in packing this object. # # This method work as just wrapper to same name class-method. def internal_format - self.class.internal_format + selfclass.send(:internal_format) end + + public - # Get field name list of this class. - def field_names - self.class.field_names - end - - # Get field type list of this class. - def field_types - self.class.field_types - end - - # Get Ruby's pack tenplate string for this class. + # Get Ruby's pack template string for this class. def pack_template - self.class.pack_template + selfclass.pack_template end # Common extending methods for Packable and Unpackable. # # Automatically extend on including StructPacking::Base module. module ClassMethods private - - # TODO temporary initializer for @@struct_internal_format - def check_vardef - if not self.class_variable_defined?(:@@struct_internal_format) - class_eval("@@struct_internal_format = ''") + + def self.extended(base) + base.class_eval do + begin + @struct_field_getter = superclass.class_eval { @struct_field_getter } + rescue + @struct_field_getter = nil + end + begin + @struct_field_setter = superclass.class_eval { @struct_field_setter } + rescue + @struct_field_setter = nil + end + begin + @struct_internal_format = superclass.class_eval { @struct_internal_format } + if @struct_internal_format == nil + @struct_internal_format = "" + end + rescue + @struct_internal_format = "" + end end end - public + protected # Get internal structure format used to pack a object of this class. def internal_format - check_vardef # TODO Find more good way! - - Util.internal_format_from( self.class_variable_get(:@@struct_internal_format) ) + Util.internal_format_from( @struct_internal_format) end + + public # Set structure format for this class by string. def byte_format=(text) - check_vardef # TODO Find more good way! - - self.class_variable_set(:@@struct_internal_format, text) + @struct_internal_format = text true end - # Get field name list of this class. - def field_names - internal_format.keys + public + + # Get Ruby's pack template string for this class. + def pack_template + if self.to_s =~ /^.*<(.*):0x.*/ + clsname = $1 + else + clsname = self.to_s + end + + Util.pack_template_from( @struct_internal_format, clsname ) end - - # Get field type list of this class. - def field_types - internal_format.values + + # Call getter procedure to get field of target object. + def get_field_value(obj, name) + begin + @struct_field_getter.call(obj, name) + rescue + 0 + end end + + # Call setter procedure to set value to the field of target object. + def set_field_value(obj, name, value) + begin + @struct_field_setter.call(obj, name, value) + rescue + end + end - # Get Ruby's pack tenplate string for this class. - def pack_template - check_vardef # TODO Find more good way! - - Util.pack_template_from( self.class_variable_get(:@@struct_internal_format) ) + # Set gettter procedure. + def set_field_getter(&block) + @struct_field_getter = block end + + # Set settter procedure. + def set_field_setter(&block) + @struct_field_setter = block + end + + # Declare this struct as accessible by hash-style-access(access by [] operator). + def hash_mapped_struct + set_field_getter {|obj, name| obj[name.to_sym] } + set_field_setter {|obj, name, value| obj[name.to_sym] = value } + end + + # Declare this struct as accessible by attr-style-access(access by {name}= operator). + # This is default behavior. + def attr_mapped_struct + set_field_getter {|obj, name| obj.send(name) } + set_field_setter {|obj, name, value| obj.send("#{name}=", value) } + end + alias :define_struct :byte_format= + end end end