lib/bindata/sanitize.rb in bindata-0.9.3 vs lib/bindata/sanitize.rb in bindata-0.10.0

- old
+ new

@@ -1,87 +1,55 @@ +require 'bindata/registry' require 'forwardable' module BinData # A BinData object accepts arbitrary parameters. This class only contains - # parameters that have been sanitized, and categorizes them according to - # whether they are BinData::Base.internal_parameters or are extra. + # parameters that have been sanitized. class SanitizedParameters extend Forwardable - # Sanitize the given parameters. - def initialize(klass, params) - @hash = params - @internal_parameters = {} - @extra_parameters = {} + def initialize(the_class, params) + @parameters = {} - # partition parameters into known and extra parameters - @hash.each do |k,v| + params.each do |k,v| k = k.to_sym if v.nil? - raise ArgumentError, "parameter :#{k} has nil value in #{klass}" + raise ArgumentError, "parameter :#{k} has nil value in #{the_class}" end - if klass.internal_parameters.include?(k) - @internal_parameters[k] = v - else - @extra_parameters[k] = v - end + @parameters[k] = v end end - attr_reader :internal_parameters, :extra_parameters + attr_reader :parameters - def_delegators :@hash, :[], :has_key?, :include?, :keys + def_delegators :@parameters, :[], :has_key?, :include?, :keys end # The Sanitizer sanitizes the parameters that are passed when creating a # BinData object. Sanitizing consists of checking for mandatory, optional # and default parameters and ensuring the values of known parameters are # valid. class Sanitizer class << self - - # Sanitize +params+ for +obj+. + # Sanitize +params+ for +the_class+. # Returns sanitized parameters. - def sanitize(klass, params) + def sanitize(the_class, params) if SanitizedParameters === params params else sanitizer = self.new - sanitizer.sanitize_params(klass, params) + sanitizer.sanitized_params(the_class, params) end end - - # Returns true if +type+ is registered. - def type_exists?(type, endian = nil) - lookup(type, endian) != nil - end - - # Returns the class matching a previously registered +name+. - def lookup(name, endian) - 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 - # Create a new Sanitizer. def initialize - @seen = [] @endian = nil + @seen = [] end # Executes the given block with +endian+ set as the current endian. def with_endian(endian, &block) if endian != nil @@ -92,46 +60,63 @@ else yield end end - # Converts +type+ into the appropriate class. - def lookup_klass(type) - klass = self.class.lookup(type, @endian) - raise TypeError, "unknown type '#{type}'" if klass.nil? - klass + def lookup_class(type) + registered_class = RegisteredClasses.lookup(type, @endian) + if registered_class.nil? + raise TypeError, "unknown type '#{type}'" + end + registered_class end - # Sanitizes +params+ for +klass+. - # Returns +sanitized_params+. - def sanitize_params(klass, params) + def sanitized_params(the_class, params) new_params = params.nil? ? {} : params.dup - if klass.recursive? and @seen.include?(klass) - # This klass is defined recursively. Remember the current endian - # and delay sanitizing the parameters until later. - new_params[:endian] = @endian if can_store_endian?(klass, new_params) - ret_val = new_params + if can_sanitize_parameters?(the_class) + get_sanitized_params(the_class, new_params) else - @seen.push(klass) + store_current_endian!(the_class, new_params) + new_params + end + end - # Sanitize new_params. This may recursively call this method again. - klass.sanitize_parameters!(self, new_params) - ret_val = SanitizedParameters.new(klass, new_params) + #--------------- + private - @seen.pop + def can_sanitize_parameters?(the_class) + not need_to_delay_sanitizing?(the_class) + end + + def need_to_delay_sanitizing?(the_class) + the_class.recursive? and @seen.include?(the_class) + end + + def get_sanitized_params(the_class, params) + result = nil + with_class_to_sanitize(the_class) do + the_class.sanitize_parameters!(self, params) + result = SanitizedParameters.new(the_class, params) end + result + end - ret_val + def with_class_to_sanitize(the_class, &block) + @seen.push(the_class) + yield + @seen.pop end - #--------------- - private + def store_current_endian!(the_class, params) + if can_store_endian?(the_class, params) + params[:endian] = @endian + end + end - # Can we store the current endian for later? - def can_store_endian?(klass, params) - (@endian != nil and klass.internal_parameters.include?(:endian) and + def can_store_endian?(the_class, params) + (@endian != nil and + the_class.accepted_internal_parameters.include?(:endian) and not params.has_key?(:endian)) end end end -