Skip to content

Commit

Permalink
Drop bolt.{un,}pack_string
Browse files Browse the repository at this point in the history
The struct thing we were doing in there was wholly pointless - ins.read
already returns a perfectly good bytestring, struct-packing it right
back into a bytestring is just thrown away performance. And after
removing that, this is now literally just a fancy lambda, so move it to
its only usage in save_headers and refactor for some perf gains too.
Py3ified lines I touched and ones in the immediate vicinity.
  • Loading branch information
Infernio committed Aug 22, 2022
1 parent 83197ba commit 57ce267
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 56 deletions.
5 changes: 0 additions & 5 deletions Mopy/bash/bolt.py
Original file line number Diff line number Diff line change
Expand Up @@ -1850,11 +1850,6 @@ def pack_bzstr8(out, val: bytes, __pack=structs_cache[u'=B'].pack):
pack_byte(out, len(val) + 1)
out.write(val)
out.write(b'\x00')
def unpack_string(ins, string_len) -> bytes:
return struct_unpack(f'{string_len}s', ins.read(string_len))[0]
def pack_string(out, val: bytes):
out.write(val)

def pack_byte_signed(out, value: int, __pack=structs_cache[u'b'].pack):
out.write(__pack(value))

Expand Down
12 changes: 6 additions & 6 deletions Mopy/bash/bosh/bsa_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@
import lz4.frame

