Add an additional optimization for the pathological case of editing the beginning and end of a file.
This commit is contained in:
parent
e02c307004
commit
23631564cf
|
@ -9,6 +9,7 @@ class FileBytes:
|
|||
def __init__(self, handle: BinaryIO) -> None:
|
||||
self.__handle: BinaryIO = handle
|
||||
self.__patches: Dict[int, int] = {}
|
||||
self.__regions: Set[int] = set()
|
||||
self.__copies: List["FileBytes"] = []
|
||||
self.__unsafe: bool = False
|
||||
self.__lowest_patch: Optional[int] = None
|
||||
|
@ -125,6 +126,7 @@ class FileBytes:
|
|||
myclone.__patches = {k: v for k, v in self.__patches.items()}
|
||||
myclone.__lowest_patch = self.__lowest_patch
|
||||
myclone.__highest_patch = self.__highest_patch
|
||||
myclone.__regions = self.__regions
|
||||
myclone.__filelength = self.__filelength
|
||||
myclone.__patchlength = self.__patchlength
|
||||
myclone.__origfilelength = self.__origfilelength
|
||||
|
@ -145,6 +147,7 @@ class FileBytes:
|
|||
self.__patches[loc] = change
|
||||
self.__lowest_patch = min(self.__lowest_patch, loc) if self.__lowest_patch is not None else loc
|
||||
self.__highest_patch = max(self.__highest_patch, loc + 1) if self.__highest_patch is not None else (loc + 1)
|
||||
self.__regions.clear()
|
||||
|
||||
self.__patchlength += len(data)
|
||||
|
||||
|
@ -164,9 +167,13 @@ class FileBytes:
|
|||
self.__filelength = size
|
||||
|
||||
# Get rid of any changes made in the truncation range.
|
||||
cleared: bool = False
|
||||
for off in range(size, self.__patchlength):
|
||||
if off in self.__patches:
|
||||
del self.__patches[off]
|
||||
cleared = True
|
||||
if cleared:
|
||||
self.__regions.clear()
|
||||
|
||||
# Set the length of this object to the size as well so resizing will
|
||||
# zero out the data.
|
||||
|
@ -237,6 +244,7 @@ class FileBytes:
|
|||
# Now that we've serialized out the data, clean up our own representation.
|
||||
self.__handle.flush()
|
||||
self.__patches.clear()
|
||||
self.__regions.clear()
|
||||
self.__lowest_patch = None
|
||||
self.__highest_patch = None
|
||||
self.__filelength = self.__patchlength
|
||||
|
@ -261,8 +269,9 @@ class FileBytes:
|
|||
inst.__patchlength = self.__patchlength
|
||||
inst.__origfilelength = self.__origfilelength
|
||||
inst.__patches.clear()
|
||||
self.__lowest_patch = None
|
||||
self.__highest_patch = None
|
||||
inst.__regions.clear()
|
||||
inst.__lowest_patch = None
|
||||
inst.__highest_patch = None
|
||||
|
||||
def __slice(self, key: slice) -> Tuple[int, int, int]:
|
||||
# Determine step of slice
|
||||
|
@ -344,7 +353,41 @@ class FileBytes:
|
|||
elif self.__highest_patch is None or (start > self.__highest_patch and stop > self.__highest_patch):
|
||||
modifications = False
|
||||
else:
|
||||
modifications = any(index in self.__patches for index in range(start, stop, step))
|
||||
# Whether we should do the slow check or not.
|
||||
check = False
|
||||
|
||||
if not self.__regions:
|
||||
# Recreate the index.
|
||||
last_index = -1
|
||||
for iterval in sorted(self.__patches.keys()):
|
||||
# Only attempt to update the region cache if we haven't already
|
||||
# seen something in this section.
|
||||
index = iterval // self.IO_SIZE
|
||||
if index != last_index:
|
||||
self.__regions.add(index)
|
||||
last_index = index
|
||||
|
||||
if start > stop:
|
||||
iterstart = stop + 1
|
||||
iterend = start + 1
|
||||
else:
|
||||
iterstart = start
|
||||
iterend = stop
|
||||
|
||||
iterstart //= self.IO_SIZE
|
||||
iterend //= self.IO_SIZE
|
||||
|
||||
if iterend == iterstart:
|
||||
iterend += 1
|
||||
|
||||
for index in range(iterstart, iterend):
|
||||
if index in self.__regions:
|
||||
check = True
|
||||
|
||||
if check:
|
||||
modifications = any(index in self.__patches for index in range(start, stop, step))
|
||||
else:
|
||||
modifications = False
|
||||
|
||||
# Now see if we can do any fast loading
|
||||
if start < stop and step == 1:
|
||||
|
@ -433,6 +476,7 @@ class FileBytes:
|
|||
self.__patches[key] = val
|
||||
self.__lowest_patch = min(self.__lowest_patch, key) if self.__lowest_patch is not None else key
|
||||
self.__highest_patch = max(self.__highest_patch, key + 1) if self.__highest_patch is not None else (key + 1)
|
||||
self.__regions.clear()
|
||||
|
||||
elif isinstance(key, slice):
|
||||
if not isinstance(val, bytes):
|
||||
|
@ -467,6 +511,7 @@ class FileBytes:
|
|||
self.__patches[off] = val[index]
|
||||
self.__lowest_patch = min(self.__lowest_patch, off) if self.__lowest_patch is not None else off
|
||||
self.__highest_patch = max(self.__highest_patch, off + 1) if self.__highest_patch is not None else (off + 1)
|
||||
self.__regions.clear()
|
||||
|
||||
else:
|
||||
raise NotImplementedError("Not implemented!")
|
||||
|
|
2
setup.py
2
setup.py
|
@ -8,7 +8,7 @@ with open(os.path.join("arcadeutils", "README.md"), "r", encoding="utf-8") as fh
|
|||
|
||||
setup(
|
||||
name='arcadeutils',
|
||||
version='0.1.7',
|
||||
version='0.1.8',
|
||||
description='Collection of utilities written in Python for working with various arcade binaries.',
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
|
|
Loading…
Reference in New Issue