static void pylzma_decomp_dealloc(CCompatDecompressionObject *self) { free_lzma_stream(&self->stream); FREE_AND_NULL(self->unconsumed_tail); DEC_AND_NULL(self->unused_data); PyObject_Del(self); }
PyObject *pylzma_decompress_compat(PyObject *self, PyObject *args) { char *data; int length, blocksize=BLOCK_SIZE; PyObject *result = NULL; lzma_stream stream; int res; char *output; if (!PyArg_ParseTuple(args, "s#|i", &data, &length, &blocksize)) return NULL; memset(&stream, 0, sizeof(stream)); if (!(output = (char *)malloc(blocksize))) { PyErr_NoMemory(); goto exit; } lzmaCompatInit(&stream); stream.next_in = (Byte *)data; stream.avail_in = length; stream.next_out = (Byte *)output; stream.avail_out = blocksize; // decompress data while (1) { Py_BEGIN_ALLOW_THREADS res = lzmaCompatDecode(&stream); Py_END_ALLOW_THREADS if (res == LZMA_STREAM_END) { break; } else if (res == LZMA_NOT_ENOUGH_MEM) { // out of memory during decompression PyErr_NoMemory(); goto exit; } else if (res == LZMA_DATA_ERROR) { PyErr_SetString(PyExc_ValueError, "data error during decompression"); goto exit; } else if (res == LZMA_OK) { // check if we need to adjust the output buffer if (stream.avail_out == 0) { output = (char *)realloc(output, blocksize+BLOCK_SIZE); stream.avail_out = BLOCK_SIZE; stream.next_out = (Byte *)&output[blocksize]; blocksize += BLOCK_SIZE; }; } else { PyErr_Format(PyExc_ValueError, "unknown return code from lzmaDecode: %d", res); goto exit; } // if we exit here, decompression finished without returning LZMA_STREAM_END // XXX: why is this sometimes? if (stream.avail_in == 0) break; } result = PyBytes_FromStringAndSize(output, stream.totalOut); exit: free_lzma_stream(&stream); if (output != NULL) free(output); return result; }