mirror of
https://github.com/dgelessus/python-rsrcfork.git
synced 2025-02-02 18:33:10 +00:00
Refactor __main__.main into smaller functions
This commit is contained in:
parent
194c886472
commit
51ae7c6a09
@ -214,7 +214,7 @@ def _describe_resource(res: api.Resource, *, include_type: bool, decompress: boo
|
|||||||
desc = f"'{restype}' {desc}"
|
desc = f"'{restype}' {desc}"
|
||||||
return desc
|
return desc
|
||||||
|
|
||||||
def main():
|
def _parse_args() -> argparse.Namespace:
|
||||||
ap = argparse.ArgumentParser(
|
ap = argparse.ArgumentParser(
|
||||||
add_help=False,
|
add_help=False,
|
||||||
fromfile_prefix_chars="@",
|
fromfile_prefix_chars="@",
|
||||||
@ -249,6 +249,128 @@ def main():
|
|||||||
ap.add_argument("filter", nargs="*", help="One or more filters to select which resources to display, or omit to show an overview of all resources")
|
ap.add_argument("filter", nargs="*", help="One or more filters to select which resources to display, or omit to show an overview of all resources")
|
||||||
|
|
||||||
ns = ap.parse_args()
|
ns = ap.parse_args()
|
||||||
|
return ns
|
||||||
|
|
||||||
|
def _show_header_data(data: bytes, *, format: str) -> None:
|
||||||
|
if format == "dump":
|
||||||
|
_hexdump(data)
|
||||||
|
elif format == "hex":
|
||||||
|
_raw_hexdump(data)
|
||||||
|
elif format == "raw":
|
||||||
|
sys.stdout.buffer.write(data)
|
||||||
|
elif format == "derez":
|
||||||
|
print("Cannot output file header data in derez format", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unhandled output format: {format}")
|
||||||
|
|
||||||
|
def _show_filtered_resources(resources: typing.Sequence[api.Resource], format: str, decompress: bool) -> None:
|
||||||
|
if not resources:
|
||||||
|
if format == "dump":
|
||||||
|
print("No resources matched the filter")
|
||||||
|
elif format in ("hex", "raw"):
|
||||||
|
print("No resources matched the filter", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
elif format == "derez":
|
||||||
|
print("/* No resources matched the filter */")
|
||||||
|
else:
|
||||||
|
raise AssertionError(f"Unhandled output format: {format}")
|
||||||
|
elif format in ("hex", "raw") and len(resources) != 1:
|
||||||
|
print(f"Format {format} can only output a single resource, but the filter matched {len(resources)} resources", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
for res in resources:
|
||||||
|
if decompress:
|
||||||
|
data = res.data
|
||||||
|
else:
|
||||||
|
data = res.data_raw
|
||||||
|
|
||||||
|
if format == "dump":
|
||||||
|
# Human-readable info and hex dump
|
||||||
|
desc = _describe_resource(res, include_type=True, decompress=decompress)
|
||||||
|
print(f"Resource {desc}:")
|
||||||
|
_hexdump(data)
|
||||||
|
print()
|
||||||
|
elif format == "hex":
|
||||||
|
# Data only as hex
|
||||||
|
|
||||||
|
_raw_hexdump(data)
|
||||||
|
elif format == "raw":
|
||||||
|
# Data only as raw bytes
|
||||||
|
|
||||||
|
sys.stdout.buffer.write(data)
|
||||||
|
elif format == "derez":
|
||||||
|
# Like DeRez with no resource definitions
|
||||||
|
|
||||||
|
attrs = list(_decompose_flags(res.attributes))
|
||||||
|
|
||||||
|
if decompress and api.ResourceAttrs.resCompressed in attrs:
|
||||||
|
attrs.remove(api.ResourceAttrs.resCompressed)
|
||||||
|
attrs_comment = " /* was compressed */"
|
||||||
|
else:
|
||||||
|
attrs_comment = ""
|
||||||
|
|
||||||
|
attr_descs = [_REZ_ATTR_NAMES[attr] for attr in attrs]
|
||||||
|
if None in attr_descs:
|
||||||
|
attr_descs[:] = [f"${res.attributes.value:02X}"]
|
||||||
|
|
||||||
|
parts = [str(res.resource_id)]
|
||||||
|
|
||||||
|
if res.name is not None:
|
||||||
|
name = _bytes_escape(res.name, quote='"')
|
||||||
|
parts.append(f'"{name}"')
|
||||||
|
|
||||||
|
parts += attr_descs
|
||||||
|
|
||||||
|
restype = _bytes_escape(res.resource_type, quote="'")
|
||||||
|
print(f"data '{restype}' ({', '.join(parts)}{attrs_comment}) {{")
|
||||||
|
|
||||||
|
for i in range(0, len(data), 16):
|
||||||
|
# Two-byte grouping is really annoying to implement.
|
||||||
|
groups = []
|
||||||
|
for j in range(0, 16, 2):
|
||||||
|
if i+j >= len(data):
|
||||||
|
break
|
||||||
|
elif i+j+1 >= len(data):
|
||||||
|
groups.append(f"{data[i+j]:02X}")
|
||||||
|
else:
|
||||||
|
groups.append(f"{data[i+j]:02X}{data[i+j+1]:02X}")
|
||||||
|
|
||||||
|
s = f'$"{" ".join(groups)}"'
|
||||||
|
comment = "/* " + data[i:i + 16].decode(_TEXT_ENCODING).translate(_TRANSLATE_NONPRINTABLES) + " */"
|
||||||
|
print(f"\t{s:<54s}{comment}")
|
||||||
|
|
||||||
|
print("};")
|
||||||
|
print()
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unhandled output format: {format}")
|
||||||
|
|
||||||
|
def _list_resource_file(rf: api.ResourceFile, *, decompress: bool) -> None:
|
||||||
|
if rf.header_system_data != bytes(len(rf.header_system_data)):
|
||||||
|
print("Header system data:")
|
||||||
|
_hexdump(rf.header_system_data)
|
||||||
|
|
||||||
|
if rf.header_application_data != bytes(len(rf.header_application_data)):
|
||||||
|
print("Header application data:")
|
||||||
|
_hexdump(rf.header_application_data)
|
||||||
|
|
||||||
|
attrs = _decompose_flags(rf.file_attributes)
|
||||||
|
if attrs:
|
||||||
|
print("File attributes: " + " | ".join(attr.name for attr in attrs))
|
||||||
|
|
||||||
|
if len(rf) > 0:
|
||||||
|
print(f"{len(rf)} resource types:")
|
||||||
|
for typecode, resources in rf.items():
|
||||||
|
restype = _bytes_escape(typecode, quote="'")
|
||||||
|
print(f"'{restype}': {len(resources)} resources:")
|
||||||
|
for resid, res in rf[typecode].items():
|
||||||
|
print(_describe_resource(res, include_type=False, decompress=decompress))
|
||||||
|
print()
|
||||||
|
else:
|
||||||
|
print("No resource types (empty resource file)")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ns = _parse_args()
|
||||||
|
|
||||||
if ns.file == "-":
|
if ns.file == "-":
|
||||||
if ns.fork is not None:
|
if ns.fork is not None:
|
||||||
@ -266,17 +388,7 @@ def main():
|
|||||||
else:
|
else:
|
||||||
data = rf.header_application_data
|
data = rf.header_application_data
|
||||||
|
|
||||||
if ns.format == "dump":
|
_show_header_data(data, format=ns.format)
|
||||||
_hexdump(data)
|
|
||||||
elif ns.format == "hex":
|
|
||||||
_raw_hexdump(data)
|
|
||||||
elif ns.format == "raw":
|
|
||||||
sys.stdout.buffer.write(data)
|
|
||||||
elif ns.format == "derez":
|
|
||||||
print("Cannot output file header data in derez format", file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Unhandled output format: {ns.format}")
|
|
||||||
elif ns.filter or ns.all:
|
elif ns.filter or ns.all:
|
||||||
if ns.filter:
|
if ns.filter:
|
||||||
resources = _filter_resources(rf, ns.filter)
|
resources = _filter_resources(rf, ns.filter)
|
||||||
@ -285,108 +397,9 @@ def main():
|
|||||||
for reses in rf.values():
|
for reses in rf.values():
|
||||||
resources.extend(reses.values())
|
resources.extend(reses.values())
|
||||||
|
|
||||||
if not resources:
|
_show_filtered_resources(resources, format=ns.format, decompress=ns.decompress)
|
||||||
if ns.format == "dump":
|
|
||||||
print("No resources matched the filter")
|
|
||||||
elif ns.format in ("hex", "raw"):
|
|
||||||
print("No resources matched the filter", file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
elif ns.format == "derez":
|
|
||||||
print("/* No resources matched the filter */")
|
|
||||||
else:
|
|
||||||
raise AssertionError(f"Unhandled output format: {ns.format}")
|
|
||||||
elif ns.format in ("hex", "raw") and len(resources) != 1:
|
|
||||||
print(f"Format {ns.format} can only output a single resource, but the filter matched {len(resources)} resources", file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
for res in resources:
|
|
||||||
if ns.decompress:
|
|
||||||
data = res.data
|
|
||||||
else:
|
|
||||||
data = res.data_raw
|
|
||||||
|
|
||||||
if ns.format == "dump":
|
|
||||||
# Human-readable info and hex dump
|
|
||||||
desc = _describe_resource(res, include_type=True, decompress=ns.decompress)
|
|
||||||
print(f"Resource {desc}:")
|
|
||||||
_hexdump(data)
|
|
||||||
print()
|
|
||||||
elif ns.format == "hex":
|
|
||||||
# Data only as hex
|
|
||||||
|
|
||||||
_raw_hexdump(data)
|
|
||||||
elif ns.format == "raw":
|
|
||||||
# Data only as raw bytes
|
|
||||||
|
|
||||||
sys.stdout.buffer.write(data)
|
|
||||||
elif ns.format == "derez":
|
|
||||||
# Like DeRez with no resource definitions
|
|
||||||
|
|
||||||
attrs = list(_decompose_flags(res.attributes))
|
|
||||||
|
|
||||||
if ns.decompress and api.ResourceAttrs.resCompressed in attrs:
|
|
||||||
attrs.remove(api.ResourceAttrs.resCompressed)
|
|
||||||
attrs_comment = " /* was compressed */"
|
|
||||||
else:
|
|
||||||
attrs_comment = ""
|
|
||||||
|
|
||||||
attr_descs = [_REZ_ATTR_NAMES[attr] for attr in attrs]
|
|
||||||
if None in attr_descs:
|
|
||||||
attr_descs[:] = [f"${res.attributes.value:02X}"]
|
|
||||||
|
|
||||||
parts = [str(res.resource_id)]
|
|
||||||
|
|
||||||
if res.name is not None:
|
|
||||||
name = _bytes_escape(res.name, quote='"')
|
|
||||||
parts.append(f'"{name}"')
|
|
||||||
|
|
||||||
parts += attr_descs
|
|
||||||
|
|
||||||
restype = _bytes_escape(res.resource_type, quote="'")
|
|
||||||
print(f"data '{restype}' ({', '.join(parts)}{attrs_comment}) {{")
|
|
||||||
|
|
||||||
for i in range(0, len(data), 16):
|
|
||||||
# Two-byte grouping is really annoying to implement.
|
|
||||||
groups = []
|
|
||||||
for j in range(0, 16, 2):
|
|
||||||
if i+j >= len(data):
|
|
||||||
break
|
|
||||||
elif i+j+1 >= len(data):
|
|
||||||
groups.append(f"{data[i+j]:02X}")
|
|
||||||
else:
|
|
||||||
groups.append(f"{data[i+j]:02X}{data[i+j+1]:02X}")
|
|
||||||
|
|
||||||
s = f'$"{" ".join(groups)}"'
|
|
||||||
comment = "/* " + data[i:i + 16].decode(_TEXT_ENCODING).translate(_TRANSLATE_NONPRINTABLES) + " */"
|
|
||||||
print(f"\t{s:<54s}{comment}")
|
|
||||||
|
|
||||||
print("};")
|
|
||||||
print()
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Unhandled output format: {ns.format}")
|
|
||||||
else:
|
else:
|
||||||
if rf.header_system_data != bytes(len(rf.header_system_data)):
|
_list_resource_file(rf, decompress=ns.decompress)
|
||||||
print("Header system data:")
|
|
||||||
_hexdump(rf.header_system_data)
|
|
||||||
|
|
||||||
if rf.header_application_data != bytes(len(rf.header_application_data)):
|
|
||||||
print("Header application data:")
|
|
||||||
_hexdump(rf.header_application_data)
|
|
||||||
|
|
||||||
attrs = _decompose_flags(rf.file_attributes)
|
|
||||||
if attrs:
|
|
||||||
print("File attributes: " + " | ".join(attr.name for attr in attrs))
|
|
||||||
|
|
||||||
if len(rf) > 0:
|
|
||||||
print(f"{len(rf)} resource types:")
|
|
||||||
for typecode, resources in rf.items():
|
|
||||||
restype = _bytes_escape(typecode, quote="'")
|
|
||||||
print(f"'{restype}': {len(resources)} resources:")
|
|
||||||
for resid, res in rf[typecode].items():
|
|
||||||
print(_describe_resource(res, include_type=False, decompress=ns.decompress))
|
|
||||||
print()
|
|
||||||
else:
|
|
||||||
print("No resource types (empty resource file)")
|
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user