~ubuntu-branches/ubuntu/precise/python-lzma/precise

« back to all changes in this revision

Viewing changes to liblzma_compressobj.c

  • Committer: Bazaar Package Importer
  • Author(s): Richard Darst
  • Date: 2010-04-19 14:16:48 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100419141648-qwz3nm7shemqp37n
Tags: 0.5.3-1
* New upstream version
* Upgrade to 3.0 (quilt) just to be able to use .orig.tar.bz2
* Bump standards-version to 3.8.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include "liblzma_compressobj.h"
2
 
#include "liblzma_options.h"
3
 
#include "liblzma_util.h"
4
 
 
5
 
PyDoc_STRVAR(LZMAComp_compress__doc__,
6
 
"compress(data) -> string\n\
7
 
\n\
8
 
Feed the compressor object with data to compress sequently.\n\
9
 
This function will return the header for the compressed string for the first\n\
10
 
input provided, this header will be needed to concatenate with the rest of\n\
11
 
the stream when flushing to have a proper stream able to be decompressed\n\
12
 
again.\n");
13
 
 
14
 
static PyObject *
15
 
LZMAComp_compress(LZMACompObject *self, PyObject *args)
16
 
{
17
 
        Py_buffer pdata;
18
 
        Py_ssize_t datasize, bufsize = SMALLCHUNK;
19
 
        uint8_t *data;
20
 
        uint64_t start_total_out;
21
 
        PyObject *ret = NULL;
22
 
        lzma_stream *lzus = &self->lzus;
23
 
        lzma_ret lzuerror;
24
 
 
25
 
        INITCHECK
26
 
        if (!PyArg_ParseTuple(args, "s*:compress", &pdata))
27
 
                return NULL;
28
 
        data = pdata.buf;
29
 
        datasize = pdata.len;
30
 
 
31
 
        ACQUIRE_LOCK(self);
32
 
        if (!self->running) {
33
 
                PyErr_SetString(PyExc_ValueError,
34
 
                                "this object was already flushed");
35
 
                goto error;
36
 
        }
37
 
 
38
 
        if (!(ret = PyString_FromStringAndSize(NULL, bufsize)))
39
 
                goto error;
40
 
 
41
 
        start_total_out = lzus->total_out;
42
 
        lzus->avail_in = (size_t)datasize;
43
 
        lzus->next_in = data;
44
 
        lzus->avail_out = (size_t)bufsize;
45
 
        lzus->next_out = (uint8_t *)PyString_AS_STRING(ret);
46
 
 
47
 
        for (;;) {
48
 
                Py_BEGIN_ALLOW_THREADS
49
 
                lzuerror = lzma_code(lzus, LZMA_RUN);
50
 
                Py_END_ALLOW_THREADS
51
 
                if (lzus->avail_in == 0 || lzus->avail_out != 0)
52
 
                        break;
53
 
                if (_PyString_Resize(&ret, bufsize << 1) < 0)
54
 
                        goto error;
55
 
                lzus->next_out = (uint8_t *)PyString_AS_STRING(ret) + datasize;
56
 
                lzus->avail_out = (size_t)bufsize;
57
 
                bufsize =  bufsize << 1;
58
 
                if(!Util_CatchLZMAError(lzuerror, lzus, true))
59
 
                        goto error;
60
 
        }
61
 
 
62
 
        _PyString_Resize(&ret, (Py_ssize_t)lzus->total_out - (Py_ssize_t)start_total_out);
63
 
 
64
 
        RELEASE_LOCK(self);
65
 
        PyBuffer_Release(&pdata);
66
 
        return ret;
67
 
 
68
 
 error:
69
 
        RELEASE_LOCK(self);
70
 
        PyBuffer_Release(&pdata);
71
 
        Py_XDECREF(ret);
72
 
        return NULL;
73
 
}
74
 
 
75
 
PyDoc_STRVAR(LZMAComp_flush__doc__,
76
 
"flush( [mode] ) -> string\n\
77
 
\n\
78
 
Returns a string containing any remaining compressed data.\n\
79
 
\n\
80
 
'mode' can be one of the constants LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, LZMA_FINISH; the\n\
81
 
default value used when mode is not specified is LZMA_FINISH.\n\
82
 
If mode == LZMA_FINISH, the compressor object can no longer be used after\n\
83
 
calling the flush() method.  Otherwise, more data can still be compressed.\n");
84
 
 
85
 
static PyObject *
86
 
LZMAComp_flush(LZMACompObject *self, PyObject *args)
87
 
{
88
 
        Py_ssize_t bufsize = SMALLCHUNK;
89
 
        PyObject *ret = NULL;
90
 
        lzma_action flushmode = LZMA_FINISH;
91
 
        uint64_t start_total_out;
92
 
        lzma_stream *lzus = &self->lzus;
93
 
        lzma_ret lzuerror;
94
 
 
95
 
        INITCHECK
96
 
        if (!PyArg_ParseTuple(args, "|i:flush", &flushmode))
97
 
                return NULL;
98
 
 
99
 
        ACQUIRE_LOCK(self);
100
 
        if (!self->running) {
101
 
                PyErr_SetString(PyExc_ValueError, "object was already flushed");
102
 
                goto error;
103
 
        }
104
 
 
105
 
        switch(flushmode){
106
 
                case(LZMA_SYNC_FLUSH):
107
 
                case(LZMA_FULL_FLUSH):
108
 
                        if(self->filters[0].id == LZMA_FILTER_LZMA1) {
109
 
                                PyErr_Format(LZMAError, "%d is not supported as flush mode for LZMA_Alone format", flushmode);
110
 
                                goto error;
111
 
                        }
112
 
                /* Flushing with LZMA_RUN is a no-op, so there's no point in
113
 
                 * doing any work at all; just return an empty string.
114
 
                 */
115
 
                case(LZMA_RUN):
116
 
                        ret = PyString_FromStringAndSize(NULL, 0);
117
 
                        goto error;
118
 
                case(LZMA_FINISH):
119
 
                        break;
120
 
                default:
121
 
                        PyErr_Format(LZMAError, "Invalid flush mode: %d", flushmode);
122
 
                        goto error;
123
 
        }
124
 
 
125
 
        self->running = false;
126
 
        if (!(ret = PyString_FromStringAndSize(NULL, bufsize)))
127
 
                goto error;
128
 
        
129
 
        start_total_out = lzus->total_out;
130
 
        lzus->avail_in = 0;
131
 
        lzus->avail_out = (size_t)bufsize;
132
 
        lzus->next_out = (uint8_t *)PyString_AS_STRING(ret);
133
 
 
134
 
        for (;;) {
135
 
                Py_BEGIN_ALLOW_THREADS
136
 
                lzuerror = lzma_code(lzus, flushmode);
137
 
                Py_END_ALLOW_THREADS
138
 
                if (lzus->avail_in == 0 || lzus->avail_out != 0)
139
 
                        break;
140
 
                if (_PyString_Resize(&ret, bufsize << 1) < 0)
141
 
                        goto error;
142
 
                lzus->next_out = (uint8_t *)PyString_AS_STRING(ret) + bufsize;
143
 
                lzus->avail_out = (size_t)bufsize;
144
 
                bufsize = bufsize << 1;
145
 
                if(!Util_CatchLZMAError(lzuerror, lzus, true))
146
 
                        goto error;
147
 
        }
148
 
 
149
 
        _PyString_Resize(&ret, (Py_ssize_t)self->lzus.total_out - (Py_ssize_t)start_total_out);
150
 
 
151
 
        RELEASE_LOCK(self);
152
 
        return ret;
153
 
 
154
 
error:
155
 
        RELEASE_LOCK(self);
156
 
        Py_XDECREF(ret);
157
 
    return ret;
158
 
}
159
 
 
160
 
PyDoc_STRVAR(LZMAComp_reset__doc__,
161
 
"reset(["DEFAULT_OPTIONS_STRING"]) -> None\n\
162
 
\n\
163
 
Resets the compression object keeping the compression settings.\n\
164
 
These existing settings can be overriden by providing\n\
165
 
keyword settings.");
166
 
 
167
 
static PyObject *
168
 
LZMAComp_reset(LZMACompObject *self, PyObject *args, PyObject *kwargs)
169
 
{
170
 
        PyObject *result = NULL, *options_dict = NULL;
171
 
        lzma_stream *lzus = &self->lzus;
172
 
        lzma_ret lzuerror = LZMA_OK;
173
 
 
174
 
        static char *kwlist[] = {"options", NULL};
175
 
 
176
 
        INITCHECK
177
 
        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:reset", kwlist,
178
 
                                &options_dict))
179
 
                goto error;
180
 
        
181
 
        if(!init_lzma_options("reset", options_dict, self->filters))
182
 
                goto error;
183
 
 
184
 
        self->lzma_options = LZMA_options_get(self->filters[0]);
185
 
 
186
 
 
187
 
        ACQUIRE_LOCK(self);
188
 
        if (self->running)
189
 
                lzma_end(lzus);
190
 
        
191
 
        if(self->filters[0].id == LZMA_FILTER_LZMA2)
192
 
                lzuerror = lzma_stream_encoder(lzus, self->filters, self->filters[LZMA_FILTERS_MAX + 1].id);
193
 
        else if(self->filters[0].id == LZMA_FILTER_LZMA1)
194
 
                lzuerror = lzma_alone_encoder(lzus, self->filters[0].options);
195
 
 
196
 
        if(!Util_CatchLZMAError(lzuerror, lzus, true))
197
 
                goto error;
198
 
        self->running = true;
199
 
 
200
 
        result = Py_None;
201
 
 error:
202
 
        RELEASE_LOCK(self);
203
 
        Py_XINCREF(result);
204
 
        return result;
205
 
}
206
 
 
207
 
PyDoc_STRVAR(LZMAComp_lzma_options__doc__,
208
 
"Dictionary containing the lzma encoder options.");
209
 
 
210
 
static PyMemberDef LZMAComp_members[] = {
211
 
        {"lzma_options", T_OBJECT, offsetof(LZMACompObject, lzma_options),
212
 
                RO, LZMAComp_lzma_options__doc__},
213
 
        {NULL, 0, 0, 0, NULL}   /* Sentinel */
214
 
};
215
 
 
216
 
static PyMethodDef LZMAComp_methods[] =
217
 
{
218
 
        {"compress", (PyCFunction)LZMAComp_compress, METH_VARARGS,
219
 
                LZMAComp_compress__doc__},
220
 
        {"flush", (PyCFunction)LZMAComp_flush, METH_VARARGS,
221
 
                LZMAComp_flush__doc__},
222
 
        {"reset", (PyCFunction)LZMAComp_reset, METH_VARARGS | METH_KEYWORDS,
223
 
                LZMAComp_reset__doc__},
224
 
        {0, 0, 0, 0}
225
 
};
226
 
 
227
 
static int
228
 
LZMAComp_init(LZMACompObject *self, PyObject *args, PyObject *kwargs)
229
 
{
230
 
        PyObject *options_dict = NULL;
231
 
        lzma_stream *lzus = &self->lzus;
232
 
        lzma_ret lzuerror = LZMA_OK;
233
 
 
234
 
        static char *kwlist[] = {"options", NULL};
235
 
 
236
 
        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:LZMACompressor", kwlist,
237
 
                                &options_dict))
