~bzr-pqm/bzr/bzr.dev

791 by Martin Pool
- import effbot.org http client
1
# $Id: gzip_consumer.py 271 2004-10-09 10:50:59Z fredrik $
2
# gzip consumer
3
#
4
# Copyright (c) 2001-2004 by Fredrik Lundh.  All rights reserved.
5
#
6
7
##
8
# Consumer wrapper for GZIP streams.
9
10
class GzipConsumer:
11
12
    def __init__(self, consumer):
13
        self.__consumer = consumer
14
        self.__decoder = None
15
        self.__data = ""
16
17
    def __getattr__(self, key):
18
        return getattr(self.__consumer, key)
19
20
    def feed(self, data):
21
        if self.__decoder is None:
22
            # check if we have a full gzip header
23
            data = self.__data + data
24
            try:
25
                i = 10
26
                flag = ord(data[3])
27
                if flag & 4: # extra
28
                    x = ord(data[i]) + 256*ord(data[i+1])
29
                    i = i + 2 + x
30
                if flag & 8: # filename
31
                    while ord(data[i]):
32
                        i = i + 1
33
                    i = i + 1
34
                if flag & 16: # comment
35
                    while ord(data[i]):
36
                        i = i + 1
37
                    i = i + 1
38
                if flag & 2: # crc
39
                    i = i + 2
40
                if len(data) < i:
41
                    raise IndexError("not enough data")
42
                if data[:3] != "\x1f\x8b\x08":
43
                    raise IOError("invalid gzip data")
44
                data = data[i:]
45
            except IndexError:
46
                self.__data = data
47
                return # need more data
48
            import zlib
49
            self.__data = ""
50
            self.__decoder = zlib.decompressobj(-zlib.MAX_WBITS)
51
        data = self.__decoder.decompress(data)
52
        if data:
53
            self.__consumer.feed(data)
54
55
    def close(self):
56
        if self.__decoder:
57
            data = self.__decoder.flush()
58
            if data:
59
                self.__consumer.feed(data)
60
        self.__consumer.close()