|
22 | 22 | # cython: binding=True |
23 | 23 |
|
24 | 24 | from libc.stdint cimport UINT64_MAX, UINT32_MAX |
25 | | -from libc.string cimport memmove, memcpy |
26 | 25 | from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free |
27 | 26 | from cpython.buffer cimport PyBUF_C_CONTIGUOUS, PyObject_GetBuffer, PyBuffer_Release |
28 | 27 | from cpython.bytes cimport PyBytes_FromStringAndSize |
@@ -258,170 +257,6 @@ cdef bytes view_bitbuffer(inflate_state * stream): |
258 | 257 | # the correct order. |
259 | 258 | return (read_in >> remainder).to_bytes(8, "little")[:read_in_length] |
260 | 259 |
|
261 | | -cdef class IgzipDecompressor: |
262 | | - """Decompress object for handling streaming decompression.""" |
263 | | - cdef public bytes unused_data |
264 | | - cdef public bint eof |
265 | | - cdef public bint needs_input |
266 | | - cdef inflate_state stream |
267 | | - cdef unsigned char * input_buffer |
268 | | - cdef size_t input_buffer_size |
269 | | - cdef Py_ssize_t avail_in_real |
270 | | - |
271 | | - def __dealloc__(self): |
272 | | - if self.input_buffer != NULL: |
273 | | - PyMem_Free(self.input_buffer) |
274 | | - |
275 | | - def __cinit__(self, |
276 | | - flag=ISAL_DEFLATE, |
277 | | - hist_bits=ISAL_DEF_MAX_HIST_BITS, |
278 | | - zdict = None): |
279 | | - isal_inflate_init(&self.stream) |
280 | | - |
281 | | - self.stream.hist_bits = hist_bits |
282 | | - self.stream.crc_flag = flag |
283 | | - cdef Py_ssize_t zdict_length |
284 | | - if zdict: |
285 | | - zdict_length = len(zdict) |
286 | | - if zdict_length > UINT32_MAX: |
287 | | - raise OverflowError("zdict length does not fit in an unsigned int") |
288 | | - err = isal_inflate_set_dict(&self.stream, zdict, zdict_length) |
289 | | - if err != COMP_OK: |
290 | | - check_isal_deflate_rc(err) |
291 | | - self.unused_data = b"" |
292 | | - self.eof = False |
293 | | - self.input_buffer = NULL |
294 | | - self.input_buffer_size = 0 |
295 | | - self.avail_in_real = 0 |
296 | | - self.needs_input = True |
297 | | - |
298 | | - def _view_bitbuffer(self): |
299 | | - """Shows the 64-bitbuffer of the internal inflate_state. It contains |
300 | | - a maximum of 8 bytes. This data is already read-in so is not part |
301 | | - of the unconsumed tail.""" |
302 | | - return view_bitbuffer(&self.stream) |
303 | | - |
304 | | - cdef decompress_buf(self, Py_ssize_t max_length, unsigned char ** obuf): |
305 | | - obuf[0] = NULL |
306 | | - cdef Py_ssize_t obuflen = DEF_BUF_SIZE_I |
307 | | - cdef int err |
308 | | - if obuflen > max_length: |
309 | | - obuflen = max_length |
310 | | - while True: |
311 | | - obuflen = arrange_output_buffer_with_maximum(&self.stream, obuf, obuflen, max_length) |
312 | | - if obuflen == -1: |
313 | | - raise MemoryError("Unsufficient memory for buffer allocation") |
314 | | - elif obuflen == -2: |
315 | | - break |
316 | | - arrange_input_buffer(&self.stream, &self.avail_in_real) |
317 | | - err = isal_inflate(&self.stream) |
318 | | - self.avail_in_real += self.stream.avail_in |
319 | | - if err != ISAL_DECOMP_OK: |
320 | | - check_isal_inflate_rc(err) |
321 | | - if self.stream.block_state == ISAL_BLOCK_FINISH: |
322 | | - self.eof = 1 |
323 | | - break |
324 | | - elif self.avail_in_real == 0: |
325 | | - break |
326 | | - return |
327 | | - |
328 | | - def decompress(self, data, Py_ssize_t max_length = -1): |
329 | | - """ |
330 | | - Decompress data, returning a bytes object containing the uncompressed |
331 | | - data corresponding to at least part of the data in string. |
332 | | -
|
333 | | - :param max_length: if non-zero then the return value will be no longer |
334 | | - than max_length. Unprocessed data will be in the |
335 | | - unconsumed_tail attribute. |
336 | | - """ |
337 | | - if self.eof: |
338 | | - raise EOFError("End of stream already reached") |
339 | | - cdef bint input_buffer_in_use |
340 | | - |
341 | | - cdef Py_ssize_t hard_limit |
342 | | - if max_length < 0: |
343 | | - hard_limit = PY_SSIZE_T_MAX |
344 | | - else: |
345 | | - hard_limit = max_length |
346 | | - |
347 | | - cdef unsigned int avail_now |
348 | | - cdef unsigned int avail_total |
349 | | - # Cython makes sure error is handled when acquiring buffer fails. |
350 | | - cdef Py_buffer buffer_data |
351 | | - cdef Py_buffer* buffer = &buffer_data |
352 | | - PyObject_GetBuffer(data, buffer, PyBUF_C_CONTIGUOUS) |
353 | | - cdef Py_ssize_t ibuflen = buffer.len |
354 | | - cdef unsigned char * data_ptr = <unsigned char*>buffer.buf |
355 | | - |
356 | | - |
357 | | - cdef bint max_length_reached = False |
358 | | - cdef unsigned char * tmp |
359 | | - cdef size_t offset |
360 | | - # Initialise output buffer |
361 | | - cdef unsigned char *obuf = NULL |
362 | | - |
363 | | - try: |
364 | | - if self.stream.next_in != NULL: |
365 | | - avail_now = (self.input_buffer + self.input_buffer_size) - \ |
366 | | - (self.stream.next_in + self.avail_in_real) |
367 | | - avail_total = self.input_buffer_size - self.avail_in_real |
368 | | - if avail_total < ibuflen: |
369 | | - offset = self.stream.next_in - self.input_buffer |
370 | | - new_size = self.input_buffer_size + ibuflen - avail_now |
371 | | - tmp = <unsigned char*>PyMem_Realloc(self.input_buffer, new_size) |
372 | | - if tmp == NULL: |
373 | | - raise MemoryError() |
374 | | - self.input_buffer = tmp |
375 | | - self.input_buffer_size = new_size |
376 | | - self.stream.next_in = self.input_buffer + offset |
377 | | - elif avail_now < ibuflen: |
378 | | - memmove(self.input_buffer, self.stream.next_in, |
379 | | - self.avail_in_real) |
380 | | - self.stream.next_in = self.input_buffer |
381 | | - memcpy(<void *>(self.stream.next_in + self.avail_in_real), data_ptr, buffer.len) |
382 | | - self.avail_in_real += ibuflen |
383 | | - input_buffer_in_use = 1 |
384 | | - else: |
385 | | - self.stream.next_in = data_ptr |
386 | | - self.avail_in_real = ibuflen |
387 | | - input_buffer_in_use = 0 |
388 | | - |
389 | | - self.decompress_buf(hard_limit, &obuf) |
390 | | - if obuf == NULL: |
391 | | - self.stream.next_in = NULL |
392 | | - return b"" |
393 | | - if self.eof: |
394 | | - self.needs_input = False |
395 | | - if self.avail_in_real > 0: |
396 | | - new_data = PyBytes_FromStringAndSize(<char *>self.stream.next_in, self.avail_in_real) |
397 | | - self.unused_data = self._view_bitbuffer() + new_data |
398 | | - elif self.avail_in_real == 0: |
399 | | - self.stream.next_in = NULL |
400 | | - self.needs_input = True |
401 | | - else: |
402 | | - self.needs_input = False |
403 | | - if not input_buffer_in_use: |
404 | | - # Discard buffer if to small. |
405 | | - # Resizing may needlessly copy the current contents. |
406 | | - if self.input_buffer != NULL and self.input_buffer_size < self.avail_in_real: |
407 | | - PyMem_Free(self.input_buffer) |
408 | | - self.input_buffer = NULL |
409 | | - |
410 | | - # Allocate of necessary |
411 | | - if self.input_buffer == NULL: |
412 | | - self.input_buffer = <unsigned char *>PyMem_Malloc(self.avail_in_real) |
413 | | - if self.input_buffer == NULL: |
414 | | - raise MemoryError() |
415 | | - self.input_buffer_size = self.avail_in_real |
416 | | - |
417 | | - # Copy tail |
418 | | - memcpy(self.input_buffer, self.stream.next_in, self.avail_in_real) |
419 | | - self.stream.next_in = self.input_buffer |
420 | | - return PyBytes_FromStringAndSize(<char*>obuf, self.stream.next_out - obuf) |
421 | | - finally: |
422 | | - PyBuffer_Release(buffer) |
423 | | - PyMem_Free(obuf) |
424 | | - |
425 | 260 |
|
426 | 261 | cdef int mem_level_to_bufsize(int compression_level, int mem_level, unsigned int *bufsize): |
427 | 262 | """ |
|
0 commit comments