コード例 #1
0
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);
}
コード例 #2
0
static void
pylzma_compfile_dealloc(CCompressionFileObject *self)
{
    DEC_AND_NULL(self->inFile);
    LzmaEnc_Destroy(self->encoder, &allocator, &allocator);
    if (self->outStream.data != NULL) {
        free(self->outStream.data);
    }
    self->ob_type->tp_free((PyObject*)self);
}
コード例 #3
0
static PyObject *pylzma_decomp_decompress(CDecompressionObject *self, PyObject *args)
{
    PyObject *result=NULL;
    unsigned char *data, *next_in, *next_out;
    int length, start_total_out, res, max_length=BLOCK_SIZE;
    SizeT avail_in, avail_out;
    unsigned char properties[LZMA_PROPERTIES_SIZE];
    SizeT inProcessed, outProcessed;
    
    if (!PyArg_ParseTuple(args, "s#|l", &data, &length, &max_length))
        return NULL;

    if (max_length <= 0)
    {
        PyErr_SetString(PyExc_ValueError, "bufsize must be greater than zero");
        return NULL;
    }
    
    start_total_out = self->total_out;
    if (self->unconsumed_length > 0) {
        self->unconsumed_tail = (unsigned char *)realloc(self->unconsumed_tail, self->unconsumed_length + length);
        next_in = (unsigned char *)self->unconsumed_tail;
        memcpy(next_in + self->unconsumed_length, data, length);
    } else
        next_in = data;
    
    avail_in = self->unconsumed_length + length;
    
    if (self->need_properties && avail_in < sizeof(properties)) {
        // we need enough bytes to read the properties
        if (!self->unconsumed_length) {
            self->unconsumed_tail = (unsigned char *)malloc(length);
            memcpy(self->unconsumed_tail, data, length);
        }
        self->unconsumed_length += length;
        
        return PyString_FromString("");
    }

    if (self->need_properties) {
        self->need_properties = 0;
        memcpy(&properties, next_in, sizeof(properties));
        avail_in -= sizeof(properties);
        next_in += sizeof(properties);
        if (self->unconsumed_length >= sizeof(properties)-length) {
            self->unconsumed_length -= sizeof(properties)-length;
            if (self->unconsumed_length > 0) {
                memcpy(self->unconsumed_tail, self->unconsumed_tail+sizeof(properties), self->unconsumed_length);
                self->unconsumed_tail = (unsigned char *)realloc(self->unconsumed_tail, self->unconsumed_length);
            } else
                FREE_AND_NULL(self->unconsumed_tail);
        }
        
        if (LzmaDecodeProperties(&self->state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
        {
            PyErr_SetString(PyExc_TypeError, "Incorrect stream properties");
            goto exit;
        }
        
        self->state.Probs = (CProb *)malloc(LzmaGetNumProbs(&self->state.Properties) * sizeof(CProb));
        if (self->state.Probs == 0) {
            PyErr_NoMemory();
            goto exit;
        }
        
        if (self->state.Properties.DictionarySize == 0)
            self->state.Dictionary = 0;
        else {
            self->state.Dictionary = (unsigned char *)malloc(self->state.Properties.DictionarySize);
            if (self->state.Dictionary == 0) {
                free(self->state.Probs);
                self->state.Probs = NULL;
                PyErr_NoMemory();
                goto exit;
            }
        }
    
        LzmaDecoderInit(&self->state);
    }

    if (avail_in == 0)
        // no more bytes to decompress
        return PyString_FromString("");
    
    if (!(result = PyString_FromStringAndSize(NULL, max_length)))
        return NULL;
    
    next_out = (unsigned char *)PyString_AS_STRING(result);
    avail_out = max_length;
    
    Py_BEGIN_ALLOW_THREADS
    // Decompress until EOS marker is reached
    res = LzmaDecode(&self->state, next_in, avail_in, &inProcessed,
                     next_out, avail_out, &outProcessed, 0);
    Py_END_ALLOW_THREADS
    self->total_out += outProcessed;
    next_in += inProcessed;
    avail_in -= inProcessed;
    next_out += outProcessed;
    avail_out -= outProcessed;
    
    if (res != LZMA_RESULT_OK) {
        PyErr_SetString(PyExc_ValueError, "data error during decompression");
        DEC_AND_NULL(result);
        goto exit;
    }

    /* Not all of the compressed data could be accomodated in the output buffer
    of specified size. Return the unconsumed tail in an attribute.*/
    if (avail_in > 0)
    {
        if (avail_in != self->unconsumed_length) {
            if (avail_in > self->unconsumed_length) {
                self->unconsumed_tail = (unsigned char *)realloc(self->unconsumed_tail, avail_in);
                memcpy(self->unconsumed_tail, next_in, avail_in);
            }
            if (avail_in < self->unconsumed_length) {
                memcpy(self->unconsumed_tail, next_in, avail_in);
                self->unconsumed_tail = (unsigned char *)realloc(self->unconsumed_tail, avail_in);
            }
        }
        
        if (!self->unconsumed_tail) {
            PyErr_NoMemory();
            DEC_AND_NULL(result);
            goto exit;
        }
    } else
        FREE_AND_NULL(self->unconsumed_tail);
    
    self->unconsumed_length = avail_in;

    _PyString_Resize(&result, self->total_out - start_total_out);
    
exit:
    return result;    
}
コード例 #4
0
static PyObject *pylzma_decomp_flush(CDecompressionObject *self, PyObject *args)
{
    PyObject *result=NULL;
    int res;
    SizeT avail_out, outsize;
    unsigned char *tmp;
    SizeT inProcessed, outProcessed;
    
    if (!PyArg_ParseTuple(args, ""))
        return NULL;

    if (self->max_length != -1)
        avail_out = self->max_length - self->total_out;
    else
        avail_out = BLOCK_SIZE;
    
    if (avail_out == 0)
        // no more remaining data
        return PyString_FromString("");
    
    result = PyString_FromStringAndSize(NULL, avail_out);
    if (result == NULL)
        return NULL;
    
    tmp = (unsigned char *)PyString_AS_STRING(result);
    outsize = 0;
    while (1) {
        Py_BEGIN_ALLOW_THREADS
        if (self->unconsumed_length == 0)
            // No remaining data
            res = LzmaDecode(&self->state, (unsigned char *)"", 0, &inProcessed,
                             tmp, avail_out, &outProcessed, 1);
        else {
            // Decompress remaining data
            res = LzmaDecode(&self->state, self->unconsumed_tail, self->unconsumed_length, &inProcessed,
                             tmp, avail_out, &outProcessed, 1);
            self->unconsumed_length -= inProcessed;
            if (self->unconsumed_length > 0)
                memcpy(self->unconsumed_tail, self->unconsumed_tail + inProcessed, self->unconsumed_length);
            else
                FREE_AND_NULL(self->unconsumed_tail);
        }
        Py_END_ALLOW_THREADS
        
        if (res != LZMA_RESULT_OK) {
            PyErr_SetString(PyExc_ValueError, "data error during decompression");
            DEC_AND_NULL(result);
            goto exit;
        }
        
        self->total_out += outProcessed;
        outsize += outProcessed;
        if (outProcessed < avail_out || (outProcessed == avail_out && self->max_length != -1))
            break;
        
        if (self->max_length != -1) {
            PyErr_SetString(PyExc_ValueError, "not enough input data for decompression");
            DEC_AND_NULL(result);
            goto exit;
        }
        
        avail_out -= outProcessed;
        
        // Output buffer is full, might be more data for decompression
        if (_PyString_Resize(&result, outsize+BLOCK_SIZE) != 0)
            goto exit;
        
        avail_out += BLOCK_SIZE;
        tmp = (unsigned char *)PyString_AS_STRING(result) + outsize;
    }
    
    if (outsize != PyString_GET_SIZE(result))
        _PyString_Resize(&result, outsize);
    
exit:
    return result;
}
コード例 #5
0
static PyObject *pylzma_decomp_decompress(CCompatDecompressionObject *self, PyObject *args)
{
    PyObject *result=NULL;
    char *data;
    PARSE_LENGTH_TYPE length, old_length;
    PY_LONG_LONG start_total_out;
    int res;
    PY_LONG_LONG max_length=BLOCK_SIZE;
    
    if (!PyArg_ParseTuple(args, "s#|L", &data, &length, &max_length))
        return NULL;

    if (max_length < 0)
    {
        PyErr_SetString(PyExc_ValueError, "bufsize must be greater than zero");
        return NULL;
    }
    
    start_total_out = self->stream.totalOut;
    if (self->unconsumed_length > 0) {
        self->unconsumed_tail = (char *)realloc(self->unconsumed_tail, self->unconsumed_length + length);
        self->stream.next_in = (Byte *)self->unconsumed_tail;
        memcpy(self->stream.next_in + self->unconsumed_length, data, length);
    } else
        self->stream.next_in = (Byte *)data;
    
    self->stream.avail_in = self->unconsumed_length + length;
    
    if (max_length && max_length < length)
        length = max_length;
    
    if (!(result = PyBytes_FromStringAndSize(NULL, length)))
        return NULL;
    
    self->stream.next_out = (unsigned char *) PyBytes_AS_STRING(result);
    self->stream.avail_out = length;
    
    Py_BEGIN_ALLOW_THREADS
    res = lzmaCompatDecode(&self->stream);
    Py_END_ALLOW_THREADS
    
    while (res == LZMA_OK && self->stream.avail_out == 0)
    {
        if (max_length && length >= max_length)
            break;
        
        old_length = length;
        length <<= 1;
        if (max_length && length > max_length)
            length = max_length;
        
        if (_PyBytes_Resize(&result, length) < 0)
            goto exit;
        
        self->stream.avail_out = length - old_length;
        self->stream.next_out = (Byte *) PyBytes_AS_STRING(result) + old_length;
        
        Py_BEGIN_ALLOW_THREADS
        res = lzmaCompatDecode(&self->stream);
        Py_END_ALLOW_THREADS
    }
        
    if (res == LZMA_NOT_ENOUGH_MEM) {
        // out of memory during decompression
        PyErr_NoMemory();
        DEC_AND_NULL(result);
        goto exit;
    } else if (res == LZMA_DATA_ERROR) {
        PyErr_SetString(PyExc_ValueError, "data error during decompression");
        DEC_AND_NULL(result);
        goto exit;
    } else if (res != LZMA_OK && res != LZMA_STREAM_END) {
        PyErr_Format(PyExc_ValueError, "unknown return code from lzmaDecode: %d", res);
        DEC_AND_NULL(result);
        goto exit;
    }

    /* Not all of the compressed data could be accomodated in the output buffer
    of specified size. Return the unconsumed tail in an attribute.*/
    if (max_length != 0) {
        if (self->stream.avail_in > 0)
        {
            if (self->stream.avail_in != self->unconsumed_length)
                self->unconsumed_tail = (char *)realloc(self->unconsumed_tail, self->stream.avail_in);
            
            if (!self->unconsumed_tail) {
                PyErr_NoMemory();
                DEC_AND_NULL(result);
                goto exit;
            }
            memcpy(self->unconsumed_tail, self->stream.next_in, self->stream.avail_in);
        } else
            FREE_AND_NULL(self->unconsumed_tail);
        self->unconsumed_length = self->stream.avail_in;
    }

    /* The end of the compressed data has been reached, so set the
       unused_data attribute to a string containing the remainder of the
       data in the string.  Note that this is also a logical place to call
       inflateEnd, but the old behaviour of only calling it on flush() is
       preserved.
    */
    if (res == LZMA_STREAM_END) {
        Py_XDECREF(self->unused_data);  /* Free original empty string */
        self->unused_data = PyBytes_FromStringAndSize((char *) self->stream.next_in, self->stream.avail_in);
        if (self->unused_data == NULL) {
            PyErr_NoMemory();
            DEC_AND_NULL(result);
            goto exit;
        }
    }
    
    _PyBytes_Resize(&result, self->stream.totalOut - start_total_out);
    
exit:
    return result;    
}
コード例 #6
0
static PyObject *
pylzma_decomp_decompress(CDecompressionObject *self, PyObject *args)
{
    PyObject *result=NULL;
    unsigned char *data;
    Byte *next_in, *next_out;
    int length, res, bufsize=BLOCK_SIZE;
    SizeT avail_in;
    SizeT inProcessed, outProcessed;
    ELzmaStatus status;
    
    if (!PyArg_ParseTuple(args, "s#|i", &data, &length, &bufsize)){
        return NULL;
    }

    if (bufsize <= 0) {
        PyErr_SetString(PyExc_ValueError, "bufsize must be greater than zero");
        return NULL;
    }
    
    if (self->unconsumed_length > 0) {
        self->unconsumed_tail = (unsigned char *) realloc(self->unconsumed_tail, self->unconsumed_length + length);
        next_in = (unsigned char *) self->unconsumed_tail;
        memcpy(next_in + self->unconsumed_length, data, length);
    } else {
        next_in = data;
    }
    
    if (self->need_properties) {
        if ((self->unconsumed_length + length) < LZMA_PROPS_SIZE) {
            // we need enough bytes to read the properties
            self->unconsumed_tail = (unsigned char *) realloc(self->unconsumed_tail, self->unconsumed_length + length);
            if (self->unconsumed_tail == NULL) {
                PyErr_NoMemory();
                return NULL;
            }
            memcpy(self->unconsumed_tail + self->unconsumed_length, data, length);
            self->unconsumed_length += length;
            return PyString_FromString("");
        }

        self->unconsumed_length += length;
        res = LzmaDec_Allocate(&self->state, next_in, LZMA_PROPS_SIZE, &allocator);
        if (res != SZ_OK) {
            PyErr_SetString(PyExc_TypeError, "Incorrect stream properties");
            return NULL;
        }
        
        next_in += LZMA_PROPS_SIZE;
        self->unconsumed_length -= LZMA_PROPS_SIZE;
        if (self->unconsumed_length > 0) {
            if (self->unconsumed_tail == NULL) {
                // No remaining data yet
                self->unconsumed_tail = (unsigned char *) malloc(self->unconsumed_length);
                if (self->unconsumed_tail == NULL) {
                    PyErr_NoMemory();
                    return NULL;
                }
                memcpy(self->unconsumed_tail, next_in, self->unconsumed_length);
                next_in = self->unconsumed_tail;
            } else {
                // Skip properties in remaining data
                memmove(self->unconsumed_tail, self->unconsumed_tail+LZMA_PROPS_SIZE, self->unconsumed_length);
                self->unconsumed_tail = next_in = (unsigned char *) realloc(self->unconsumed_tail, self->unconsumed_length);
                if (self->unconsumed_tail == NULL) {
                    PyErr_NoMemory();
                    return NULL;
                }
            }
        } else {
            FREE_AND_NULL(self->unconsumed_tail);
        }
        
        self->need_properties = 0;
        LzmaDec_Init(&self->state);
    } else {
        self->unconsumed_length += length;
    }
    avail_in = self->unconsumed_length;
    if (avail_in == 0) {
        // no more bytes to decompress
        return PyString_FromString("");
    }
    
    result = PyString_FromStringAndSize(NULL, bufsize);
    if (result == NULL) {
        PyErr_NoMemory();
        goto exit;
    }
    
    next_out = (unsigned char *) PyString_AS_STRING(result);
    Py_BEGIN_ALLOW_THREADS
    // Decompress until EOS marker is reached
    inProcessed = avail_in;
    outProcessed = bufsize;
    res = LzmaDec_DecodeToBuf(&self->state, next_out, &outProcessed,
                    next_in, &inProcessed, LZMA_FINISH_ANY, &status);
    Py_END_ALLOW_THREADS
    self->total_out += outProcessed;
    next_in += inProcessed;
    avail_in -= inProcessed;
    
    if (res != SZ_OK) {
        DEC_AND_NULL(result);
        PyErr_SetString(PyExc_ValueError, "data error during decompression");
        goto exit;
    }

    // Not all of the compressed data could be accomodated in the output buffer
    // of specified size. Return the unconsumed tail in an attribute.
    if (avail_in > 0) {
        if (self->unconsumed_tail == NULL) {
            // data are in "data"
            self->unconsumed_tail = (unsigned char *) malloc(avail_in);
            if (self->unconsumed_tail == NULL) {
                Py_DECREF(result);
                PyErr_NoMemory();
                goto exit;
            }
            memcpy(self->unconsumed_tail, next_in, avail_in);
        } else {
            memmove(self->unconsumed_tail, next_in, avail_in);
            self->unconsumed_tail = (unsigned char *) realloc(self->unconsumed_tail, avail_in);
        }
    } else {
        FREE_AND_NULL(self->unconsumed_tail);
    }
    
    self->unconsumed_length = avail_in;
    _PyString_Resize(&result, outProcessed);
    
exit:
    return result;
}
コード例 #7
0
static PyObject *
pylzma_decomp_flush(CDecompressionObject *self, PyObject *args)
{
    PyObject *result=NULL;
    int res;
    SizeT avail_out, outsize;
    unsigned char *tmp;
    SizeT inProcessed, outProcessed;
    ELzmaStatus status;
    
    if (self->max_length != -1) {
        avail_out = self->max_length - self->total_out;
    } else {
        avail_out = BLOCK_SIZE;
    }
    
    if (avail_out == 0) {
        // no more remaining data
        return PyString_FromString("");
    }
    
    result = PyString_FromStringAndSize(NULL, avail_out);
    if (result == NULL) {
        return NULL;
    }
    
    tmp = (unsigned char *)PyString_AS_STRING(result);
    outsize = 0;
    while (1) {
        Py_BEGIN_ALLOW_THREADS
        if (self->unconsumed_length == 0) {
            // No remaining data
            inProcessed = 0;
            outProcessed = avail_out;
            res = LzmaDec_DecodeToBuf(&self->state, tmp, &outProcessed,
                            (Byte *) "", &inProcessed, LZMA_FINISH_ANY, &status);
        } else {
            // Decompress remaining data
            inProcessed = self->unconsumed_length;
            outProcessed = avail_out;
            res = LzmaDec_DecodeToBuf(&self->state, tmp, &outProcessed,
                            self->unconsumed_tail, &inProcessed, LZMA_FINISH_ANY, &status);
            self->unconsumed_length -= inProcessed;
            if (self->unconsumed_length > 0)
                memmove(self->unconsumed_tail, self->unconsumed_tail + inProcessed, self->unconsumed_length);
            else
                FREE_AND_NULL(self->unconsumed_tail);
        }
        Py_END_ALLOW_THREADS
        
        if (res != SZ_OK) {
            PyErr_SetString(PyExc_ValueError, "data error during decompression");
            DEC_AND_NULL(result);
            goto exit;
        }
        
        if (!outProcessed && self->max_length != -1 && self->total_out < self->max_length) {
            PyErr_SetString(PyExc_ValueError, "data error during decompression");
            DEC_AND_NULL(result);
            goto exit;
        }
        
        self->total_out += outProcessed;
        outsize += outProcessed;
        if (outProcessed < avail_out || (outProcessed == avail_out && self->max_length != -1)) {
            break;
        }
        
        if (self->max_length != -1) {
            PyErr_SetString(PyExc_ValueError, "not enough input data for decompression");
            DEC_AND_NULL(result);
            goto exit;
        }
        
        avail_out -= outProcessed;
        
        // Output buffer is full, might be more data for decompression
        if (_PyString_Resize(&result, outsize+BLOCK_SIZE) != 0) {
            goto exit;
        }
        
        avail_out += BLOCK_SIZE;
        tmp = (unsigned char *)PyString_AS_STRING(result) + outsize;
    }
    
    if (outsize != PyString_GET_SIZE(result)) {
        _PyString_Resize(&result, outsize);
    }
    
exit:
    return result;
}