@@ -30,7 +30,7 @@ from libc.stdint cimport UINT64_MAX, UINT32_MAX, uint32_t
3030from cpython.mem cimport PyMem_Malloc, PyMem_Free
3131from cpython.buffer cimport PyBUF_READ, PyBUF_C_CONTIGUOUS, PyObject_GetBuffer, \
3232 PyBuffer_Release
33-
33+ from cpython.bytes cimport PyBytes_FromStringAndSize
3434
3535
3636cdef extern from " <Python.h>" :
@@ -413,28 +413,22 @@ cdef class Decompress:
413413 self .eof = 0
414414 self .is_initialised = 1
415415
416- cdef save_unconsumed_input(self , object data):
417- cdef Py_ssize_t old_size, new_size, left_size, offset
418- cdef unsigned char * data_ptr
416+ cdef save_unconsumed_input(self , Py_buffer * data):
417+ cdef Py_ssize_t old_size, new_size, left_size
418+ cdef bytes new_data
419419 if self .stream.block_state == ISAL_BLOCK_FINISH:
420420 self .eof = 1
421421 if self .stream.avail_in > 0 :
422422 old_size = len (self .unused_data)
423- data_ptr = data
424- left_size = data_ptr + len (data) - self .stream.next_in
425- offset = self .stream.next_in - data_ptr
426- if offset < 0 :
427- raise Exception ()
423+ left_size = < unsigned char * > data.buf + data.len - self .stream.next_in
428424 if left_size > (PY_SSIZE_T_MAX - old_size):
429425 raise MemoryError ()
430- self .unused_data += data[offset:]
426+ new_data = PyBytes_FromStringAndSize(< char * > self .stream.next_in, left_size)
427+ self .unused_data += new_data
431428 if self .stream.avail_in > 0 or self .unconsumed_tail:
432- data_ptr = data
433- left_size = data_ptr + len (data) - self .stream.next_in
434- offset = self .stream.next_in - data_ptr
435- if offset < 0 :
436- raise Exception ()
437- self .unconsumed_tail = data[offset:]
429+ left_size = < unsigned char * > data.buf + data.len - self .stream.next_in
430+ new_data = PyBytes_FromStringAndSize(< char * > self .stream.next_in, left_size)
431+ self .unconsumed_tail = new_data
438432
439433 def decompress (self , data , Py_ssize_t max_length = 0 ):
440434
@@ -494,7 +488,7 @@ cdef class Decompress:
494488 out.append(obuf[:bytes_written])
495489 if self .stream.block_state == ISAL_BLOCK_FINISH or last_round:
496490 break
497- self .save_unconsumed_input(data )
491+ self .save_unconsumed_input(buffer )
498492 return b" " .join(out)
499493 finally :
500494 PyMem_Free(obuf)
@@ -505,14 +499,14 @@ cdef class Decompress:
505499 raise ValueError (" Length must be greater than 0" )
506500 if length > UINT32_MAX:
507501 raise ValueError (" Length should not be larger than 4GB." )
508- data = self .unconsumed_tail[:]
509- cdef Py_ssize_t ibuflen = len (data)
510- if ibuflen > UINT32_MAX :
511- # This should never happen, because we check the input size in
512- # the decompress function as well.
513- raise IsalError( " Unconsumed tail too large. Can not flush. " )
514- self .stream.next_in = data
515- self .stream.avail_in = ibuflen
502+ cdef Py_buffer buffer_data
503+ cdef Py_buffer * buffer = & buffer_data
504+ if PyObject_GetBuffer( self .unconsumed_tail, buffer , PyBUF_READ & PyBUF_C_CONTIGUOUS) ! = 0 :
505+ raise TypeError ( " Failed to get buffer " )
506+ cdef Py_ssize_t ibuflen = buffer .len
507+ cdef unsigned char * ibuf = < unsigned char * > buffer .buf
508+ self .stream.next_in = ibuf
509+
516510 cdef unsigned long total_bytes = 0
517511 cdef unsigned long bytes_written
518512 out = []
@@ -521,23 +515,24 @@ cdef class Decompress:
521515 cdef Py_ssize_t unused_bytes
522516
523517 try :
524- while (self .stream.block_state != ISAL_BLOCK_FINISH
525- and self .stream.avail_in != 0 ):
526- self .stream.next_out = obuf # Reset output buffer.
527- self .stream.avail_out = obuflen
528- err = isal_inflate(& self .stream)
529- if err != ISAL_DECOMP_OK:
530- # There is some python interacting when possible exceptions
531- # Are raised. So we remain in pure C code if we check for
532- # COMP_OK first.
533- check_isal_inflate_rc(err)
534- # Instead of output buffer resizing as the zlibmodule.c example
535- # the data is appended to a list.
536- # TODO: Improve this with the buffer protocol.
537- bytes_written = obuflen - self .stream.avail_out
538- total_bytes += bytes_written
539- out.append(obuf[:bytes_written])
540- self .save_unconsumed_input(data)
518+ while self .stream.block_state != ISAL_BLOCK_FINISH and ibuflen != 0 :
519+ arrange_input_buffer(& self .stream, & ibuflen)
520+ while (self .stream.block_state != ISAL_BLOCK_FINISH):
521+ self .stream.next_out = obuf # Reset output buffer.
522+ self .stream.avail_out = obuflen
523+ err = isal_inflate(& self .stream)
524+ if err != ISAL_DECOMP_OK:
525+ # There is some python interacting when possible exceptions
526+ # Are raised. So we remain in pure C code if we check for
527+ # COMP_OK first.
528+ check_isal_inflate_rc(err)
529+ # Instead of output buffer resizing as the zlibmodule.c example
530+ # the data is appended to a list.
531+ # TODO: Improve this with the buffer protocol.
532+ bytes_written = obuflen - self .stream.avail_out
533+ total_bytes += bytes_written
534+ out.append(obuf[:bytes_written])
535+ self .save_unconsumed_input(buffer )
541536 return b" " .join(out)
542537 finally :
543538 PyMem_Free(obuf)
0 commit comments