summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/python/binfile.py
diff options
context:
space:
mode:
authorpauldubois <pauldubois@c06c8d41-db1a-0410-9941-cceddc491573>2008-04-19 12:20:10 +0000
committerpauldubois <pauldubois@c06c8d41-db1a-0410-9941-cceddc491573>2008-04-19 12:20:10 +0000
commitf605828804f26076d143fbc5ea6e8d2f1702cf22 (patch)
treed4aa19b0244c7a1144b97022dd7f9a8d217b44f9 /crawl-ref/source/python/binfile.py
parentb0b4d7e1fbb9efed46a590a0045ad270fa409305 (diff)
downloadcrawl-ref-f605828804f26076d143fbc5ea6e8d2f1702cf22.tar.gz
crawl-ref-f605828804f26076d143fbc5ea6e8d2f1702cf22.zip
A utility I've been working on to parse and examine savegames.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4363 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/python/binfile.py')
-rw-r--r--crawl-ref/source/python/binfile.py107
1 files changed, 107 insertions, 0 deletions
diff --git a/crawl-ref/source/python/binfile.py b/crawl-ref/source/python/binfile.py
new file mode 100644
index 0000000000..2ebb986539
--- /dev/null
+++ b/crawl-ref/source/python/binfile.py
@@ -0,0 +1,107 @@
+import struct
+
+class reader(object):
+ """Wrapper around a read-only binary file"""
+ def __init__(self, fileorname):
+ """fileorname may be a file-like object or a filename"""
+ self.byteorder = '=' # can also be '<' or '>'
+ if hasattr(fileorname, 'read'):
+ self.file = fileorname
+ else:
+ self.file = file(fileorname, 'rb')
+
+ def read(self,len): return self.file.read(len)
+
+ def stream(self, fmt, len=0):
+ """Unpack fmt from f and return results."""
+ fmt = self.byteorder + fmt # don't enforce alignment!
+ if len == 0: len = struct.calcsize(fmt)
+ data = self.file.read(len)
+ return struct.unpack(fmt, data)
+
+ def stream1(self, fmt, len=0):
+ """Unpack fmt from f and return just one result."""
+ (data,) = self.stream(fmt,len)
+ return data
+
+ def _streamStringLow(self, len):
+ if len <= 0: return ''
+ str = self.file.read(len-1)
+ char = self.file.read(1)
+ if ord(char)==0: return str
+ else: return str+char
+
+ def streamCooky(self):
+ l = list(self.stream("4c"))
+ l.reverse()
+ return ''.join(l)
+
+ def streamString4(self):
+ """Stream string prefixed with 4 bytes of length"""
+ (strlen,) = self.stream("I",4)
+ if strlen >= 2048:
+ print "Bad string len: %#x" % strlen
+ assert strlen < 2048
+ return self._streamStringLow(strlen)
+
+ def streamString2(self):
+ """Stream string prefixed with 2 bytes of length"""
+ (strlen,) = self.stream("H",2)
+ assert strlen < 2048
+ return self._streamStringLow(strlen)
+
+ def streamString1(self):
+ """Stream string prefixed with 1 byte of length"""
+ (strlen,) = self.stream("B",1)
+ assert strlen < 2048
+ return self._streamStringLow(strlen)
+
+class writer(object):
+ """Wrapper around a write-only binary file"""
+ def __init__(self, fileorname):
+ """fileorname may be a file-like object or a filename"""
+ if hasattr(fileorname, 'write'):
+ self.file = fileorname
+ else:
+ self.file = file(fileorname, 'wb')
+
+ def write(self,data): return self.file.write(data)
+ def stream(self, fmt, *args):
+ fmt = '='+fmt # add the "no alignment" flag to the fmt
+ self.file.write(struct.pack(fmt, *args))
+ # for symmetry with reader
+ def stream1(self, fmt, *args):
+ fmt = '='+fmt # add the "no alignment" flag to the fmt
+ self.file.write(struct.pack(fmt, *args))
+
+ def streamCooky(self, cooky):
+ assert len(cooky)==4
+ l = list(cooky)
+ l.reverse()
+ self.stream("4c", *l)
+
+ def streamString1(self, str):
+ """Stream string prefixed with 1 byte of length"""
+ #print "writing %s" % str
+ # Game doesn't handle 0-length null strings
+ self.file.write(struct.pack("B",len(str)+1))
+ self.file.write(str)
+ self.file.write("\0")
+
+ def streamString2(self, str):
+ """Stream string prefixed with 2 bytes of length"""
+ #print "writing %s" % str
+ # Game doesn't handle 0-length null strings
+ self.file.write(struct.pack("H",len(str)+1))
+ self.file.write(str)
+ self.file.write("\0")
+
+ def streamString4(self, str):
+ """Stream string prefixed with 4 bytes of length"""
+ if str=='':
+ self.file.write(struct.pack("I",0))
+ else:
+ #print "writing %s" % str
+ self.file.write(struct.pack("I",len(str)+1))
+ self.file.write(str)
+ self.file.write("\0")