From d0e1eaf262011e52fad705a4f28d5f67ade10a3f Mon Sep 17 00:00:00 2001 From: dgelessus Date: Thu, 26 Dec 2019 00:34:27 +0100 Subject: [PATCH] Add raw-compress-info subcommand (#6) --- README.rst | 1 + rsrcfork/__main__.py | 42 +++++++++++++++++++++++++++++++++++ rsrcfork/compress/__init__.py | 4 +++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 2c2c555..720071a 100644 --- a/README.rst +++ b/README.rst @@ -118,6 +118,7 @@ Version 1.7.1 (next version) * Removed the old (non-subcommand-based) CLI syntax. * Added filtering support to the ``list`` subcommand. +* Added a ``raw-compress-info`` subcommand to display technical header information about standalone compressed resource data. Version 1.7.0 ^^^^^^^^^^^^^ diff --git a/rsrcfork/__main__.py b/rsrcfork/__main__.py index cd40b92..a14ec9f 100644 --- a/rsrcfork/__main__.py +++ b/rsrcfork/__main__.py @@ -577,6 +577,47 @@ Read the data of one or more resources. show_filtered_resources(resources, format=ns.format, decompress=ns.decompress) +def do_raw_compress_info(prog: str, args: typing.List[str]) -> typing.NoReturn: + """Display technical information about raw compressed resource data.""" + + ap = make_argument_parser( + prog=prog, + description=""" +Display technical information about raw compressed resource data that is stored +in a standalone file and not as a resource in a resource file. +""", + ) + + ap.add_argument("input_file", help="The file from which to read the compressed resource data, or - for stdin.") + + ns = ap.parse_args(args) + + if ns.input_file == "-": + in_stream = sys.stdin.buffer + close_in_stream = False + else: + in_stream = open(ns.input_file, "rb") + close_in_stream = True + + try: + header_info = compress.CompressedHeaderInfo.parse_stream(in_stream) + + print(f"Header length: {header_info.header_length} bytes") + print(f"Compression type: 0x{header_info.compression_type:>04x}") + print(f"Decompressed data length: {header_info.decompressed_length} bytes") + print(f"'dcmp' resource ID: {header_info.dcmp_id}") + + if isinstance(header_info, compress.CompressedType8HeaderInfo): + print(f"Working buffer fractional size: {header_info.working_buffer_fractional_size} 256ths of compressed data length") + print(f"Expansion buffer size: {header_info.expansion_buffer_size} bytes") + elif isinstance(header_info, compress.CompressedType9HeaderInfo): + print(f"Decompressor-specific parameters: {header_info.parameters}") + else: + raise AssertionError(f"Unhandled compressed header info type: {type(header_info)}") + finally: + if close_in_stream: + in_stream.close() + def do_raw_decompress(prog: str, args: typing.List[str]) -> typing.NoReturn: """Decompress raw compressed resource data.""" @@ -643,6 +684,7 @@ SUBCOMMANDS = { "info": do_info, "list": do_list, "read": do_read, + "raw-compress-info": do_raw_compress_info, "raw-decompress": do_raw_decompress, } diff --git a/rsrcfork/compress/__init__.py b/rsrcfork/compress/__init__.py index 0a96f32..a178e8e 100644 --- a/rsrcfork/compress/__init__.py +++ b/rsrcfork/compress/__init__.py @@ -5,10 +5,12 @@ from . import dcmp0 from . import dcmp1 from . import dcmp2 -from .common import DecompressError, CompressedHeaderInfo +from .common import DecompressError, CompressedHeaderInfo, CompressedType8HeaderInfo, CompressedType9HeaderInfo __all__ = [ "CompressedHeaderInfo", + "CompressedType8HeaderInfo", + "CompressedType9HeaderInfo", "DecompressError", "decompress", "decompress_parsed",