import sys import struct import re __all__ = ['load_bin_file', 'get_data', 'search_data'] type_map = { 'float32': ('f', 4), 'float64': ('d', 8), 'uint16': ('H', 2), 'int16': ('h', 2), 'uint32': ('I', 4), 'int32': ('i', 4), 'uint64': ('Q', 8), 'int64': ('q', 8), } def append_data(metadata, varname, vartype, value, eps): metadata.append({ 'varname': varname, 'vartype': vartype, 'value' : value, 'eps' : eps }) return metadata def guess_vartype(str): try: int(str) return 'int' except: pass try: float(str) return 'float' except: pass return 'str' def find_ascii_strings(in_data, istart, ilast, min_length=4): pattern = rb'[\x20-\x7E]{%d,}' % min_length # ASCII printable characters results = [] for match in re.finditer(pattern, in_data[istart:ilast+1]): offset = match.start() value = match.group().decode('ascii', errors='ignore') results.append((offset, value)) return results def load_bin_file(file_path): with open(file_path, 'rb') as f: return f.read() def extract_ascii_prefix(bin_data, offset, size): chunk = bin_data[offset:offset+size] result = bytearray() for b in chunk: if 0x20 <= b <= 0x7E: result.append(b) else: break # 非ASCII文字が出たら終了 return result.decode('ascii', errors='ignore') def get_data(bin_data, offset, size, vartype, endian='little', varname = None): if endian == 'little': endian_prefix = '<' elif endian == 'big': endian_prefix = '>' else: raise ValueError(f"未対応のエンディアン指定: {endian}") if vartype == 'str': return extract_ascii_prefix(bin_data, offset, size) if vartype in type_map: fmt, expected_size = type_map[vartype] if size != expected_size: raise ValueError(f"サイズ {size} は型 {vartype} に対して不正です(期待値: {expected_size})") try: ret = struct.unpack_from(endian_prefix + fmt, bin_data, offset)[0] return ret except: print(f"Error in binparser.get_data(): Failed to read [{varname}] (type {vartype}) from offset={offset} with size={size}") return None raise ValueError(f"未対応の型: {vartype}") def search_data(bin_data, itop, ilast, size, vartype, endian, value, tolerance=1e-6, varname = 'not given'): # print("**search:", varname, value, vartype, size, tolerance) if endian == 'little': endian_prefix = '<' elif endian == 'big': endian_prefix = '>' else: raise ValueError(f"未対応のエンディアン指定: {endian}") matches = [] if vartype == 'str': for offset in range(itop, ilast - size + 1): chunk = bin_data[offset:offset+size] try: decoded = chunk.decode('utf-8', errors='ignore') if value in decoded: matches.append(offset) except UnicodeDecodeError: continue return matches if vartype not in type_map: raise ValueError(f"未対応の型: {vartype}") fmt, expected_size = type_map[vartype] if size != expected_size: raise ValueError(f"サイズ {size} は型 {vartype} に対して不正です(期待値: {expected_size})") for offset in range(itop, ilast - size + 1): try: val = struct.unpack_from(endian_prefix + fmt, bin_data, offset)[0] if isinstance(val, float): if abs(val - value) <= tolerance: matches.append(offset) else: if val == value: matches.append(offset) except struct.error: continue return matches def main(): bin_file = 'test.raw' endian = 'little' if len(sys.argv) > 1: bin_file = sys.argv[1] if len(sys.argv) > 2: endian = sys.argv[2] bin_data = load_bin_file(bin_file) ilast = len(bin_data) eps = 0.002 for val in [8.0, 120.0, 0.02, 514.902, 552.835]: offsets = search_data(bin_data, 0, ilast, 4, 'float32', endian, val, tolerance=eps) if not offsets: print(f"No data found for {val}") else: for offset in offsets: print(f"offset {offset:08x} for {val}") for val in [5601]: offsets = search_data(bin_data, 0, ilast, 2, 'int16', endian, val) if not offsets: print(f"No data found for {val}") else: for offset in offsets: print(f"offset {offset:08x} for {val}") if __name__ == '__main__': main()