lib/bindata/base.rb in bindata-0.9.1 vs lib/bindata/base.rb in bindata-0.9.2

- old
+ new

@@ -1,9 +1,9 @@ require 'bindata/io' require 'bindata/lazy' -require 'bindata/sanitize' require 'bindata/registry' +require 'bindata/sanitize' require 'stringio' module BinData # Error raised when unexpected results occur when reading data from IO. class ValidityError < StandardError ; end @@ -13,15 +13,15 @@ # == Parameters # # Parameters may be provided at initialisation to control the behaviour of # an object. These params are: # - # [<tt>:readwrite</tt>] If false, calls to #read or #write will - # not perform any I/O. Default is true. - # [<tt>:onlyif</tt>] This is an alias for :readwrite. It is generally - # used to indicate a data object is optional. - # not perform any I/O. Default is true. + # [<tt>:readwrite</tt>] Deprecated. An alias for :onlyif. + # [<tt>:onlyif</tt>] Used to indicate a data object is optional. + # if false, calls to #read or #write will not + # perform any I/O, #num_bytes will return 0 and + # #snapshot will return nil. Default is true. # [<tt>:check_offset</tt>] 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 @@ -39,11 +39,12 @@ 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) + pmp = parent.mandatory_parameters + @mandatory_parameters.concat(pmp) end end end if not args.empty? args.each { |arg| @mandatory_parameters << arg.to_sym } @@ -59,11 +60,12 @@ 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) + pop = parent.optional_parameters + @optional_parameters.concat(pop) end end end if not args.empty? args.each { |arg| @optional_parameters << arg.to_sym } @@ -79,11 +81,12 @@ def default_parameters(params = {}) unless defined? @default_parameters @default_parameters = {} ancestors[1..-1].each do |parent| if parent.respond_to?(:default_parameters) - @default_parameters = @default_parameters.merge(parent.default_parameters) + pdp = parent.default_parameters + @default_parameters = @default_parameters.merge(pdp) end end end if not params.empty? @default_parameters = @default_parameters.merge(params) @@ -98,11 +101,12 @@ def mutually_exclusive_parameters(*args) unless defined? @mutually_exclusive_parameters @mutually_exclusive_parameters = [] ancestors[1..-1].each do |parent| if parent.respond_to?(:mutually_exclusive_parameters) - @mutually_exclusive_parameters.concat(parent.mutually_exclusive_parameters) + pmep = parent.mutually_exclusive_parameters + @mutually_exclusive_parameters.concat(pmep) end end end if not args.empty? @mutually_exclusive_parameters << [args[0].to_sym, args[1].to_sym] @@ -115,16 +119,17 @@ (mandatory_parameters + optional_parameters + default_parameters.keys).uniq end # Returns a sanitized +params+ that is of the form expected # by #initialize. - def sanitize_parameters(params, *args) + def sanitize_parameters(sanitizer, params, *args) params = params.dup - # replace :onlyif with :readwrite - if params.has_key?(:onlyif) - params[:readwrite] = params.delete(:onlyif) + # replace :readwrite with :onlyif + if params.has_key?(:readwrite) + warn ":readwrite is deprecated. Replacing with :onlyif" + params[:onlyif] = params.delete(:readwrite) end # add default parameters default_parameters.each do |k,v| params[k] = v unless params.has_key?(k) @@ -161,42 +166,25 @@ # Registers the mapping of +name+ to +klass+. def register(name, klass) Registry.instance.register(name, klass) end private :register - - # Returns the class matching a previously registered +name+. - def lookup(name, endian = nil) - name = name.to_s - klass = Registry.instance.lookup(name) - if klass.nil? and endian != nil - # lookup failed so attempt endian lookup - if /^u?int\d{1,3}$/ =~ name - new_name = name + ((endian == :little) ? "le" : "be") - klass = Registry.instance.lookup(new_name) - elsif ["float", "double"].include?(name) - new_name = name + ((endian == :little) ? "_le" : "_be") - klass = Registry.instance.lookup(new_name) - end - end - klass - end end # Define the parameters we use in this class. optional_parameters :check_offset, :adjust_offset - default_parameters :readwrite => true + default_parameters :onlyif => true mutually_exclusive_parameters :check_offset, :adjust_offset # 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. def initialize(params = {}, env = nil) unless SanitizedParameters === params - params = SanitizedParameters.new(self.class, params) + params = Sanitizer.sanitize(self, params) end @params = params.accepted_parameters # set up the environment @@ -219,11 +207,11 @@ raise ArgumentError, "io must be a BinData::IO" unless BinData::IO === io clear check_offset(io) - if eval_param(:readwrite) + if eval_param(:onlyif) _do_read(io) end end # Writes the value for this data to +io+ by calling #do_write. @@ -238,11 +226,11 @@ # Writes the value for this data to +io+. def do_write(io) raise ArgumentError, "io must be a BinData::IO" unless BinData::IO === io - if eval_param(:readwrite) + if eval_param(:onlyif) _do_write(io) end end # Returns the number of bytes it will take to write this data by calling @@ -252,17 +240,27 @@ num.ceil end # Returns the number of bytes it will take to write this data. def do_num_bytes(what = nil) - if eval_param(:readwrite) + if eval_param(:onlyif) _do_num_bytes(what) else 0 end end + # Returns a snapshot of this data object. + # Returns nil if :onlyif is false + def snapshot + if eval_param(:onlyif) + _snapshot + else + nil + end + end + # Returns the string representation of this data object. def to_s io = StringIO.new write(io) io.rewind @@ -334,38 +332,26 @@ end ########################################################################### # To be implemented by subclasses - # Returns a list of the names of all possible field names for an object - # created with +sanitized_params+. - def self.all_possible_field_names(sanitized_params) + # Resets the internal state to that of a newly created object. + def clear raise NotImplementedError end - # Resets the internal state to that of a newly created object. - def clear + # Returns true if the object has not been changed since creation. + def clear?(*args) raise NotImplementedError end # Returns whether this data object contains a single value. Single # value data objects respond to <tt>#value</tt> and <tt>#value=</tt>. def single_value? raise NotImplementedError end - # Returns a list of the names of all fields accessible through this - # object. - def field_names - raise NotImplementedError - end - - # Returns a snapshot of this data object. - def snapshot - raise NotImplementedError - end - # To be called after calling #do_read. def done_read raise NotImplementedError end @@ -382,12 +368,17 @@ # Returns the number of bytes it will take to write this data. def _do_num_bytes raise NotImplementedError end + # Returns a snapshot of this data object. + def _snapshot + raise NotImplementedError + end + # Set visibility requirements of methods to implement - public :clear, :single_value?, :field_names, :snapshot, :done_read - private :_do_read, :_do_write, :_do_num_bytes + public :clear, :clear?, :single_value?, :done_read + private :_do_read, :_do_write, :_do_num_bytes, :_snapshot # End To be implemented by subclasses ########################################################################### end end