diff pytouhou/formats/pbg3.py @ 204:88361534c77e

Add some documentation (argh, so much left to document!)
author Thibaut Girka <thib@sitedethib.com>
date Tue, 01 Nov 2011 13:46:03 +0100
parents ac2e5e1c2c3c
children b5c7369abd7c
line wrap: on
line diff
--- a/pytouhou/formats/pbg3.py
+++ b/pytouhou/formats/pbg3.py
@@ -12,6 +12,17 @@
 ## GNU General Public License for more details.
 ##
 
+"""PBG3 archive files handling.
+
+This module provides classes for handling the PBG3 file format.
+The PBG3 format is the archive format used by Touhou: EoSD.
+
+PBG3 files are merely a bitstream composed of a header,
+a file table, and LZSS-compressed files.
+"""
+
+from collections import namedtuple
+
 from pytouhou.utils.bitstream import BitStream
 import pytouhou.utils.lzss as lzss
 
@@ -21,12 +32,26 @@ logger = get_logger(__name__)
 
 
 class PBG3BitStream(BitStream):
+    """Helper class to handle strings and integers in PBG3 bitstreams."""
+
     def read_int(self):
+        """Read an integer from the bitstream.
+
+        Integers have variable sizes. They begin with a two-bit value indicating
+        the number of (non-aligned) bytes to read.
+        """
+
         size = self.read(2)
         return self.read((size + 1) * 8)
 
 
     def read_string(self, maxsize):
+        """Read a string from the bitstream.
+
+        Strings are stored as standard NULL-termianted sequences of bytes.
+        The only catch is that they are not byte-aligned.
+        """
+
         string = []
         for i in range(maxsize):
             byte = self.read(8)
@@ -37,9 +62,24 @@ class PBG3BitStream(BitStream):
 
 
 
+PBG3Entry = namedtuple('PBG3Entry', 'unknown1 unknown2 checksum offset size')
+
+
+
 class PBG3(object):
-    def __init__(self, entries, bitstream=None):
-        self.entries = entries
+    """Handle PBG3 archive files.
+
+    PBG3 is a file archive format used in Touhou 6: EoSD.
+    This class provides a representation of such files, as well as functions to
+    read and extract files from a PBG3 archive.
+
+    Instance variables:
+    entries -- list of PBG3Entry objects describing files present in the archive
+    bitstream -- PBG3BitStream object
+    """
+
+    def __init__(self, entries=None, bitstream=None):
+        self.entries = entries or []
         self.bitstream = bitstream #TODO
 
 
@@ -53,6 +93,12 @@ class PBG3(object):
 
     @classmethod
     def read(cls, file):
+        """Read a PBG3 file.
+
+        Raise an exception if the file is invalid.
+        Return a PBG3 instance otherwise.
+        """
+
         magic = file.read(4)
         if magic != b'PBG3':
             raise Exception #TODO
@@ -70,21 +116,31 @@ class PBG3(object):
             offset = bitstream.read_int()
             size = bitstream.read_int()
             name = bitstream.read_string(255).decode('ascii')
-            entries[name] = (unknown1, unknown2, checksum, offset, size)
+            entries[name] = PBG3Entry(unknown1, unknown2, checksum, offset, size)
 
         return PBG3(entries, bitstream)
 
 
     def list_files(self):
+        """List files present in the archive."""
         return self.entries.keys()
 
 
     def extract(self, filename, check=False):
+        """Extract a given file.
+
+        If “filename” is in the archive, extract it and return its contents.
+        Otherwise, raise an exception.
+
+        By default, the checksum of the file won't be verified,
+        you can however force the verification using the “check” argument.
+        """
+
         unkwn1, unkwn2, checksum, offset, size = self.entries[filename]
         self.bitstream.seek(offset)
         data = lzss.decompress(self.bitstream, size)
         if check:
-            # Checking the checksum
+            # Verify the checksum
             compressed_size = self.bitstream.io.tell() - offset
             self.bitstream.seek(offset)
             value = 0