|
22 | 22 | import gzip
|
23 | 23 | import io
|
24 | 24 | import os
|
| 25 | +import shutil |
25 | 26 | import struct
|
26 | 27 | import sys
|
27 | 28 | import time
|
|
41 | 42 | READ_BUFFER_SIZE = 512 * 1024
|
42 | 43 |
|
43 | 44 | FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
|
44 |
| -READ, WRITE = 1, 2 |
| 45 | +READ, WRITE = gzip.READ, gzip.WRITE |
45 | 46 |
|
46 | 47 | BadGzipFile = gzip.BadGzipFile # type: ignore
|
47 | 48 |
|
@@ -180,50 +181,27 @@ def write(self, data):
|
180 | 181 | _GzipNGReader = _GzipReader
|
181 | 182 |
|
182 | 183 |
|
183 |
| -def _create_simple_gzip_header(compresslevel: int, |
184 |
| - mtime=None) -> bytes: |
185 |
| - """ |
186 |
| - Write a simple gzip header with no extra fields. |
187 |
| - :param compresslevel: Compresslevel used to determine the xfl bytes. |
188 |
| - :param mtime: The mtime (must support conversion to a 32-bit integer). |
189 |
| - :return: A bytes object representing the gzip header. |
190 |
| - """ |
191 |
| - if mtime is None: |
192 |
| - mtime = time.time() |
193 |
| - if compresslevel == _COMPRESS_LEVEL_BEST: |
194 |
| - xfl = 2 |
195 |
| - elif compresslevel == _COMPRESS_LEVEL_FAST: |
196 |
| - xfl = 4 |
197 |
| - else: |
198 |
| - xfl = 0 |
199 |
| - # Pack ID1 and ID2 magic bytes, method (8=deflate), header flags (no extra |
200 |
| - # fields added to header), mtime, xfl and os (255 for unknown OS). |
201 |
| - return struct.pack("<BBBBLBB", 0x1f, 0x8b, 8, 0, int(mtime), xfl, 255) |
202 |
| - |
203 |
| - |
204 | 184 | def compress(data, compresslevel=_COMPRESS_LEVEL_BEST, *, mtime=None):
|
205 | 185 | """Compress data in one shot and return the compressed string.
|
206 | 186 | compresslevel sets the compression level in range of 0-9.
|
207 | 187 | mtime can be used to set the modification time. The modification time is
|
208 | 188 | set to the current time by default.
|
209 | 189 | """
|
210 |
| - if mtime == 0: |
211 |
| - # Use zlib as it creates the header with 0 mtime by default. |
212 |
| - # This is faster and with less overhead. |
213 |
| - return zlib_ng.compress(data, level=compresslevel, wbits=31) |
214 |
| - header = _create_simple_gzip_header(compresslevel, mtime) |
215 |
| - trailer = struct.pack("<LL", zlib_ng.crc32(data), (len(data) & 0xffffffff)) |
216 |
| - # Wbits=-15 creates a raw deflate block. |
217 |
| - return (header + zlib_ng.compress(data, level=compresslevel, wbits=-15) + |
218 |
| - trailer) |
| 190 | + # Wbits=31 automatically includes a gzip header and trailer. |
| 191 | + gzip_data = zlib_ng.compress(data, level=compresslevel, wbits=31) |
| 192 | + if mtime is None: |
| 193 | + mtime = time.time() |
| 194 | + # Reuse gzip header created by zlib_ng, replace mtime and OS byte for |
| 195 | + # consistency. |
| 196 | + header = struct.pack("<4sLBB", gzip_data, int(mtime), gzip_data[8], 255) |
| 197 | + return header + gzip_data[10:] |
219 | 198 |
|
220 | 199 |
|
221 | 200 | def decompress(data):
|
222 | 201 | """Decompress a gzip compressed string in one shot.
|
223 | 202 | Return the decompressed string.
|
224 | 203 | """
|
225 |
| - fp = io.BytesIO(data) |
226 |
| - reader = _GzipReader(fp, max(len(data), 16)) |
| 204 | + reader = _GzipReader(data) |
227 | 205 | return reader.readall()
|
228 | 206 |
|
229 | 207 |
|
@@ -325,11 +303,7 @@ def main():
|
325 | 303 | global READ_BUFFER_SIZE
|
326 | 304 | READ_BUFFER_SIZE = args.buffer_size
|
327 | 305 | try:
|
328 |
| - while True: |
329 |
| - block = in_file.read(args.buffer_size) |
330 |
| - if block == b"": |
331 |
| - break |
332 |
| - out_file.write(block) |
| 306 | + shutil.copyfileobj(in_file, out_file, args.buffer_size) |
333 | 307 | finally:
|
334 | 308 | if in_file is not sys.stdin.buffer:
|
335 | 309 | in_file.close()
|
|
0 commit comments