Simplify the syntax denoting compression

This commit is contained in:
Elliot Nunn 2019-01-10 13:05:28 +08:00
parent e9f9154dff
commit 7b9d12cc74

View File

@ -1,12 +1,16 @@
import collections
import struct
import enum
import re
from ResDecompress import DecompressResource, CompressResource, GetEncoding
FAKE_HEADER_RSRC_TYPE = b'header' # obviously invalid
RE_COMPRESS = re.compile(rb'(?i)^/[*/].*?compress(?:ion)?\s*[:=]?\s*([-_a-zA-Z0-9]+)')
MAP = bytearray(range(256))
for i in range(32): MAP[i] = ord('.')
MAP[127] = ord('.')
@ -174,19 +178,24 @@ class Resource:
def _rez_repr(self, expand=False): # the Rez file will be annotated for re-compression
if self.compression_format:
if expand:
attribs = ResourceAttrs(self.attribs & ~1)
if self.compression_format == 'UnknownCompression':
attribs = ResourceAttrs(self.attribs | 1) # so Rez will produce a valid file
compression_format = None
else:
attribs = ResourceAttrs(self.attribs & ~1) # hide the compression from Rez
compression_format = self.compression_format # but expose it via a comment
try:
data = self.data # prefer clean data from user
except ResExpandError:
data = self._cache # sad fallback on original compressed data
compression_format = self.compression_format
else:
attribs = ResourceAttrs(self.attribs | 1)
self._update_cache() # ensures that self._cache is valid
data = self._cache
compression_format = None
else:
attribs = ResourceAttrs(self.attribs & ~1)
data = self.data
@ -266,9 +275,13 @@ def parse_rez_code(from_rezcode):
from_rezcode = from_rezcode.replace(b'\r\n', b'\n').replace(b'\r', b'\n')
line_iter = iter(from_rezcode.split(b'\n'))
compression_format = None
for line in line_iter:
line = line.lstrip()
if line.startswith(b'data '):
m = RE_COMPRESS.match(line)
if m:
compression_format = m.group(1).decode('mac_roman')
elif line.startswith(b'data '):
_, _, line = line.partition(b' ')
rsrctype, line = _rez_unescape(line)
_, _, line = line.partition(b'(')
@ -287,10 +300,6 @@ def parse_rez_code(from_rezcode):
line = line[1:]
args.append(('nonstring', arg))
compression_format = None
a, b, c = line.partition(b'Compress:')
if b: compression_format = c.split()[0].decode('ascii')
rsrcname = None
rsrcattrs = ResourceAttrs(0)
@ -322,6 +331,8 @@ def parse_rez_code(from_rezcode):
if compression_format: cur_resource.compression_format = compression_format
yield cur_resource
compression_format = None
def make_file(from_iter, align=1):
"""Pack an iterator of Resource objects into a binary resource file."""
@ -438,10 +449,9 @@ def make_rez_code(from_iter, ascii_clean=False, expand=False):
if resource.type == FAKE_HEADER_RSRC_TYPE:
lines.append(b'#if 0')
lines.append(b'data %s (%s) {' % (fourcc, args))
if compression_format:
cmt = ('Compress: ' + compression_format).replace('Compress: UnknownCompression', 'Unknown compression format')
lines[-1] += b' /* %s */' % cmt.encode('mac_roman')
lines.append(b'// compress %s' % compression_format.encode('mac_roman'))
lines.append(b'data %s (%s) {' % (fourcc, args))
step = 16