Skip to content

Commit 28bc0ad

Browse files
committed
Use buffer for save unconsumed input
1 parent 9ea53a2 commit 28bc0ad

File tree

1 file changed

+37
-42
lines changed

1 file changed

+37
-42
lines changed

src/isal/isal_zlib.pyx

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ from libc.stdint cimport UINT64_MAX, UINT32_MAX, uint32_t
3030
from cpython.mem cimport PyMem_Malloc, PyMem_Free
3131
from cpython.buffer cimport PyBUF_READ, PyBUF_C_CONTIGUOUS, PyObject_GetBuffer, \
3232
PyBuffer_Release
33-
33+
from cpython.bytes cimport PyBytes_FromStringAndSize
3434

3535

3636
cdef 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

Comments
 (0)