238
 
                return -1;
239
 
        
240
 
        if(!init_lzma_options("LZMACompressor", options_dict, self->filters))
241
 
                goto error;
242
 
 
243
 
        self->lzma_options = LZMA_options_get(self->filters[0]);
244
 
 
245
 
#ifdef WITH_THREAD
246
 
        self->lock = PyThread_allocate_lock();
247
 
        if (!self->lock) {
248
 
                PyErr_SetString(PyExc_MemoryError, "unable to allocate lock");
249
 
                goto error;
250
 
        }
251
 
#endif
252
 
 
253
 
        if(self->filters[0].id == LZMA_FILTER_LZMA2)
254
 
                lzuerror = lzma_stream_encoder(lzus, self->filters, self->filters[LZMA_FILTERS_MAX + 1].id);
255
 
        else if(self->filters[0].id == LZMA_FILTER_LZMA1)
256
 
                lzuerror = lzma_alone_encoder(lzus, self->filters[0].options);
257
 
 
258
 
        if(!Util_CatchLZMAError(lzuerror, lzus, true))
259
 
                goto error;
260
 
 
261
 
        self->is_initialised = true;
262
 
        self->running = true;   
263
 
 
264
 
        return 0;
265
 
 
266
 
 error:
267
 
#ifdef WITH_THREAD
268
 
        if (self->lock) {
269
 
                PyThread_free_lock(self->lock);
270
 
                self->lock = NULL;
271
 
        }