from .dds_files import DDSFile, mk_dxgi_fmt
from ..bolt import deprint, Progress, struct_unpack, unpack_byte, \
unpack_string, unpack_int, Flags, AFile, structs_cache, struct_calcsize, \
struct_error
from ..bolt import deprint, Progress, struct_unpack, unpack_byte, unpack_int, \
Flags, AFile, structs_cache, struct_calcsize, struct_error
from ..env import convert_separators
from ..exception import AbstractError, BSAError, BSADecodingError, \
BSAFlagError, BSACompressionError, BSADecompressionError, \
Expand Down Expand Up @@ -689,6 +688,7 @@ def _read_bsa_file(self, folder_records, read_file_records) -> list[bytes]:
my_bsa_name = self.bsa_name
with open(self.abs_path, u'rb') as bsa_file:
bsa_seek = bsa_file.seek
bsa_read = bsa_file.read
# load the header from input stream
self.bsa_header.load_header(bsa_file, my_bsa_name)
# load the folder records from input stream
Expand All @@ -710,8 +710,8 @@ def _read_bsa_file(self, folder_records, read_file_records) -> list[bytes]:
# Size is summed as strlen() + 1, so use +1 for root
total_names_length += 1
else:
folder_path = _decode_path(
unpack_string(bsa_file, name_size - 1), my_bsa_name)
folder_path = _decode_path(bsa_read(name_size - 1),
my_bsa_name)
bsa_seek(1, 1) # discard null terminator
total_names_length += name_size
read_file_records(bsa_file, folder_path, folder_record)
Expand All @@ -721,7 +721,7 @@ def _read_bsa_file(self, folder_records, read_file_records) -> list[bytes]:
self.abs_path, self.bsa_header.total_folder_name_length,
total_names_length, self.bsa_header.folder_count))
self.total_names_length = total_names_length
file_names = bsa_file.read( # has an empty string at the end
file_names = bsa_read( # has an empty string at the end
self.bsa_header.total_file_name_length).split(b'\00')
# close the file
return file_names
Expand Down
13 changes: 6 additions & 7 deletions Mopy/bash/bosh/cosaves.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@
from typing import Type, get_type_hints
from zlib import crc32

from ..bolt import decoder, encode, struct_unpack, unpack_string, \
unpack_int, unpack_short, unpack_4s, unpack_byte, unpack_str16, \
unpack_float, unpack_double, unpack_int_signed, unpack_str32, AFile, \
unpack_spaced_string, pack_int, pack_short, pack_double, pack_byte, \
pack_int_signed, pack_float, pack_4s, struct_error, GPath, struct_pack, \
deprint, Path
from ..bolt import decoder, encode, struct_unpack, unpack_int, unpack_short, \
unpack_4s, unpack_byte, unpack_str16, unpack_float, unpack_double, \
unpack_int_signed, unpack_str32, AFile, unpack_spaced_string, pack_int, \
pack_short, pack_double, pack_byte, pack_int_signed, pack_float, pack_4s, \
struct_error, GPath, struct_pack, deprint, Path
from ..exception import AbstractError, BoltError, CosaveError, \
InvalidCosaveError, UnsupportedCosaveError

Expand Down Expand Up @@ -132,7 +131,7 @@ def __init__(self, ins, cosave_name):
:param ins: The input stream to read from.
:param cosave_name: The filename of the cosave for error messages."""
actual_tag = _cosave_decode(unpack_string(ins, len(self.savefile_tag)))
actual_tag = _cosave_decode(ins.read(len(self.savefile_tag)))
if actual_tag != self.savefile_tag:
raise InvalidCosaveError(cosave_name,
f'Header tag wrong: got {actual_tag}, '
Expand Down
80 changes: 42 additions & 38 deletions Mopy/bash/bosh/save_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,22 @@
import lz4.block

from .. import bolt
from ..bolt import decoder, cstrip, unpack_string, unpack_int, unpack_str8, \
unpack_short, unpack_float, unpack_str16, unpack_byte, \
unpack_str_int_delim, unpack_str16_delim, unpack_str_byte_delim, \
unpack_many, encode, struct_unpack, pack_int, pack_byte, pack_short, \
pack_float, pack_string, pack_str8, pack_bzstr8, structs_cache, \
struct_error, remove_newlines, deprint, FName
from ..bolt import decoder, cstrip, unpack_int, unpack_str8, unpack_short, \
unpack_float, unpack_str16, unpack_byte, unpack_str_int_delim, \
unpack_str16_delim, unpack_str_byte_delim, unpack_many, encode, \
struct_unpack, pack_int, pack_byte, pack_short, pack_float, pack_str8, \
pack_bzstr8, structs_cache, struct_error, remove_newlines, deprint, FName
from ..exception import SaveHeaderError, AbstractError

# Utilities -------------------------------------------------------------------
def _pack_c(out, value, __pack=structs_cache[u'=c'].pack):
def _unpack_fstr8(ins) -> bytes:
return ins.read(8)
def _unpack_fstr16(ins) -> bytes:
return ins.read(16)
def _pack_c(out, value, __pack=structs_cache['=c'].pack):
out.write(__pack(value))
unpack_fstr16 = partial(unpack_string, string_len=16)
def _pack_string(out, val: bytes):
out.write(val)

class SaveFileHeader(object):
save_magic = b'OVERRIDE'
Expand Down Expand Up @@ -84,7 +88,7 @@ def read_save_header(self, load_image=False, ins=None):
raise SaveHeaderError(err_msg) from e

def load_header(self, ins, load_image=False):
save_magic = unpack_string(ins, len(self.__class__.save_magic))
save_magic = ins.read(len(self.__class__.save_magic))
if save_magic != self.__class__.save_magic:
raise SaveHeaderError(f'Magic wrong: {save_magic!r} (expected '
f'{self.__class__.save_magic!r})')
Expand Down Expand Up @@ -201,21 +205,21 @@ class OblivionSaveHeader(SaveFileHeader):
##: exe_time and gameTime are SYSTEMTIME structs, as described here:
# https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime
unpackers = OrderedDict([
(u'major_version', (pack_byte, unpack_byte)),
(u'minor_version', (pack_byte, unpack_byte)),
(u'exe_time', (pack_string, unpack_fstr16)),
(u'header_version', (pack_int, unpack_int)),
(u'header_size', (pack_int, unpack_int)),
(u'saveNum', (pack_int, unpack_int)),
(u'pcName', (_pack_str8_1, unpack_str8)),
(u'pcLevel', (pack_short, unpack_short)),
(u'pcLocation', (_pack_str8_1, unpack_str8)),
(u'gameDays', (pack_float, unpack_float)),
(u'gameTicks', (pack_int, unpack_int)),
(u'gameTime', (pack_string, unpack_fstr16)),
(u'ssSize', (pack_int, unpack_int)),
(u'ssWidth', (pack_int, unpack_int)),
(u'ssHeight', (pack_int, unpack_int)),
('major_version', (pack_byte, unpack_byte)),
('minor_version', (pack_byte, unpack_byte)),
('exe_time', (_pack_string, _unpack_fstr16)),
('header_version', (pack_int, unpack_int)),
('header_size', (pack_int, unpack_int)),
('saveNum', (pack_int, unpack_int)),
('pcName', (_pack_str8_1, unpack_str8)),
('pcLevel', (pack_short, unpack_short)),
('pcLocation', (_pack_str8_1, unpack_str8)),
('gameDays', (pack_float, unpack_float)),
('gameTicks', (pack_int, unpack_int)),
('gameTime', (_pack_string, _unpack_fstr16)),
('ssSize', (pack_int, unpack_int)),
('ssWidth', (pack_int, unpack_int)),
('ssHeight', (pack_int, unpack_int)),
])

def _write_masters(self, ins, out):
Expand Down Expand Up @@ -269,20 +273,20 @@ class SkyrimSaveHeader(SaveFileHeader):
'masters_regular', 'masters_esl')

unpackers = OrderedDict([
(u'header_size', (00, unpack_int)),
(u'version', (00, unpack_int)),
(u'saveNumber', (00, unpack_int)),
(u'pcName', (00, unpack_str16)),
(u'pcLevel', (00, unpack_int)),
(u'pcLocation', (00, unpack_str16)),
(u'gameDate', (00, unpack_str16)),
(u'raceEid', (00, unpack_str16)), # pcRace
(u'pcSex', (00, unpack_short)),
(u'pcExp', (00, unpack_float)),
(u'pcLvlExp', (00, unpack_float)),
(u'filetime', (00, lambda ins: unpack_string(ins, 8))),
(u'ssWidth', (00, unpack_int)),
(u'ssHeight', (00, unpack_int)),
('header_size', (00, unpack_int)),
('version', (00, unpack_int)),
('saveNumber', (00, unpack_int)),
('pcName', (00, unpack_str16)),
('pcLevel', (00, unpack_int)),
('pcLocation', (00, unpack_str16)),
('gameDate', (00, unpack_str16)),
('raceEid', (00, unpack_str16)), # pcRace
('pcSex', (00, unpack_short)),
('pcExp', (00, unpack_float)),
('pcLvlExp', (00, unpack_float)),
('filetime', (00, _unpack_fstr8)),
('ssWidth', (00, unpack_int)),
('ssHeight', (00, unpack_int)),
])

def __is_sse(self): return self.version == 12
Expand Down

0 comments on commit 57ce267

Please sign in to comment.