Class: BinData::Base
- Inherits:
-
Object
- Object
- BinData::Base
- Defined in:
- lib/bindata/base.rb
Overview
This is the abstract base class for all data objects.
Parameters
Parameters may be provided at initialisation to control the behaviour of an object. These params are:
:readwrite
-
If false, calls to #read or #write will not perform any I/O. Default is true.
:check_offset
-
Raise an error if the current IO offest doesn’t meet this criteria. A boolean return indicates success or failure. Any other return is compared to the current offset. This parameter is only checked before reading.
Class Method Summary collapse
-
.lookup(name) ⇒ Object
Returns the class matching a previously registered
name
. -
.mandatory_parameters(*args) ⇒ Object
(also: mandatory_parameter)
Returns the mandatory parameters used by this class.
-
.optional_parameters(*args) ⇒ Object
(also: optional_parameter)
Returns the optional parameters used by this class.
-
.parameters ⇒ Object
Returns both the mandatory and optional parameters used by this class.
-
.read(io) ⇒ Object
Instantiates this class and reads from
io
. -
.register(name, klass) ⇒ Object
Registers the mapping of
name
toklass
.
Instance Method Summary collapse
-
#do_read(io) ⇒ Object
Reads the value for this data from
io
. -
#initialize(params = {}, env = nil) ⇒ Base
constructor
Creates a new data object.
-
#klass_lookup(name) ⇒ Object
Returns the class matching a previously registered
name
. -
#num_bytes(what = nil) ⇒ Object
Returns the number of bytes it will take to write this data.
-
#read(io) ⇒ Object
Reads data into this bin object by calling #do_read then #done_read.
-
#single_value? ⇒ Boolean
Returns whether this data object contains a single value.
-
#write(io) ⇒ Object
Writes the value for this data to
io
.
Constructor Details
#initialize(params = {}, env = nil) ⇒ Base
Creates a new data object.
params
is a hash containing symbol keys. Some params may reference callable objects (methods or procs). env
is the environment that these callable objects are evaluated in.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/bindata/base.rb', line 112 def initialize(params = {}, env = nil) # default :readwrite param to true if unspecified unless params.has_key?(:readwrite) params = params.dup params[:readwrite] = true end # ensure mandatory parameters exist self.class.mandatory_parameters.each do |prm| unless params.has_key?(prm) raise ArgumentError, "parameter ':#{prm}' must be specified " + "in #{self}" end end known_params = self.class.parameters # partition parameters into known and extra parameters @params = {} extra = {} params.each do |k,v| k = k.to_sym raise ArgumentError, "parameter :#{k} is nil in #{self}" if v.nil? if known_params.include?(k) @params[k] = v.freeze else extra[k] = v.freeze end end # set up the environment @env = env || LazyEvalEnv.new @env.params = extra @env.data_object = self end |
Class Method Details
.lookup(name) ⇒ Object
Returns the class matching a previously registered name
.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/bindata/base.rb', line 85 def lookup(name) klass = Registry.instance.lookup(name) if klass.nil? # lookup failed so attempt endian lookup if self.respond_to?(:endian) and self.endian != nil name = name.to_s if /^u?int\d\d?$/ =~ name new_name = name + ((self.endian == :little) ? "le" : "be") klass = Registry.instance.lookup(new_name) elsif ["float", "double"].include?(name) new_name = name + ((self.endian == :little) ? "_le" : "_be") klass = Registry.instance.lookup(new_name) end end end klass end |
.mandatory_parameters(*args) ⇒ Object Also known as: mandatory_parameter
Returns the mandatory parameters used by this class. Any given args are appended to the parameters list. The parameters for a class will include the parameters of its ancestors.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/bindata/base.rb', line 27 def mandatory_parameters(*args) unless defined? @mandatory_parameters @mandatory_parameters = [] ancestors[1..-1].each do |parent| if parent.respond_to?(:mandatory_parameters) @mandatory_parameters.concat(parent.mandatory_parameters) end end end unless (args.empty?) args.each { |arg| @mandatory_parameters << arg.to_sym } @mandatory_parameters.uniq! end @mandatory_parameters end |
.optional_parameters(*args) ⇒ Object Also known as: optional_parameter
Returns the optional parameters used by this class. Any given args are appended to the parameters list. The parameters for a class will include the parameters of its ancestors.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/bindata/base.rb', line 47 def optional_parameters(*args) unless defined? @optional_parameters @optional_parameters = [] ancestors[1..-1].each do |parent| if parent.respond_to?(:optional_parameters) @optional_parameters.concat(parent.optional_parameters) end end end unless (args.empty?) args.each { |arg| @optional_parameters << arg.to_sym } @optional_parameters.uniq! end @optional_parameters end |
.parameters ⇒ Object
Returns both the mandatory and optional parameters used by this class.
65 66 67 |
# File 'lib/bindata/base.rb', line 65 def parameters (mandatory_parameters + optional_parameters).uniq end |
.read(io) ⇒ Object
Instantiates this class and reads from io
. For single value objects just the value is returned, otherwise the newly created data object is returned.
72 73 74 75 76 |
# File 'lib/bindata/base.rb', line 72 def read(io) data = self.new data.read(io) data.single_value? ? data.value : data end |
.register(name, klass) ⇒ Object
Registers the mapping of name
to klass
.
79 80 81 |
# File 'lib/bindata/base.rb', line 79 def register(name, klass) Registry.instance.register(name, klass) end |
Instance Method Details
#do_read(io) ⇒ Object
Reads the value for this data from io
.
168 169 170 171 172 |
# File 'lib/bindata/base.rb', line 168 def do_read(io) clear check_offset(io) _do_read(io) if eval_param(:readwrite) != false end |
#klass_lookup(name) ⇒ Object
Returns the class matching a previously registered name
.
149 150 151 152 153 154 155 156 |
# File 'lib/bindata/base.rb', line 149 def klass_lookup(name) klass = self.class.lookup(name) if klass.nil? and @env.parent_data_object != nil # lookup failed so retry in the context of the parent data object klass = @env.parent_data_object.klass_lookup(name) end klass end |
#num_bytes(what = nil) ⇒ Object
Returns the number of bytes it will take to write this data.
180 181 182 |
# File 'lib/bindata/base.rb', line 180 def num_bytes(what = nil) (eval_param(:readwrite) != false) ? _num_bytes(what) : 0 end |
#read(io) ⇒ Object
Reads data into this bin object by calling #do_read then #done_read.
159 160 161 162 163 164 165 |
# File 'lib/bindata/base.rb', line 159 def read(io) # remember the current position in the IO object io.instance_eval "def mark; #{io.pos}; end" do_read(io) done_read end |
#single_value? ⇒ Boolean
Returns whether this data object contains a single value. Single value data objects respond to #value
and #value=
.
186 187 188 |
# File 'lib/bindata/base.rb', line 186 def single_value? respond_to? :value end |
#write(io) ⇒ Object
Writes the value for this data to io
.
175 176 177 |
# File 'lib/bindata/base.rb', line 175 def write(io) _write(io) if eval_param(:readwrite) != false end |