272
 
#endif
273
 
        return -1;
274
 
}
275
 
 
276
 
static PyObject *
277
 
LZMACompObject_new(PyTypeObject *type, __attribute__((unused)) PyObject *args, __attribute__((unused)) PyObject *kwargs)
278
 
{
279
 
        LZMACompObject *self;
280
 
        self = (LZMACompObject *)type->tp_alloc(type, 0);
281
 
        if (self != NULL){
282
 
                self->is_initialised = false;
283
 
                self->running = false;
284
 
                lzma_stream tmp = LZMA_STREAM_INIT;
285
 
                self->lzus = tmp;
286
 
                self->filters[0].options = &self->options;
287
 
        }
288
 
        else
289
 
                return NULL;
290
 
 
291
 
        return (PyObject *)self;
292
 
}
293
 
 
294
 
static void
295
 
LZMAComp_dealloc(LZMACompObject *self)
296
 
{
297
 
#ifdef WITH_THREAD
298
 
        if (self->lock)
299
 
                PyThread_free_lock(self->lock);
300
 
#endif
301
 
        if (self->is_initialised)
302
 
                lzma_end(&self->lzus);
303
 
        Py_XDECREF(self->lzma_options);
304
 
        Py_TYPE(self)->tp_free((PyObject *)self);
305
 
}
306
 
 
307
 
