mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-05 02:43:37 +00:00
980e05cc99
Backported 400 revisions from rev 1de4961-8897c5b (2018-2014). Move core/benchmark, core/cmd_line, core/memory, core/profiler and core/timeout to core/optional/* Remove metadata/qt* PORT: Version 2.0a3 (inline with 3.0a3 @ f80c7d5). Basic Support for XMP Packets. tga: improvements to adhere more closely to the spec. pdf: slightly improved parsing. rar: fix TypeError on unknown block types. Add MacRoman win32 codepage. tiff/exif: support SubIFDs and tiled images. Add method to export metadata in dictionary. mpeg_video: don't attempt to parse Stream past length. mpeg_video: parse ESCR correctly, add SCR value. Change centralise CustomFragments. field: don't set parser class if class is None, to enable autodetect. field: add value/display for CustomFragment. parser: inline warning to enable tracebacks in debug mode. Fix empty bytestrings in makePrintable. Fix contentSize in jpeg.py to account for image_data blocks. Fix the ELF parser. Enhance the AR archive parser. elf parser: fix wrong wrong fields order in parsing little endian section flags. elf parser: add s390 as a machine type. Flesh out mp4 parser. PORT: Version 2.0a1 (inline with 3.0a1). Major refactoring and PEP8. Fix ResourceWarning warnings on files. Add a close() method and support for the context manager protocol ("with obj: ...") to parsers, input and output streams. metadata: get comment from ZIP. Support for InputIOStream.read(0). Fix sizeGe when size is None. Remove unused new_seekable_field_set file. Remove parser Mapsforge .map. Remove parser Parallel Realities Starfighter .pak files. sevenzip: fix for newer archives. java: update access flags and modifiers for Java 1.7 and update description text for most recent Java. Support ustar prefix field in tar archives. Remove file_system* parsers. Remove misc parsers 3d0, 3ds, gnome_keyring, msoffice*, mstask, ole*, word*. Remove program parsers macho, nds, prc. Support non-8bit Character subclasses. Python parser supports Python 3.7. Enhance mpeg_ts parser to support MTS/M2TS. Support for creation date in tiff. Change don't hardcode errno constant. PORT: 1.9.1 Internal Only: The following are legacy reference to upstream commit messages. Relevant changes up to b0a115f8. Use integer division. Replace HACHOIR_ERRORS with Exception. Fix metadata.Data: make it sortable. Import fixes from e7de492. PORT: Version 2.0a1 (inline with 3.0a1 @ e9f8fad). Replace hachoir.core.field with hachoir.field Replace hachoir.core.stream with hachoir.stream Remove the compatibility module for PY1.5 to PY2.5. metadata: support TIFF picture. metadata: fix string normalization. metadata: fix datetime regex Fix hachoir bug #57. FileFromInputStream: fix comparison between None and an int. InputIOStream: open the file in binary mode.
93 lines
3.2 KiB
Python
93 lines
3.2 KiB
Python
from hachoir.field import BasicFieldSet, GenericFieldSet, ParserError, createRawField
|
|
|
|
|
|
# getgaps(int, int, [listof (int, int)]) -> generator of (int, int)
|
|
# Gets all the gaps not covered by a block in `blocks` from `start` for `length` units.
|
|
def getgaps(start, length, blocks):
|
|
"""
|
|
Example:
|
|
>>> list(getgaps(0, 20, [(15,3), (6,2), (6,2), (1,2), (2,3), (11,2), (9,5)]))
|
|
[(0, 1), (5, 1), (8, 1), (14, 1), (18, 2)]
|
|
"""
|
|
# done this way to avoid mutating the original
|
|
blocks = sorted(blocks, key=lambda b: b[0])
|
|
end = start + length
|
|
for s, l in blocks:
|
|
if s > start:
|
|
yield (start, s - start)
|
|
start = s
|
|
if s + l > start:
|
|
start = s + l
|
|
if start < end:
|
|
yield (start, end - start)
|
|
|
|
|
|
class RootSeekableFieldSet(GenericFieldSet):
|
|
|
|
def close(self):
|
|
self.stream.close()
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, *args, **kwargs):
|
|
self.close()
|
|
|
|
def seekBit(self, address, relative=True):
|
|
if not relative:
|
|
address -= self.absolute_address
|
|
if address < 0:
|
|
raise ParserError("Seek below field set start (%s.%s)" % divmod(address, 8))
|
|
self._current_size = address
|
|
return None
|
|
|
|
def seekByte(self, address, relative=True):
|
|
return self.seekBit(address * 8, relative)
|
|
|
|
def _fixLastField(self):
|
|
"""
|
|
Try to fix last field when we know current field set size.
|
|
Returns new added field if any, or None.
|
|
"""
|
|
assert self._size is not None
|
|
|
|
# Stop parser
|
|
message = ["stop parser"]
|
|
self._field_generator = None
|
|
|
|
# If last field is too big, delete it
|
|
while self._size < self._current_size:
|
|
field = self._deleteField(len(self._fields) - 1)
|
|
message.append("delete field %s" % field.path)
|
|
assert self._current_size <= self._size
|
|
|
|
blocks = [(x.absolute_address, x.size) for x in self._fields]
|
|
fields = []
|
|
self._size = max(self._size, max(a + b for a, b in blocks) - self.absolute_address)
|
|
for start, length in getgaps(self.absolute_address, self._size, blocks):
|
|
self.seekBit(start, relative=False)
|
|
field = createRawField(self, length, "unparsed[]")
|
|
self.setUniqueFieldName(field)
|
|
self._fields.append(field.name, field)
|
|
fields.append(field)
|
|
message.append("found unparsed segment: start %s, length %s" % (start, length))
|
|
self.seekBit(self._size + self.absolute_address, relative=False)
|
|
message = ", ".join(message)
|
|
if fields:
|
|
self.warning("[Autofix] Fix parser error: " + message)
|
|
return fields
|
|
|
|
def _stopFeeding(self):
|
|
if self._size is None:
|
|
if self._parent:
|
|
self._size = self._current_size
|
|
|
|
new_field = self._fixLastField()
|
|
self._field_generator = None
|
|
return new_field
|
|
|
|
|
|
class SeekableFieldSet(RootSeekableFieldSet):
|
|
def __init__(self, parent, name, description=None, size=None):
|
|
assert issubclass(parent.__class__, BasicFieldSet)
|
|
RootSeekableFieldSet.__init__(self, parent, name, parent.stream, description, size)
|