2 # Copyright 2011 Google Inc. All Rights Reserved.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 """Apply gzip/deflate to separate chunks of data."""
22 '\037\213' # magic header
23 '\010' # compression method
25 '\000\000\000\000' # packed time (use zero)
30 def compress_chunks(uncompressed_chunks
, use_gzip
):
31 """Compress a list of data with gzip or deflate.
33 The returned chunks may be used with HTTP chunked encoding.
36 uncompressed_chunks: a list of strings
37 (e.g. ["this is the first chunk", "and the second"])
38 use_gzip: if True, compress with gzip. Otherwise, use deflate.
41 [compressed_chunk_1, compressed_chunk_2, ...]
45 crc
= zlib
.crc32("") & 0xffffffffL
46 compressor
= zlib
.compressobj(
47 6, zlib
.DEFLATED
, -zlib
.MAX_WBITS
, zlib
.DEF_MEM_LEVEL
, 0)
49 compressor
= zlib
.compressobj()
50 compressed_chunks
= []
51 last_index
= len(uncompressed_chunks
) - 1
52 for index
, data
in enumerate(uncompressed_chunks
):
56 crc
= zlib
.crc32(data
, crc
) & 0xffffffffL
59 chunk
+= compressor
.compress(data
)
60 if index
< last_index
:
61 chunk
+= compressor
.flush(zlib
.Z_SYNC_FLUSH
)
63 chunk
+= (compressor
.flush(zlib
.Z_FULL_FLUSH
) +
66 chunk
+= (struct
.pack("<L", long(crc
)) +
67 struct
.pack("<L", long(size
)))
68 compressed_chunks
.append(chunk
)
69 return compressed_chunks
72 def uncompress_chunks(compressed_chunks
, use_gzip
):
73 """Uncompress a list of data compressed with gzip or deflate.
76 compressed_chunks: a list of compressed data
77 use_gzip: if True, uncompress with gzip. Otherwise, use deflate.
80 [uncompressed_chunk_1, uncompressed_chunk_2, ...]
83 decompress
= zlib
.decompressobj(16 + zlib
.MAX_WBITS
).decompress
85 decompress
= zlib
.decompressobj(-zlib
.MAX_WBITS
).decompress
86 return [decompress(c
) for c
in compressed_chunks
]