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}
VERSION =
"1.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.



44
45
46
# File 'lib/binary_struct.rb', line 44

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

Class Method Details

.clear_structs_by_definition_cacheObject



129
130
131
# File 'lib/binary_struct.rb', line 129

def self.clear_structs_by_definition_cache
  @@structs_by_definition.clear
end

.decode(data, definition) ⇒ Object



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

def self.decode(data, definition)
  d = @@structs_by_definition[definition]
  d = @@structs_by_definition[definition] = definition.kind_of?(self) ? definition : self.new(definition) if d.nil?
  d.decode(data)
end

.encode(hash, definition) ⇒ Object



145
146
147
148
149
# File 'lib/binary_struct.rb', line 145

def self.encode(hash, definition)
  d = @@structs_by_definition[definition]
  d = @@structs_by_definition[definition] = definition.kind_of?(self) ? definition : self.new(definition) if d.nil?
  d.encode(hash)
end

.sizeof(definition) ⇒ Object



133
134
135
136
137
# File 'lib/binary_struct.rb', line 133

def self.sizeof(definition)
  d = @@structs_by_definition[definition]
  d = @@structs_by_definition[definition] = definition.kind_of?(self) ? definition : self.new(definition) if d.nil?
  d.size
end

Instance Method Details

#==(other) ⇒ Object



115
116
117
# File 'lib/binary_struct.rb', line 115

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

#decode(data, num = 1) ⇒ Object



67
68
69
70
71
72
73
74
# File 'lib/binary_struct.rb', line 67

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)


76
77
78
79
80
81
# File 'lib/binary_struct.rb', line 76

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



83
84
85
86
87
88
89
90
91
# File 'lib/binary_struct.rb', line 83

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



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

def definition
  @definition
end

#definition=(value) ⇒ Object



52
53
54
55
56
57
58
59
60
61
# File 'lib/binary_struct.rb', line 52

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



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

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

#encode(hash) ⇒ Object



93
94
95
96
97
98
99
# File 'lib/binary_struct.rb', line 93

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



101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/binary_struct.rb', line 101

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



63
64
65
# File 'lib/binary_struct.rb', line 63

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