Skip to content

Commit 2b0acfc

Browse files
committed
Improved file reading: started using memory-mapping files and added from_any method
1 parent 89b73db commit 2b0acfc

File tree

1 file changed

+42
-16
lines changed

1 file changed

+42
-16
lines changed

kaitaistruct.py

+42-16
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import struct
44
from struct import unpack
55
from io import BytesIO # noqa
6+
from _io import _IOBase
7+
import mmap
8+
from pathlib import Path
69

710
PY2 = sys.version_info[0] == 2
811

@@ -15,8 +18,41 @@
1518
#
1619
__version__ = '0.8'
1720

21+
class _KaitaiFromCtor(object):
22+
"""Adds to class methods to construct it from ctor"""
23+
@classmethod
24+
def from_file(cls, file, map=True):
25+
if isinstance(file, str):
26+
return cls.from_file(Path(file), map)
27+
elif isinstance(file, Path):
28+
with file.open("rb") as f:
29+
return cls.from_file(f, map)
30+
elif isinstance(file, _IOBase):
31+
if map:
32+
with mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as buf:
33+
return cls.from_bytes(buf)
34+
else:
35+
return cls.from_io(file)
36+
else:
37+
raise Exception("file argument must be either file path (either str or Path) or a file object")
38+
39+
@classmethod
40+
def from_any(cls, data, map=True):
41+
"""Parses a Kaitai Struct type"""
42+
if isinstance(data, KaitaiStream):
43+
return cls(data)
44+
elif isinstance(data, (str, Path, _IOBase)):
45+
return cls.from_file(data, map)
46+
elif isinstance(file, (data, bytearray)):
47+
return cls.from_bytes(data)
48+
else:
49+
return cls.from_io(data)
50+
51+
@classmethod
52+
def from_bytes(cls, buf):
53+
return cls.from_io(BytesIO(buf))
1854

19-
class KaitaiStruct(object):
55+
class KaitaiStruct(_KaitaiFromCtor):
2056
def __init__(self, stream):
2157
self._io = stream
2258

@@ -29,26 +65,12 @@ def __exit__(self, *args, **kwargs):
2965
def close(self):
3066
self._io.close()
3167

32-
@classmethod
33-
def from_file(cls, filename):
34-
f = open(filename, 'rb')
35-
try:
36-
return cls(KaitaiStream(f))
37-
except Exception:
38-
# close file descriptor, then reraise the exception
39-
f.close()
40-
raise
41-
42-
@classmethod
43-
def from_bytes(cls, buf):
44-
return cls(KaitaiStream(BytesIO(buf)))
45-
4668
@classmethod
4769
def from_io(cls, io):
4870
return cls(KaitaiStream(io))
4971

5072

51-
class KaitaiStream(object):
73+
class KaitaiStream(_KaitaiFromCtor):
5274
def __init__(self, io):
5375
self._io = io
5476
self.align_to_byte()
@@ -62,6 +84,10 @@ def __exit__(self, *args, **kwargs):
6284
def close(self):
6385
self._io.close()
6486

87+
@classmethod
88+
def from_io(cls, io):
89+
return cls(io)
90+
6591
# ========================================================================
6692
# Stream positioning
6793
# ========================================================================

0 commit comments

Comments
 (0)