class Bistro
Constants
- BIT_FORMATS
- ENDIAN_FORMATS
- ENDIAN_MODIFIERS
- MODIFIERS
- NIBBLE_FORMATS
- SIZES
- STRING_FORMATS
- VERSION
Public Class Methods
clear_structs_by_definition_cache()
click to toggle source
# File lib/bistro.rb, line 153 def self.clear_structs_by_definition_cache @@structs_by_definition.clear end
decode(data, definition)
click to toggle source
# File lib/bistro.rb, line 161 def self.decode(data, definition) struct_by_definition(definition).decode(data) end
encode(hash, definition)
click to toggle source
# File lib/bistro.rb, line 165 def self.encode(hash, definition) struct_by_definition(definition).encode(hash) end
new(definition = nil)
click to toggle source
# File lib/bistro.rb, line 49 def initialize(definition = nil) self.definition = definition unless definition.nil? end
sizeof(definition)
click to toggle source
# File lib/bistro.rb, line 157 def self.sizeof(definition) struct_by_definition(definition).size end
Private Class Methods
get_size(definition)
click to toggle source
# File lib/bistro.rb, line 225 def self.get_size(definition) size = 0 definition.each_slice(2) do |format, _| type, count = format[0, 1], format[1..-1] modifier, modcount = count[0, 1], count[1..-1] count = modcount if valid_definition_entry_modifier?(modifier) count = count.empty? ? 1 : count.to_i size += if BIT_FORMATS.include?(type) (count / 8.0).ceil elsif NIBBLE_FORMATS.include?(type) (count / 2.0).ceil else count * SIZES[type] end end size end
prep_decode(definition)
click to toggle source
# File lib/bistro.rb, line 247 def self.prep_decode(definition) formats = "" types = [] names = [] counts = [] definition.each_slice(2) do |format, name| type, count = format[0, 1], format[1..-1] modifier, modcount = count[0, 1], count[1..-1] count = modcount if valid_definition_entry_modifier?(modifier) count = 1 if count.empty? types << type formats << format names << name counts << count end return types, formats, names, counts end
struct_by_definition(definition)
click to toggle source
# File lib/bistro.rb, line 171 def self.struct_by_definition(definition) @@structs_by_definition[definition] ||= definition.kind_of?(self) ? definition : self.new(definition) end
valid_definition_entry_modifier?(modifier)
click to toggle source
# File lib/bistro.rb, line 212 def self.valid_definition_entry_modifier?(modifier) MODIFIERS.include? modifier end
validate_definition(definition)
click to toggle source
# File lib/bistro.rb, line 177 def self.validate_definition(definition) raise "definition must be an array of format/name pairs" if definition.empty? || definition.length % 2 != 0 definition.each_slice(2) do |format, _| type, count = format[0, 1], format[1..-1] modifier, modcount = count[0, 1], count[1..-1] validate_definition_entry_type(type) if valid_definition_entry_modifier?(modifier) validate_definition_endian_modifier(modifier, type) validate_definition_entry_count(modcount) else validate_definition_entry_count(count) end end end
validate_definition_endian_modifier(modifier, type)
click to toggle source
# File lib/bistro.rb, line 216 def self.validate_definition_endian_modifier(modifier, type) if ENDIAN_MODIFIERS.include? modifier raise "unsupported type attribute #{type} "\ "for endian modifier #{modifier}" unless ENDIAN_FORMATS.include? type return true end false end
validate_definition_entry_count(count)
click to toggle source
# File lib/bistro.rb, line 201 def self.validate_definition_entry_count(count) return true if count.empty? || count == '*' begin count = Integer(count) rescue raise "unsupported count: #{count}" end raise "unsupported count: #{count}" if count < 0 end
validate_definition_entry_type(type)
click to toggle source
# File lib/bistro.rb, line 195 def self.validate_definition_entry_type(type) raise "unrecognized format: #{type}" unless SIZES.has_key?(type) raise "unsupported format: #{type}" if SIZES[type].nil? return true end
Public Instance Methods
==(other)
click to toggle source
# File lib/bistro.rb, line 139 def ==(other) self.definition == other.definition end
decode(data, num = 1)
click to toggle source
# File lib/bistro.rb, line 76 def decode(data, num = 1) values = self.decode_to_array(data, num) return self.decoded_array_to_hash!(values) if num == 1 result = [] num.times { result << self.decoded_array_to_hash!(values) } return result end
decode_to_array(data, num = 1)
click to toggle source
# File lib/bistro.rb, line 85 def decode_to_array(data, num = 1) raise ArgumentError, "data cannot be nil" if data.nil? @decode_types, @decode_formats, @decode_names, @decode_counts = self.class.prep_decode(@definition) if @decode_formats.nil? format = (num == 1) ? @decode_formats : @decode_formats * num return data.unpack(format) end
decoded_array_to_hash!(array)
click to toggle source
# File lib/bistro.rb, line 95 def decoded_array_to_hash!(array) hash = {} @decode_names.each_with_index do |k,i| c = @decode_counts[i].to_i t = @decode_types[i] v = nil if !STRING_FORMATS.include?(t) && c != 1 v = 0.upto(c-1).collect { array.shift } else v = array.shift end next if k.nil? hash[k] = v end return hash end
definition()
click to toggle source
# File lib/bistro.rb, line 53 def definition @definition end
definition=(value)
click to toggle source
# File lib/bistro.rb, line 57 def definition=(value) if value.kind_of?(self.class) @definition = value.definition.dup else value = value.to_a.map(&:reverse).flatten if value.kind_of?(Hash) value = Array(value) self.class.validate_definition(value) @definition = value end @size = @decode_types = @decode_formats = @decode_names = @decode_counts = nil end
each(&block)
click to toggle source
# File lib/bistro.rb, line 143 def each(&block) self.definition.each_slice(2, &block) end
encode(hash)
click to toggle source
# File lib/bistro.rb, line 114 def encode(hash) return encode_hash(hash) unless hash.kind_of?(Array) data = "" hash.each { |h| data << self.encode_hash(h) } return data end
encode_hash(hash)
click to toggle source
# File lib/bistro.rb, line 122 def encode_hash(hash) data = "" @definition.each_slice(2) do |format, name| raise "member not found: #{name}" unless name.nil? || hash.has_key?(name) value = unless name.nil? hash[name] else STRING_FORMATS.include?(format[0, 1]) ? '0' : 0 end data << [value].pack(format) end return data end
size()
click to toggle source
# File lib/bistro.rb, line 72 def size @size ||= self.class.get_size(@definition) end