Class: Unpacker
- Inherits:
-
Object
- Object
- Unpacker
- Defined in:
- lib/packer.rb
Instance Attribute Summary collapse
-
#data ⇒ Object
readonly
Returns the value of attribute data.
-
#parsed ⇒ Object
readonly
Returns the value of attribute parsed.
-
#prev ⇒ Object
readonly
Returns the value of attribute prev.
Instance Method Summary collapse
- #get_int ⇒ Object
- #get_raw(size = -1)) ⇒ Object
- #get_string(sanitize = SANITIZE) ⇒ Object
-
#initialize(data) ⇒ Unpacker
constructor
A new instance of Unpacker.
- #str_sanitize(str) ⇒ Object
- #str_sanitize_cc(str) ⇒ Object
Constructor Details
#initialize(data) ⇒ Unpacker
Returns a new instance of Unpacker.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/packer.rb', line 77 def initialize(data) @data = data @prev = [] # all the data already unpacked @parsed = [] # TODO: delete parsed or document it with examples # @parsed.push({ type: 'string', value: str, raw:, len:, pos: }) @red_bytes = 0 # { type: 'int', value: 1, raw: "\x01", len: 1, pos: 0 } if data.instance_of?(String) @data = data.unpack('C*') elsif data.instance_of?(Array) @data = data else raise 'Error: Unpacker expects array of integers or byte string' end end |
Instance Attribute Details
#data ⇒ Object (readonly)
Returns the value of attribute data.
75 76 77 |
# File 'lib/packer.rb', line 75 def data @data end |
#parsed ⇒ Object (readonly)
Returns the value of attribute parsed.
75 76 77 |
# File 'lib/packer.rb', line 75 def parsed @parsed end |
#prev ⇒ Object (readonly)
Returns the value of attribute prev.
75 76 77 |
# File 'lib/packer.rb', line 75 def prev @prev end |
Instance Method Details
#get_int ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/packer.rb', line 136 def get_int return nil if @data.nil? return nil if @data.empty? # TODO: make this more performant # it should not read in ALL bytes # of the WHOLE packed data # it should be max 4 bytes # because bigger ints are not sent anyways bytes = @data.map { |byte| byte.to_s(2).rjust(8, '0') } first = bytes[0] sign = first[1] bits = [] parsed = { type: 'int' } # extended if first[0] == '1' bits << first[2..] bytes = bytes[1..] consumed = 1 bytes.each do |eigth_bits| bits << eigth_bits[1..] consumed += 1 break if eigth_bits[0] == '0' end bits = bits.reverse @prev += @data[0...consumed] parsed[:raw] = @data[0...consumed] parsed[:len] = consumed parsed[:pos] = @red_bytes @red_bytes += consumed @data = @data[consumed..] else # single byte bits = [first[2..]] @prev.push(@data[0]) parsed[:raw] = [@data[0]] parsed[:len] = 1 parsed[:pos] = @red_bytes @red_bytes += 1 @data = @data[1..] end num = bits.join.to_i(2) parsed[:value] = sign == '1' ? -(num + 1) : num @parsed.push(parsed) parsed[:value] end |
#get_raw(size = -1)) ⇒ Object
185 186 187 188 189 190 191 192 193 |
# File 'lib/packer.rb', line 185 def get_raw(size = -1) len = size == -1 ? @data.size : size @prev += @data[...len] pos = @red_bytes @red_bytes += len @parsed.push({ type: 'raw', value: @data[...len], raw: @data[...len], len:, pos: }) # TODO: error if size exceeds @data.size @data.shift(len) end |
#get_string(sanitize = SANITIZE) ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/packer.rb', line 110 def get_string(sanitize = SANITIZE) return nil if @data.nil? str = '' raw = [] len = 0 pos = @red_bytes @data.each_with_index do |byte, index| @prev.push(byte) raw.push(raw) @red_bytes += 1 len += 1 if byte.zero? @data = index == @data.length - 1 ? nil : @data[(index + 1)..] str = str_sanitize(str) unless (sanitize & SANITIZE).zero? str = str_sanitize_cc(str) unless (sanitize & SANITIZE_CC).zero? @parsed.push({ type: 'string', value: str, raw:, len:, pos: }) return str end str += byte.chr end # raise "get_string() failed to find null terminator" # return empty string in case of error '' end |
#str_sanitize(str) ⇒ Object
94 95 96 97 98 99 100 |
# File 'lib/packer.rb', line 94 def str_sanitize(str) letters = str.chars letters.map! do |c| c.ord < 32 && c != "\r" && c != "\n" && c != "\t" ? ' ' : c end letters.join end |
#str_sanitize_cc(str) ⇒ Object
102 103 104 105 106 107 108 |
# File 'lib/packer.rb', line 102 def str_sanitize_cc(str) letters = str.chars letters.map! do |c| c.ord < 32 ? ' ' : c end letters.join end |