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 offset doesn’t meet this criteria. A boolean return indicates success or failure. Any other return is compared to the current offset. The variable
offset
is made available to any lambda assigned to this parameter. 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
-
#accepted_parameters ⇒ Object
Returns a list of parameters that are accepted by this object.
-
#clear ⇒ Object
Resets the internal state to that of a newly created object.
-
#do_read(io) ⇒ Object
Reads the value for this data from
io
. -
#done_read ⇒ Object
To be called after calling #do_read.
-
#field_names ⇒ Object
Returns a list of the names of all fields accessible through this object.
-
#initialize(params = {}, env = nil) ⇒ Base
constructor
Creates a new data object.
-
#inspect ⇒ Object
Return a human readable representation of this 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.
-
#snapshot ⇒ Object
Returns a snapshot of this data object.
-
#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.
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 147 148 149 150 151 152 |
# File 'lib/bindata/base.rb', line 116 def initialize(params = {}, env = nil) # all known parameters mandatory = self.class.mandatory_parameters optional = self.class.optional_parameters # default :readwrite param to true if unspecified if not params.has_key?(:readwrite) params = params.dup params[:readwrite] = true end # ensure mandatory parameters exist mandatory.each do |prm| if not params.has_key?(prm) raise ArgumentError, "parameter ':#{prm}' must be specified " + "in #{self}" end end # 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 mandatory.include?(k) or optional.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
.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/bindata/base.rb', line 89 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.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/bindata/base.rb', line 29 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 if not 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.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/bindata/base.rb', line 49 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 if not 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.
67 68 69 70 71 |
# File 'lib/bindata/base.rb', line 67 def parameters # warn about deprecated method - remove before releasing 1.0 warn "warning: #parameters is deprecated." (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.
76 77 78 79 80 |
# File 'lib/bindata/base.rb', line 76 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
.
83 84 85 |
# File 'lib/bindata/base.rb', line 83 def register(name, klass) Registry.instance.register(name, klass) end |
Instance Method Details
#accepted_parameters ⇒ Object
Returns a list of parameters that are accepted by this object
170 171 172 |
# File 'lib/bindata/base.rb', line 170 def accepted_parameters (self.class.mandatory_parameters + self.class.optional_parameters).uniq end |
#clear ⇒ Object
Resets the internal state to that of a newly created object.
273 274 275 |
# File 'lib/bindata/base.rb', line 273 def clear raise NotImplementedError end |
#do_read(io) ⇒ Object
Reads the value for this data from io
.
190 191 192 193 194 |
# File 'lib/bindata/base.rb', line 190 def do_read(io) clear check_offset(io) _do_read(io) if eval_param(:readwrite) != false end |
#done_read ⇒ Object
To be called after calling #do_read.
283 284 285 |
# File 'lib/bindata/base.rb', line 283 def done_read raise NotImplementedError end |
#field_names ⇒ Object
Returns a list of the names of all fields accessible through this object.
304 305 306 |
# File 'lib/bindata/base.rb', line 304 def field_names raise NotImplementedError end |
#inspect ⇒ Object
Return a human readable representation of this object.
213 214 215 |
# File 'lib/bindata/base.rb', line 213 def inspect snapshot.inspect end |
#klass_lookup(name) ⇒ Object
Returns the class matching a previously registered name
.
155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/bindata/base.rb', line 155 def klass_lookup(name) @cache ||= {} klass = @cache[name] if klass.nil? 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 @cache[name] = klass end klass end |
#num_bytes(what = nil) ⇒ Object
Returns the number of bytes it will take to write this data.
202 203 204 |
# File 'lib/bindata/base.rb', line 202 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.
175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/bindata/base.rb', line 175 def read(io) # remove previous method to prevent warnings class << io undef_method(:bindata_mark) if method_defined?(:bindata_mark) end # remember the current position in the IO object io.instance_eval "def bindata_mark; #{io.pos}; end" do_read(io) done_read self end |
#single_value? ⇒ Boolean
Returns whether this data object contains a single value. Single value data objects respond to #value
and #value=
.
208 209 210 |
# File 'lib/bindata/base.rb', line 208 def single_value? respond_to? :value end |
#snapshot ⇒ Object
Returns a snapshot of this data object.
298 299 300 |
# File 'lib/bindata/base.rb', line 298 def snapshot raise NotImplementedError end |
#write(io) ⇒ Object
Writes the value for this data to io
.
197 198 199 |
# File 'lib/bindata/base.rb', line 197 def write(io) _write(io) if eval_param(:readwrite) != false end |