153 lines
3.8 KiB
Ruby
153 lines
3.8 KiB
Ruby
require 'bin_utils'
|
|
|
|
module Mikunyan
|
|
# Class for manipulating binary string
|
|
# @attr [Symbol] endian endianness
|
|
# @attr [Integer] pos position
|
|
# @attr [Integer] length data size
|
|
class BinaryReader
|
|
attr_accessor :endian, :pos, :length
|
|
|
|
# Constructor
|
|
# @param [String] data binary string
|
|
# @param [Symbol] endian endianness
|
|
def initialize(data, endian = :big)
|
|
@data = data
|
|
@pos = 0
|
|
@length = data.bytesize
|
|
@endian = endian
|
|
end
|
|
|
|
# Returns whether little endian or not
|
|
# @return [Boolean]
|
|
def little?
|
|
@endian == :little
|
|
end
|
|
|
|
# Jump to given position
|
|
# @param [Integer] pos position
|
|
def jmp(pos=0)
|
|
@pos = pos
|
|
end
|
|
|
|
# Advance position given size
|
|
# @param [Integer] size size
|
|
def adv(size=0)
|
|
@pos += size
|
|
end
|
|
|
|
# Round up position to multiple of given size
|
|
# @param [Integer] size size
|
|
def align(size)
|
|
@pos = (@pos + size - 1) / size * size
|
|
end
|
|
|
|
# Read given size of binary string and seek
|
|
# @param [Integer] size size
|
|
# @return [String] data
|
|
def read(size)
|
|
data = @data.byteslice(@pos, size)
|
|
@pos += size
|
|
data
|
|
end
|
|
|
|
# Read string until null character
|
|
# @return [String] string
|
|
def cstr
|
|
r = @data.unpack("@#{pos}Z*")[0]
|
|
@pos += r.bytesize + 1
|
|
r
|
|
end
|
|
|
|
# Read 8bit signed integer
|
|
def i8
|
|
i8s
|
|
end
|
|
|
|
# Read 8bit signed integer
|
|
def i8s
|
|
r = BinUtils.get_sint8(@data, @pos)
|
|
@pos += 1
|
|
r
|
|
end
|
|
|
|
# Read 8bit unsigned integer
|
|
def i8u
|
|
r = BinUtils.get_int8(@data, @pos)
|
|
@pos += 1
|
|
r
|
|
end
|
|
|
|
# Read 16bit signed integer
|
|
def i16
|
|
i16s
|
|
end
|
|
|
|
# Read 16bit signed integer
|
|
def i16s
|
|
r = little? ? BinUtils.get_sint16_le(@data, @pos) : BinUtils.get_sint16_be(@data, @pos)
|
|
@pos += 2
|
|
r
|
|
end
|
|
|
|
# Read 16bit unsigned integer
|
|
def i16u
|
|
r = little? ? BinUtils.get_int16_le(@data, @pos) : BinUtils.get_int16_be(@data, @pos)
|
|
@pos += 2
|
|
r
|
|
end
|
|
|
|
# Read 32bit signed integer
|
|
def i32
|
|
i32s
|
|
end
|
|
|
|
# Read 32bit signed integer
|
|
def i32s
|
|
r = little? ? BinUtils.get_sint32_le(@data, @pos) : BinUtils.get_sint32_be(@data, @pos)
|
|
@pos += 4
|
|
r
|
|
end
|
|
|
|
# Read 32bit unsigned integer
|
|
def i32u
|
|
r = little? ? BinUtils.get_int32_le(@data, @pos) : BinUtils.get_int32_be(@data, @pos)
|
|
@pos += 4
|
|
r
|
|
end
|
|
|
|
# Read 64bit signed integer
|
|
def i64
|
|
i64s
|
|
end
|
|
|
|
# Read 64bit signed integer
|
|
def i64s
|
|
r = little? ? BinUtils.get_sint64_le(@data, @pos) : BinUtils.get_sint64_be(@data, @pos)
|
|
@pos += 8
|
|
r
|
|
end
|
|
|
|
# Read 64bit unsigned integer
|
|
def i64u
|
|
r = little? ? BinUtils.get_int64_le(@data, @pos) : BinUtils.get_int64_be(@data, @pos)
|
|
@pos += 8
|
|
r
|
|
end
|
|
|
|
# Read 32bit floating point value
|
|
def float
|
|
r = little? ? @data.byteslice(@pos, 4).unpack('e')[0] : @data.byteslice(@pos, 4).unpack('g')[0]
|
|
@pos += 4
|
|
r
|
|
end
|
|
|
|
# Read 64bit floating point value
|
|
def double
|
|
r = little? ? @data.byteslice(@pos, 8).unpack('E')[0] : @data.byteslice(@pos, 8).unpack('G')[0]
|
|
@pos += 8
|
|
r
|
|
end
|
|
end
|
|
end
|