aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorGravatar Valentin Lorentz2024-06-11 19:55:25 +0200
committerGravatar Sadie Powell2024-06-11 19:05:31 +0100
commit28e2f30525a97f7eb058e5d99e83df4bd6e0a876 (patch)
tree2c7a510a1713c8197ef4b7ecc8729a31d8833253 /tools
parentAdd 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-xtools/convert-unreal-channel21
-rwxr-xr-xtools/convert-unreal-tkl25
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):