Skip to content

Commit bacb8ce

Browse files
committed
Remove igzipdecompressor
1 parent d274e9d commit bacb8ce

File tree

2 files changed

+0
-324
lines changed

2 files changed

+0
-324
lines changed

src/isal/igzip_lib.pyx

Lines changed: 0 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
# cython: binding=True
2323

2424
from libc.stdint cimport UINT64_MAX, UINT32_MAX
25-
from libc.string cimport memmove, memcpy
2625
from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
2726
from cpython.buffer cimport PyBUF_C_CONTIGUOUS, PyObject_GetBuffer, PyBuffer_Release
2827
from cpython.bytes cimport PyBytes_FromStringAndSize
@@ -258,170 +257,6 @@ cdef bytes view_bitbuffer(inflate_state * stream):
258257
# the correct order.
259258
return (read_in >> remainder).to_bytes(8, "little")[:read_in_length]
260259

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-
425260

426261
cdef int mem_level_to_bufsize(int compression_level, int mem_level, unsigned int *bufsize):
427262
"""

tests/test_igzip_lib.py

Lines changed: 0 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,9 @@
1919
# SOFTWARE.
2020

2121
import itertools
22-
import os
23-
import pickle
2422
from typing import NamedTuple
2523

2624
from isal import igzip_lib
27-
from isal.igzip_lib import IgzipDecompressor
2825

2926
import pytest
3027

@@ -57,159 +54,3 @@ def test_compress_decompress(level, flag: Flag, hist_bits):
5754
comp = igzip_lib.compress(DATA, level, flag.comp, hist_bits)
5855
decomp = igzip_lib.decompress(comp, flag.decomp, hist_bits)
5956
assert decomp == DATA
60-
61-
62-
class TestIgzipDecompressor():
63-
# Tests adopted from CPython's test_bz2.py
64-
TEXT = DATA
65-
DATA = igzip_lib.compress(DATA)
66-
BAD_DATA = b"Not a valid deflate block"
67-
68-
def test_decompress(self):
69-
decomp = IgzipDecompressor()
70-
decompressed = decomp.decompress(self.DATA)
71-
assert decompressed == self.TEXT
72-
73-
def testDecompressChunks10(self):
74-
igzd = IgzipDecompressor()
75-
text = b''
76-
n = 0
77-
while True:
78-
str = self.DATA[n*10:(n+1)*10]
79-
if not str:
80-
break
81-
text += igzd.decompress(str)
82-
n += 1
83-
assert text == self.TEXT
84-
85-
def testDecompressUnusedData(self):
86-
igzd = IgzipDecompressor()
87-
unused_data = b"this is unused data"
88-
text = igzd.decompress(self.DATA+unused_data)
89-
assert text == self.TEXT
90-
assert igzd.unused_data == unused_data
91-
92-
def testEOFError(self):
93-
igzd = IgzipDecompressor()
94-
igzd.decompress(self.DATA)
95-
with pytest.raises(EOFError):
96-
igzd.decompress(b"anything")
97-
with pytest.raises(EOFError):
98-
igzd.decompress(b"")
99-
100-
def testDecompress4G(self):
101-
# "Test igzdecompressor.decompress() with >4GiB input"
102-
size = 4 * 1024 ** 3 + 100 # 4 GiB + 100
103-
blocksize = 10 * 1024 * 1024
104-
block = os.urandom(blocksize)
105-
try:
106-
data = block * (size // blocksize + 1)
107-
compressed = igzip_lib.compress(data)
108-
igzd = IgzipDecompressor()
109-
decompressed = igzd.decompress(compressed)
110-
assert decompressed == data
111-
finally:
112-
data = None
113-
compressed = None
114-
decompressed = None
115-
116-
def testPickle(self):
117-
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
118-
with pytest.raises(TypeError):
119-
pickle.dumps(IgzipDecompressor(), proto)
120-
121-
def testDecompressorChunksMaxsize(self):
122-
igzd = IgzipDecompressor()
123-
max_length = 100
124-
out = []
125-
126-
# Feed some input
127-
len_ = len(self.DATA) - 64
128-
out.append(igzd.decompress(self.DATA[:len_],
129-
max_length=max_length))
130-
assert not igzd.needs_input
131-
assert len(out[-1]) == max_length
132-
133-
# Retrieve more data without providing more input
134-
out.append(igzd.decompress(b'', max_length=max_length))
135-
assert not igzd.needs_input
136-
assert len(out[-1]) == max_length
137-
138-
# Retrieve more data while providing more input
139-
out.append(igzd.decompress(self.DATA[len_:],
140-
max_length=max_length))
141-
assert len(out[-1]) == max_length
142-
143-
# Retrieve remaining uncompressed data
144-
while not igzd.eof:
145-
out.append(igzd.decompress(b'', max_length=max_length))
146-
assert len(out[-1]) <= max_length
147-
148-
out = b"".join(out)
149-
assert out == self.TEXT
150-
assert igzd.unused_data == b""
151-
152-
def test_decompressor_inputbuf_1(self):
153-
# Test reusing input buffer after moving existing
154-
# contents to beginning
155-
igzd = IgzipDecompressor()
156-
out = []
157-
158-
# Create input buffer and fill it
159-
assert igzd.decompress(self.DATA[:100], max_length=0) == b''
160-
161-
# Retrieve some results, freeing capacity at beginning
162-
# of input buffer
163-
out.append(igzd.decompress(b'', 2))
164-
165-
# Add more data that fits into input buffer after
166-
# moving existing data to beginning
167-
out.append(igzd.decompress(self.DATA[100:105], 15))
168-
169-
# Decompress rest of data
170-
out.append(igzd.decompress(self.DATA[105:]))
171-
assert b''.join(out) == self.TEXT
172-
173-
def test_decompressor_inputbuf_2(self):
174-
# Test reusing input buffer by appending data at the
175-
# end right away
176-
igzd = IgzipDecompressor()
177-
out = []
178-
179-
# Create input buffer and empty it
180-
assert igzd.decompress(self.DATA[:200], max_length=0) == b''
181-
out.append(igzd.decompress(b''))
182-
183-
# Fill buffer with new data
184-
out.append(igzd.decompress(self.DATA[200:280], 2))
185-
186-
# Append some more data, not enough to require resize
187-
out.append(igzd.decompress(self.DATA[280:300], 2))
188-
189-
# Decompress rest of data
190-
out.append(igzd.decompress(self.DATA[300:]))
191-
assert b''.join(out) == self.TEXT
192-
193-
def test_decompressor_inputbuf_3(self):
194-
# Test reusing input buffer after extending it
195-
196-
igzd = IgzipDecompressor()
197-
out = []
198-
199-
# Create almost full input buffer
200-
out.append(igzd.decompress(self.DATA[:200], 5))
201-
202-
# Add even more data to it, requiring resize
203-
out.append(igzd.decompress(self.DATA[200:300], 5))
204-
205-
# Decompress rest of data
206-
out.append(igzd.decompress(self.DATA[300:]))
207-
assert b''.join(out) == self.TEXT
208-
209-
def test_failure(self):
210-
igzd = IgzipDecompressor()
211-
with pytest.raises(Exception):
212-
igzd.decompress(self.BAD_DATA * 30)
213-
# Make sure there are no internal consistencies
214-
with pytest.raises(Exception):
215-
igzd.decompress(self.BAD_DATA * 30)

0 commit comments

Comments
 (0)