Files
CM95/src/cm93db/dictionaries.py
2026-09-02 09:50:12 +08:00

95 lines
2.5 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from pathlib import Path
TYPE_MAP = {
"aFLOAT": "R",
"aBYTE": "B",
"aSTRING": "S",
"aCMPLX": "C",
"aLIST": "L",
"aWORD10": "W",
"aLONG": "G",
"aNotUsed": "?",
}
@dataclass(frozen=True)
class ObjectDef:
name: str
object_id: int
geometry_code: str
display_code: str | None
description: str | None
raw_line: str
@dataclass(frozen=True)
class AttributeDef:
name: str
attribute_id: int
source_type_name: str
decoder_type: str
min_value: float | None
max_value: float | None
raw_line: str
def _read_lines(path: Path):
for enc in ("utf-8-sig", "cp1252", "latin1"):
try:
return path.read_text(encoding=enc).splitlines()
except UnicodeDecodeError:
pass
raise UnicodeDecodeError("unknown", b"", 0, 1, f"无法读取 {path}")
def load_object_dictionary(path: Path) -> list[ObjectDef]:
out = []
for line in _read_lines(path):
if not line.strip():
continue
parts = line.rstrip("\r\n").split("|")
if len(parts) < 3:
continue
try:
object_id = int(parts[1].strip())
except ValueError:
continue
out.append(ObjectDef(
name=parts[0].strip(),
object_id=object_id,
geometry_code=parts[2].strip(),
display_code=parts[3].strip() if len(parts) > 3 else None,
description=parts[4].strip() if len(parts) > 4 else None,
raw_line=line,
))
return out
def load_attribute_dictionary(path: Path) -> list[AttributeDef]:
out = []
for line in _read_lines(path):
if not line.strip():
continue
parts = [p.strip() for p in line.rstrip("\r\n").split("|")]
if len(parts) < 3:
continue
try:
attribute_id = int(parts[1])
except ValueError:
continue
source_type = parts[2]
def f(i):
if len(parts) <= i or parts[i] == "":
return None
try:
return float(parts[i])
except ValueError:
return None
out.append(AttributeDef(
name=parts[0],
attribute_id=attribute_id,
source_type_name=source_type,
decoder_type=TYPE_MAP.get(source_type, "?"),
min_value=f(3),
max_value=f(4),
raw_line=line,
))
return out