From f3b3de496ed607282413fba0ba9bf80a77c695c9 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Mon, 7 Oct 2019 10:08:32 +0200 Subject: [PATCH] Change naming of compression types The old names ("system" and "application" compression) were not really accurate in all cases, so the compression types are now referred to by their number. --- rsrcfork/compress/common.py | 34 +++++++++++++++++----------------- rsrcfork/compress/dcmp0.py | 2 +- rsrcfork/compress/dcmp1.py | 2 +- rsrcfork/compress/dcmp2.py | 10 +++++----- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/rsrcfork/compress/common.py b/rsrcfork/compress/common.py index ae66794..a5f6a28 100644 --- a/rsrcfork/compress/common.py +++ b/rsrcfork/compress/common.py @@ -9,30 +9,30 @@ class DecompressError(Exception): # The signature of all compressed resource data, 0xa89f6572 in hex, or "®üer" in MacRoman. COMPRESSED_SIGNATURE = b"\xa8\x9fer" -# The compression type commonly used for application resources. -COMPRESSED_TYPE_APPLICATION = 0x0801 -# The compression type commonly used for System file resources. -COMPRESSED_TYPE_SYSTEM = 0x0901 +# The number of the "type 8" compression type. This type is used in the Finder, ResEdit, and some other system files. +COMPRESSED_TYPE_8 = 0x0801 +# The number of the "type 9" compression type. This type is used in the System file and System 7.5's Installer. +COMPRESSED_TYPE_9 = 0x0901 # Common header for compressed resources of all types. # 4 bytes: Signature (see above). # 2 bytes: Length of the complete header (this common part and the type-specific part that follows it). (This meaning is just a guess - the field's value is always 0x0012, so there's no way to know for certain what it means.) -# 2 bytes: Compression type. Known so far: 0x0901 is used in the System file's resources. 0x0801 is used in other files' resources. +# 2 bytes: Compression type. Known so far: 0x0801 ("type 8") and 0x0901 ("type 9"). # 4 bytes: Length of the data after decompression. # 6 bytes: Remainder of the header. The exact format varies depending on the compression type. STRUCT_COMPRESSED_HEADER = struct.Struct(">4sHHI6s") -# Remainder of header for an "application" compressed resource. +# Remainder of header for a "type 8" compressed resource. # 1 byte: "Working buffer fractional size" - the ratio of the compressed data size to the uncompressed data size, times 256. # 1 byte: "Expansion buffer size" - the maximum number of bytes that the data might grow during decompression. # 2 bytes: The ID of the 'dcmp' resource that can decompress this resource. Currently only ID 0 is supported. # 2 bytes: Reserved (always zero). -STRUCT_COMPRESSED_APPLICATION_HEADER = struct.Struct(">BBhH") +STRUCT_COMPRESSED_TYPE_8_HEADER = struct.Struct(">BBhH") -# Remainder of header for a "system" compressed resource. +# Remainder of header for a "type 9" compressed resource. # 2 bytes: The ID of the 'dcmp' resource that can decompress this resource. Currently only ID 2 is supported. # 4 bytes: Decompressor-specific parameters. -STRUCT_COMPRESSED_SYSTEM_HEADER = struct.Struct(">h4s") +STRUCT_COMPRESSED_TYPE_9_HEADER = struct.Struct(">h4s") class CompressedHeaderInfo(object): @@ -47,17 +47,17 @@ class CompressedHeaderInfo(object): if header_length != 0x12: raise DecompressError(f"Unsupported header length: 0x{header_length:>04x}, expected 0x12") - if compression_type == COMPRESSED_TYPE_APPLICATION: - working_buffer_fractional_size, expansion_buffer_size, dcmp_id, reserved = STRUCT_COMPRESSED_APPLICATION_HEADER.unpack(remainder) + if compression_type == COMPRESSED_TYPE_8: + working_buffer_fractional_size, expansion_buffer_size, dcmp_id, reserved = STRUCT_COMPRESSED_TYPE_8_HEADER.unpack(remainder) if reserved != 0: raise DecompressError(f"Reserved field should be 0, not 0x{reserved:>04x}") - return CompressedApplicationHeaderInfo(header_length, compression_type, decompressed_length, dcmp_id, working_buffer_fractional_size, expansion_buffer_size) - elif compression_type == COMPRESSED_TYPE_SYSTEM: - dcmp_id, parameters = STRUCT_COMPRESSED_SYSTEM_HEADER.unpack(remainder) + return CompressedType8HeaderInfo(header_length, compression_type, decompressed_length, dcmp_id, working_buffer_fractional_size, expansion_buffer_size) + elif compression_type == COMPRESSED_TYPE_9: + dcmp_id, parameters = STRUCT_COMPRESSED_TYPE_9_HEADER.unpack(remainder) - return CompressedSystemHeaderInfo(header_length, compression_type, decompressed_length, dcmp_id, parameters) + return CompressedType9HeaderInfo(header_length, compression_type, decompressed_length, dcmp_id, parameters) else: raise DecompressError(f"Unsupported compression type: 0x{compression_type:>04x}") @@ -79,7 +79,7 @@ class CompressedHeaderInfo(object): self.dcmp_id = dcmp_id -class CompressedApplicationHeaderInfo(CompressedHeaderInfo): +class CompressedType8HeaderInfo(CompressedHeaderInfo): working_buffer_fractional_size: int expansion_buffer_size: int @@ -93,7 +93,7 @@ class CompressedApplicationHeaderInfo(CompressedHeaderInfo): return f"{type(self).__qualname__}(header_length={self.header_length}, compression_type=0x{self.compression_type:>04x}, decompressed_length={self.decompressed_length}, dcmp_id={self.dcmp_id}, working_buffer_fractional_size={self.working_buffer_fractional_size}, expansion_buffer_size={self.expansion_buffer_size})" -class CompressedSystemHeaderInfo(CompressedHeaderInfo): +class CompressedType9HeaderInfo(CompressedHeaderInfo): parameters: bytes def __init__(self, header_length: int, compression_type: int, decompressed_length: int, dcmp_id: int, parameters: bytes) -> None: diff --git a/rsrcfork/compress/dcmp0.py b/rsrcfork/compress/dcmp0.py index 4a3bda7..1e58b4f 100644 --- a/rsrcfork/compress/dcmp0.py +++ b/rsrcfork/compress/dcmp0.py @@ -42,7 +42,7 @@ assert len(TABLE) == len(range(0x4b, 0xfe)) def decompress_stream_inner(header_info: common.CompressedHeaderInfo, stream: typing.BinaryIO, *, debug: bool=False) -> typing.Iterator[bytes]: """Internal helper function, implements the main decompression algorithm. Only called from decompress_stream, which performs some extra checks and debug logging.""" - if not isinstance(header_info, common.CompressedApplicationHeaderInfo): + if not isinstance(header_info, common.CompressedType8HeaderInfo): raise common.DecompressError(f"Incorrect header type: {type(header_info).__qualname__}") prev_literals: typing.List[bytes] = [] diff --git a/rsrcfork/compress/dcmp1.py b/rsrcfork/compress/dcmp1.py index 2b2128e..1fea263 100644 --- a/rsrcfork/compress/dcmp1.py +++ b/rsrcfork/compress/dcmp1.py @@ -25,7 +25,7 @@ assert len(TABLE) == len(range(0xd5, 0xfe)) def decompress_stream_inner(header_info: common.CompressedHeaderInfo, stream: typing.BinaryIO, *, debug: bool=False) -> typing.Iterator[bytes]: """Internal helper function, implements the main decompression algorithm. Only called from decompress_stream, which performs some extra checks and debug logging.""" - if not isinstance(header_info, common.CompressedApplicationHeaderInfo): + if not isinstance(header_info, common.CompressedType8HeaderInfo): raise common.DecompressError(f"Incorrect header type: {type(header_info).__qualname__}") prev_literals: typing.List[bytes] = [] diff --git a/rsrcfork/compress/dcmp2.py b/rsrcfork/compress/dcmp2.py index cd60b7a..e82916d 100644 --- a/rsrcfork/compress/dcmp2.py +++ b/rsrcfork/compress/dcmp2.py @@ -74,7 +74,7 @@ def _split_bits(i: int) -> typing.Tuple[bool, bool, bool, bool, bool, bool, bool ) -def _decompress_system_untagged(stream: "common.PeekableIO", decompressed_length: int, table: typing.Sequence[bytes], *, debug: bool=False) -> typing.Iterator[bytes]: +def _decompress_untagged(stream: "common.PeekableIO", decompressed_length: int, table: typing.Sequence[bytes], *, debug: bool=False) -> typing.Iterator[bytes]: while True: # Loop is terminated when EOF is reached. table_index_data = stream.read(1) if not table_index_data: @@ -93,7 +93,7 @@ def _decompress_system_untagged(stream: "common.PeekableIO", decompressed_length print(f"Reference: {table_index} -> {table[table_index]}") yield table[table_index] -def _decompress_system_tagged(stream: "common.PeekableIO", decompressed_length: int, table: typing.Sequence[bytes], *, debug: bool=False) -> typing.Iterator[bytes]: +def _decompress_tagged(stream: "common.PeekableIO", decompressed_length: int, table: typing.Sequence[bytes], *, debug: bool=False) -> typing.Iterator[bytes]: while True: # Loop is terminated when EOF is reached. tag_data = stream.read(1) if not tag_data: @@ -136,7 +136,7 @@ def _decompress_system_tagged(stream: "common.PeekableIO", decompressed_length: def decompress_stream(header_info: common.CompressedHeaderInfo, stream: typing.BinaryIO, *, debug: bool=False) -> typing.Iterator[bytes]: """Decompress compressed data in the format used by 'dcmp' (2).""" - if not isinstance(header_info, common.CompressedSystemHeaderInfo): + if not isinstance(header_info, common.CompressedType9HeaderInfo): raise common.DecompressError(f"Incorrect header type: {type(header_info).__qualname__}") unknown, table_count_m1, flags_raw = STRUCT_PARAMETERS.unpack(header_info.parameters) @@ -170,8 +170,8 @@ def decompress_stream(header_info: common.CompressedHeaderInfo, stream: typing.B print("Using default table") if ParameterFlags.TAGGED in flags: - decompress_func = _decompress_system_tagged + decompress_func = _decompress_tagged else: - decompress_func = _decompress_system_untagged + decompress_func = _decompress_untagged yield from decompress_func(common.make_peekable(stream), header_info.decompressed_length, table, debug=debug)