Files
cobol-java-v3/comparator/cobol_binary_reader.py
T
2026-05-24 12:36:44 +08:00

44 lines
1.5 KiB
Python

import struct
from pathlib import Path
from data.field_tree import FieldTree
class CobolBinaryReader:
def read(self, path: str, tree: FieldTree) -> list[dict]:
d = Path(path).read_bytes()
rs = self._record_size(tree)
if rs == 0 or len(d) == 0:
return []
return [self._parse(d[o:o + rs], tree) for o in range(0, len(d), rs) if len(d[o:o + rs]) >= rs]
def _record_size(self, tree):
return max((f.offset + f.length for f in tree.fields), default=0)
def _parse(self, r, tree):
out = {}
for n, f in tree.flatten().items():
if f.length == 0 or f.offset + f.length > len(r):
continue
raw = r[f.offset:f.offset + f.length]
if f.usage == "COMP-3":
out[n] = self._comp3(raw, f.signed, f.decimal)
elif f.usage in ("COMP", "COMP-5"):
out[n] = int.from_bytes(raw, "big", signed=f.signed)
else:
out[n] = raw.decode("ascii", errors="replace").strip()
return out
def _comp3(self, raw, signed, dec):
if not raw:
return "0"
nib = []
for b in raw:
nib.append((b >> 4) & 0xF)
nib.append(b & 0xF)
s = nib.pop()
v = sum(n * (10 ** (len(nib) - i)) for i, n in zip(range(len(nib)), nib))
if signed and s in (0xD, 0xB):
v = -v
d = 10 ** dec
return f"{float(v) / d:.{dec}f}" if dec else str(v)