Class: BinaryStruct

Inherits:
Object
  • Object
show all
Defined in:
lib/binary_struct.rb,
lib/binary_struct/version.rb

Constant Summary collapse

SIZES =
{
  'A'   => 1,   # String with trailing NULs and spaces removed
  'a'   => 1,   # String
  'B'   => nil, # Extract bits from each character (MSB first)
  'b'   => nil, # Extract bits from each character (LSB first)
  'C'   => 1,   # Extract a character as an unsigned integer
  'c'   => 1,   # Extract a character as a    signed integer
  'E'   => nil, # Treat sizeof(double) characters as a double in little-endian byte order
  'e'   => nil, # Treat sizeof(float)  characters as a float  in little-endian byte order
  'G'   => nil, # Treat sizeof(double) characters as a double in network       byte order
  'g'   => nil, # Treat sizeof(float)  characters as a float  in network       byte order
  'H'   => nil, # Extract hex nibbles from each character (most  significant first)
  'h'   => nil, # Extract hex nibbles from each character (least significant first)
  'I'   => 4,   # Treat sizeof(int) successive characters as an unsigned native integer
  'i'   => 4,   # Treat sizeof(int) successive characters as a    signed native integer
  'L'   => 4,   # Treat 4 successive characters as an unsigned native long integer
  'l'   => 4,   # Treat 4 successive characters as a    signed native long integer
  'M'   => 1,   # Extract a quoted printable string
  'm'   => 1,   # Extract a Base64 encoded string
  'N'   => 4,   # Treat 4 characters as an unsigned long  in network byte order
  'n'   => 2,   # Treat 2 characters as an unsigned short in network byte order
  'P'   => nil, # Treat sizeof(char *) characters as a pointer, and return len characters from the referenced location
  'p'   => nil, # Treat sizeof(char *) characters as a pointer to a null-terminated string
  'Q'   => 8,   # Treat 8 characters as an unsigned quad word (64 bits)
  'q'   => 8,   # Treat 8 characters as a    signed quad word (64 bits)
  'S'   => 2,   # Treat 2 successive characters as an unsigned short in native byte order
  's'   => 2,   # Treat 2 successive characters as a    signed short in native byte order
  'U'   => nil, # Extract UTF-8 characters as unsigned integers
  'u'   => nil, # Extract a UU-encoded string
  'V'   => 4,   # Treat 4 characters as an unsigned long  in little-endian byte order
  'v'   => 2,   # Treat 2 characters as an unsigned short in little-endian byte order
  'w'   => nil, # BER-compressed integer
  'X'   => -1,  # Skip backward one character
  'x'   => 1,   # Skip forward  one character
  'Z'   => 1,   # String with trailing NULs removed
}
STRING_FORMATS =
%w(A a M m u)
ENDIAN_FORMATS =
%w(I i L l Q q S s)
ENDIAN_MODIFIERS =
%w(> <)
MODIFIERS =
ENDIAN_MODIFIERS
VERSION =
"2.0.0"
@@structs_by_definition =

Methods to handle the old style of calling

{}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(definition = nil) ⇒ BinaryStruct

Returns a new instance of BinaryStruct.



47
48
49
# File 'lib/binary_struct.rb', line 47

def initialize(definition = nil)
  self.definition = definition unless definition.nil?
end

Class Method Details

.clear_structs_by_definition_cacheObject



132
133
134
# File 'lib/binary_struct.rb', line 132

def self.clear_structs_by_definition_cache
  @@structs_by_definition.clear
end

.decode(data, definition) ⇒ Object



140
141
142
# File 'lib/binary_struct.rb', line 140

def self.decode(data, definition)
  struct_by_definition(definition).decode(data)
end

.encode(hash, definition) ⇒ Object



144
145
146
# File 'lib/binary_struct.rb', line 144

def self.encode(hash, definition)
  struct_by_definition(definition).encode(hash)
end

.sizeof(definition) ⇒ Object



136
137
138
# File 'lib/binary_struct.rb', line 136

def self.sizeof(definition)
  struct_by_definition(definition).size
end

Instance Method Details

#==(other) ⇒ Object



118
119
120
# File 'lib/binary_struct.rb', line 118

def ==(other)
  self.definition == other.definition
end

#decode(data, num = 1) ⇒ Object



70
71
72
73
74
75
76
77
# File 'lib/binary_struct.rb', line 70

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) ⇒ Object

Raises:

  • (ArgumentError)


79
80
81
82
83
84
# File 'lib/binary_struct.rb', line 79

def decode_to_array(data, num = 1)
  raise ArgumentError, "data cannot be nil" if data.nil?
  @decode_format, @decode_names = self.class.prep_decode(@definition) if @decode_format.nil?
  format = (num == 1) ? @decode_format : @decode_format * num
  return data.unpack(format)
end

#decoded_array_to_hash!(array) ⇒ Object



86
87
88
89
90
91
92
93
94
# File 'lib/binary_struct.rb', line 86

def decoded_array_to_hash!(array)
  hash = {}
  @decode_names.each do |k|
    v = array.shift
    next if k.nil?
    hash[k] = v
  end
  return hash
end

#definitionObject



51
52
53
# File 'lib/binary_struct.rb', line 51

def definition
  @definition
end

#definition=(value) ⇒ Object



55
56
57
58
59
60
61
62
63
64
# File 'lib/binary_struct.rb', line 55

def definition=(value)
  if value.kind_of?(self.class)
    @definition = value.definition.dup
  else
    value = Array(value)
    self.class.validate_definition(value)
    @definition = value
  end
  @size = @decode_format = @decode_name = nil
end

#each(&block) ⇒ Object



122
123
124
# File 'lib/binary_struct.rb', line 122

def each(&block)
  self.definition.each_slice(2, &block)
end

#encode(hash) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/binary_struct.rb', line 96

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) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/binary_struct.rb', line 104

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

#sizeObject



66
67
68
# File 'lib/binary_struct.rb', line 66

def size
  @size ||= self.class.get_size(@definition)
end