示例#1
0
class decompressobj(object):

    def __init__(self, wbits=MAX_WBITS):

        # Jython only uses wbits to determine to skip the header if it's negative;
        # but apparently there are some tests around this that we do some bogus
        # param checking

        if abs(wbits) < 8:
            raise ValueError, "Invalid initialization option"
        if abs(wbits) > 16:  # NOTE apparently this also implies being negative in CPython/zlib
            wbits = -1

        self.inflater = Inflater(wbits < 0)
        self._ended = False
        self.unused_data = ""
        self.unconsumed_tail = ""
        self.gzip = wbits < 0
        self.gzip_header_skipped = False
        self._crc32 = CRC32()


    def decompress(self, string, max_length=0):
        if self._ended:
            raise error("decompressobj may not be used after flush()")

        # unused_data is always "" until inflation is finished; then it is
        # the unused bytes of the input;
        # unconsumed_tail is whatever input was not used because max_length
        # was exceeded before inflation finished.
        # Thus, at most one of {unused_data, unconsumed_tail} may be non-empty.

        self.unconsumed_tail = ""
        if not self.inflater.finished() and not (self.gzip and not self.gzip_header_skipped):
            self.unused_data = ""

        if max_length < 0:
            raise ValueError("max_length must be a positive integer")

        # Suppress gzip header if present and wbits < 0
        if self.gzip and not self.gzip_header_skipped:
            string = self.unused_data + string
            self.unused_data = ""
            try:
                string = _skip_gzip_header(string)
            except IndexError:
                # need more input!
                self.unused_data = string
                return ""
            self.gzip_header_skipped = True

        string = _to_input(string)

        self.inflater.setInput(string)
        inflated = _get_inflate_data(self.inflater, max_length)
        self._crc32.update(inflated)

        r = self.inflater.getRemaining()
        if r:
            if self.gzip and self.inflater.finished() and r == 8:
                # Consume tail, check inflate size, and crc32
                crc,isize = struct.unpack_from("<LL", string[-r:])
                mysize = self.inflater.getBytesWritten() & _MASK32
                mycrc = self._crc32.getValue() & _MASK32
                if mysize != isize:
                    raise error('Error -3 while decompressing data: incorrect length check')
                if mycrc != crc:
                    raise error("Error -3 while decompressing data: incorrect data check")
            elif max_length and not self.inflater.finished():
                self.unconsumed_tail = string[-r:]
            else:
                self.unused_data += string[-r:]

        return inflated

    def flush(self, length=None):
        if self._ended:
            raise error("decompressobj may not be used after flush()")
        if length is None:
            length = 0
        elif length <= 0:
            raise ValueError('length must be greater than zero')
        last = _get_inflate_data(self.inflater, length)
        self.inflater.end()
        return last