PyDoc_STRVAR(LZMAComp__doc__,
308
 
"LZMACompressor(["DEFAULT_OPTIONS_STRING"]) -> compressor object\n\
309
 
Create a new compressor object. This object may be used to compress\n\
310
 
data sequentially. If you want to compress data in one shot, use the\n\
311
 
compress() function instead.\n");
312
 
 
313
 
PyTypeObject LZMAComp_Type = {
314
 
        PyObject_HEAD_INIT(NULL)
315
 
        0,                                              /*ob_size*/
316
 
        "lzma.LZMACompressor",                          /*tp_name*/
317
 
        sizeof(LZMACompObject),                         /*tp_basicsize*/
318
 
        0,                                              /*tp_itemsize*/
319
 
        (destructor)LZMAComp_dealloc,                   /*tp_dealloc*/
320
 
        0,                                              /*tp_print*/
321
 
        0,                                              /*tp_getattr*/
322
 
        0,                                              /*tp_setattr*/
323
 
        0,                                              /*tp_compare*/
324
 
        0,                                              /*tp_repr*/
325
 
        0,                                              /*tp_as_number*/
326
 
        0,                                              /*tp_as_sequence*/
327
 
        0,                                              /*tp_as_mapping*/
328
 
        0,                                              /*tp_hash*/
329
 
        0,                                              /*tp_call*/
330
 
        0,                                              /*tp_str*/
331
 
        PyObject_GenericGetAttr,                        /*tp_getattro*/
332
 
        PyObject_GenericSetAttr,                        /*tp_setattro*/
333
 
        0,                                              /*tp_as_buffer*/
334
 
        Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,         /*tp_flags*/
335
 
        LZMAComp__doc__,                                /*tp_doc*/
336
 
        0,                                              /*tp_traverse*/
337
 
        0,                                              /*tp_clear*/
338
 
        0,                                              /*tp_richcompare*/
339
 
        0,                                              /*tp_weaklistoffset*/
340
 
        0,                                              /*tp_iter*/
341
 
        0,                                              /*tp_iternext*/
342
 
        LZMAComp_methods,                               /*tp_methods*/
343
 
        LZMAComp_members,                               /*tp_members*/
344
 
        0,                                              /*tp_getset*/
345
 
        0,                                              /*tp_base*/
346
 
        0,                                              /*tp_dict*/
347
 
        0,                                              /*tp_descr_get*/
348
 
        0,                                              /*tp_descr_set*/
349
 
        0,                                              /*tp_dictoffset*/
350
 
        (initproc)LZMAComp_init,                        /*tp_init*/
351
 
        PyType_GenericAlloc,                            /*tp_alloc*/
352
 
        LZMACompObject_new,                             /*tp_new*/
353
 
        _PyObject_Del,                                  /*tp_free*/
354
 
        0,                                              /*tp_is_gc*/
355
 
        0,                                              /*tp_bases*/
356
 
        0,                                              /*tp_mro*/
357
 
        0,                                              /*tp_cache*/
358
 
        0,                                              /*tp_subclasses*/
359
 
        0,                                              /*tp_weaklist*/
360
 
        0,                                              /*tp_del*/
361
 
        0                                               /*tp_version_tag*/
362
 
};