diff options
| author | 2024-06-11 19:55:25 +0200 | |
|---|---|---|
| committer | 2024-06-11 19:05:31 +0100 | |
| commit | 28e2f30525a97f7eb058e5d99e83df4bd6e0a876 (patch) | |
| tree | 2c7a510a1713c8197ef4b7ecc8729a31d8833253 /tools | |
| parent | Add some tools for converting UnrealIRCd databases to InspIRCd. (diff) | |
tools/convert-unreal-*: Parse input in linear time
Non-trivial string slicing on CPython makes a copy of the string, making
the overall parsing run in quadratic time.
For example, assuming an average field size of 10 bytes, parsing a 1MB
file on my computer would take 70s in slicing alone.
Diffstat (limited to 'tools')
| -rwxr-xr-x | tools/convert-unreal-channel | 21 | ||||
| -rwxr-xr-x | tools/convert-unreal-tkl | 25 |
2 files changed, 15 insertions, 31 deletions
diff --git a/tools/convert-unreal-channel b/tools/convert-unreal-channel index a580606f6..32c907e47 100755 --- a/tools/convert-unreal-channel +++ b/tools/convert-unreal-channel @@ -18,6 +18,7 @@ # +import io import os import sys @@ -29,36 +30,28 @@ class UnrealDB: with open(sys.argv[1], mode="rb") as fh: data = fh.read() if data.startswith(b"UnrealIRCd-DB-v1"): - self.data = data[40:] + self.data = io.BytesIO(data[40:]) elif data.startswith(b"UnrealIRCd-DB"): self.error = f"Unsupported database version: {data[0:32]}" else: - self.data = data + self.data = io.BytesIO(data) except OSError as e: self.error = f"Read error: {e}" def read_i16(self): - tmp = int.from_bytes(self.data[0:2], byteorder="little") - self.data = self.data[2:] - return tmp + return int.from_bytes(self.data.read(2), byteorder="little") def read_i32(self): - tmp = int.from_bytes(self.data[0:4], byteorder="little") - self.data = self.data[4:] - return tmp + return int.from_bytes(self.data.read(4), byteorder="little") def read_i64(self): - tmp = int.from_bytes(self.data[0:8], byteorder="little") - self.data = self.data[8:] - return tmp + return int.from_bytes(self.data.read(8), byteorder="little") def read_str(self): len = self.read_i16() if len == 0 or len == 0xFFFF: return "" - tmp = self.data[0:len] - self.data = self.data[len:] - return str(tmp, "utf-8") + return self.data.read(len).decode("utf-8") def error(msg): diff --git a/tools/convert-unreal-tkl b/tools/convert-unreal-tkl index 58dd37192..692627a69 100755 --- a/tools/convert-unreal-tkl +++ b/tools/convert-unreal-tkl @@ -18,6 +18,7 @@ # +import io import os import sys @@ -29,41 +30,31 @@ class UnrealDB: with open(sys.argv[1], mode="rb") as fh: data = fh.read() if data.startswith(b"UnrealIRCd-DB-v1"): - self.data = data[40:] + self.data = io.BytesIO(data[40:]) elif data.startswith(b"UnrealIRCd-DB"): self.error = f"Unsupported database version: {data[0:32]}" else: - self.data = data + self.data = io.BytesIO(data) except OSError as e: self.error = f"Read error: {e}" def read_char(self): - tmp = self.data[0:1] - self.data = self.data[1:] - return str(tmp, "utf-8") + return self.data.read(1).decode("utf-8") def read_i16(self): - tmp = int.from_bytes(self.data[0:2], byteorder="little") - self.data = self.data[2:] - return tmp + return int.from_bytes(self.data.read(2), byteorder="little") def read_i32(self): - tmp = int.from_bytes(self.data[0:4], byteorder="little") - self.data = self.data[4:] - return tmp + return int.from_bytes(self.data.read(4), byteorder="little") def read_i64(self): - tmp = int.from_bytes(self.data[0:8], byteorder="little") - self.data = self.data[8:] - return tmp + return int.from_bytes(self.data.read(8), byteorder="little") def read_str(self): len = self.read_i16() if len == 0 or len == 0xFFFF: return "" - tmp = self.data[0:len] - self.data = self.data[len:] - return str(tmp, "utf-8") + return self.data.read(len).decode("utf-8") def error(msg): |
