예제 #1
0
class Decompress(object):

    STATE_MAGIC = 0
    STATE_BLOCK_HEADER = 1
    STATE_BLOCK = 2

    def __init__(self):
        self.__buff = lzo_buffer(MAX_BLOCK)
        self.__fifo = Fifo()
        self.__output = []
        self.state = self.STATE_MAGIC

    def __yield_output(self):
        output = ''.join(self.__output)
        self.__output = []
        return output

    def decompress(self, data):
        self.__fifo.write(data)

        while True:

            # magic
            if self.state == self.STATE_MAGIC:
                magic = self.__fifo.readblock(len(LZO_MAGIC))
                if not magic:
                    break
                if magic != LZO_MAGIC:
                    raise Exception('Bad magic: %s' % magic)
                self.state = self.STATE_BLOCK_HEADER

            # block header
            if self.state == self.STATE_BLOCK_HEADER:
                header = self.__fifo.readblock(_BLOCK_HEADER_LENGTH)
                if not header:
                    break
                self.__block_length = unpack(_BLOCK_HEADER_FORMAT, header)[0]
                self.__block_compressed = self.__block_length & 0x8000
                self.__block_length ^= self.__block_compressed
                if self.__block_length:
                    self.state = self.STATE_BLOCK

            # block
            if self.state == self.STATE_BLOCK:
                block = self.__fifo.readblock(self.__block_length)
                if not block:
                    break
                if self.__block_compressed:
                    decomp = lzo1x_decompress(block, self.__buff)
                    self.__output.append(decomp)
                else:
                    self.__output.append(block)
                self.state = self.STATE_BLOCK_HEADER

        return self.__yield_output()