Instantly share code, notes, and snippets.

Embed
What would you like to do?
Unsigned LEB128 Converter
#!/usr/bin/env ruby
# Unsigned LEB128 Converter
# https://en.wikipedia.org/wiki/LEB128
def encode( num, with_hex=false)
bs_n = num.to_s(2)
len = bs_n.length
# 0 padding for 7-bit
padding_len = (len / 7 + ( len % 7 > 0 ? 1 : 0 )) * 7
zero_padded = bs_n.rjust(padding_len,"0")
# split into 7-bit groups
groups = []
(zero_padded.length/7).times {|i|
high1bit = i==0 ? "0" : "1"
bits = high1bit + zero_padded.slice!(0,7)
groups.push(bits.to_i(2).to_s(16).rjust(2,'0'))
}
hex = groups.reverse.join
# hex to bin
if with_hex
hex
else
[hex].pack("H*")
end
end
def decode( b128, with_hex=false)
# hex to bin
if with_hex
b128 = [b128].pack("H*")
end
# set BINARY
b128.force_encoding('BINARY')
# decode
groups = []
b128.each_char {|c|
groups.push(c.ord.to_s(2).rjust(8,'0').slice(1,8))
if 0 == c.ord & 0x80
break
end
}
groups.reverse.join.to_i(2)
end
def parse(bytes, offset)
# set BINARY
bytes = bytes.force_encoding('BINARY')
bytes = bytes.slice( offset, bytes.length )
groups = []
bytes.each_char {|c|
groups.push(c)
if 0 == c.ord & 0x80
break
end
}
groups.join.force_encoding('BINARY')
end
# Examples
# encode: Integer to LEB128 Hex String
encode(0, true) # 00
encode(127, true) # 7f
encode(543210, true) # ea9321
encode(543210, true).encoding # <Encoding:US-ASCII>
# encode: Integer to LEB128 Binary
encode(0) # "\x00"
encode(127) # "\x7F"
encode(543210) # "\xEA\x93!"
encode(543210).encoding # <Encoding:ASCII-8BIT>
# decode: LEB128 Hex String to Integer
decode("00", true) # 0
decode("7f", true) # 127
decode("ea9321", true) # 543210
# decode: LEB128 Binary to Integer
decode("\x00") # 0
decode("\x7F") # 127
decode("\xEA\x93!") # 543210
# parse LEB128 by offset
parse("C\x00",1) # "\x00"
parse("C\x7F",1) # "\x7F"
parse("C\xEA\x93!",1) # "\xEA\x93!"
parse("C\xEA\x93!",1).encoding # <Encoding:ASCII-8BIT>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment