Class: BinData::SingleValue
- Defined in:
- lib/bindata/single_value.rb
Overview
A SingleValue is a declarative way to define a new BinData data type. The data type must contain a single value only. For new data types that contain multiple values see BinData::MultiValue.
To define a new data type, set fields as if for MultiValue and add a #get and #set method to extract / convert the data between the fields and the #value of the object.
require 'bindata'
class PascalString < BinData::SingleValue
uint8 :len, :value => lambda { data.length }
string :data, :read_length => :len
def get
self.data
end
def set(v)
self.data = v
end
end
ps = PascalString.new(:initial_value => "hello")
ps.to_s #=> "\005hello"
ps.read("\003abcde")
ps.value #=> "abc"
# Unsigned 24 bit big endian integer
class Uint24be < BinData::SingleValue
uint8 :byte1
uint8 :byte2
uint8 :byte3
def get
(self.byte1 << 16) | (self.byte2 << 8) | self.byte3
end
def set(v)
v = 0 if v < 0
v = 0xffffff if v > 0xffffff
self.byte1 = (v >> 16) & 0xff
self.byte2 = (v >> 8) & 0xff
self.byte3 = v & 0xff
end
end
u24 = Uint24be.new
u24.read("\x12\x34\x56")
"0x%x" % u24.value #=> 0x123456
Parameters
SingleValue objects accept all the parameters that BinData::Single do.
Class Method Summary collapse
-
.endian(endian = nil) ⇒ Object
Returns or sets the endianess of numerics used in this stucture.
-
.fields ⇒ Object
Returns all stored fields.
-
.inherited(subclass) ⇒ Object
Register the names of all subclasses of this class.
-
.method_missing(symbol, *args) ⇒ Object
Used to define fields for the internal structure.
-
.sanitize_parameters(params, endian = nil) ⇒ Object
Returns a sanitized
params
that is of the form expected by #initialize.
Instance Method Summary collapse
-
#initialize(params = {}, env = nil) ⇒ SingleValue
constructor
A new instance of SingleValue.
-
#method_missing(symbol, *args, &block) ⇒ Object
Forward method calls to the internal struct.
Methods inherited from Single
#_do_read, #_num_bytes, #_write, all_possible_field_names, #clear, #clear?, #done_read, #field_names, #single_value?, #snapshot, #value, #value=
Methods inherited from Base
accepted_parameters, #clear, default_parameters, #do_read, #done_read, #field_names, #inspect, lookup, mandatory_parameters, mutually_exclusive_parameters, #num_bytes, optional_parameters, read, #read, register, #single_value?, #snapshot, #to_s, #write
Constructor Details
#initialize(params = {}, env = nil) ⇒ SingleValue
Returns a new instance of SingleValue.
150 151 152 153 154 |
# File 'lib/bindata/single_value.rb', line 150 def initialize(params = {}, env = nil) super(params, env) @struct = BinData::Struct.new(param(:struct_params), create_env) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(symbol, *args, &block) ⇒ Object
Forward method calls to the internal struct.
157 158 159 160 161 162 163 |
# File 'lib/bindata/single_value.rb', line 157 def method_missing(symbol, *args, &block) if @struct.respond_to?(symbol) @struct.__send__(symbol, *args, &block) else super end end |
Class Method Details
.endian(endian = nil) ⇒ Object
Returns or sets the endianess of numerics used in this stucture. Endianess is applied to the fields of this structure. Valid values are :little and :big.
73 74 75 76 77 78 79 80 81 |
# File 'lib/bindata/single_value.rb', line 73 def endian(endian = nil) @endian ||= nil if [:little, :big].include?(endian) @endian = endian elsif endian != nil raise ArgumentError, "unknown value for endian '#{endian}'" end @endian end |
.fields ⇒ Object
Returns all stored fields. Should only be called by #sanitize_parameters
85 86 87 |
# File 'lib/bindata/single_value.rb', line 85 def fields @fields || [] end |
.inherited(subclass) ⇒ Object
Register the names of all subclasses of this class.
66 67 68 |
# File 'lib/bindata/single_value.rb', line 66 def inherited(subclass) #:nodoc: register(subclass.name, subclass) end |
.method_missing(symbol, *args) ⇒ Object
Used to define fields for the internal structure.
90 91 92 93 94 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 |
# File 'lib/bindata/single_value.rb', line 90 def method_missing(symbol, *args) name, params = args type = symbol name = (name.nil? or name == "") ? nil : name.to_s params ||= {} # note that fields are stored in an instance variable not a class var @fields ||= [] # check that type is known if lookup(type, endian).nil? raise TypeError, "unknown type '#{type}' for #{self}", caller end # check that name is okay if name != nil # check for duplicate names @fields.each do |t, n, p| if n == name raise SyntaxError, "duplicate field '#{name}' in #{self}", caller end end # check that name doesn't shadow an existing method if self.instance_methods.include?(name) raise NameError.new("", name), "field '#{name}' shadows an existing method", caller end end # remember this field. These fields will be recalled upon creating # an instance of this class @fields.push([type, name, params]) end |
.sanitize_parameters(params, endian = nil) ⇒ Object
Returns a sanitized params
that is of the form expected by #initialize.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/bindata/single_value.rb', line 128 def sanitize_parameters(params, endian = nil) params = params.dup # possibly override endian endian = self.endian || endian hash = {} hash[:fields] = self.fields unless endian.nil? hash[:endian] = endian end params[:struct_params] = hash super(params, endian) end |