17db96d56Sopenharmony_ci/* _lzma - Low-level Python interface to liblzma. 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ci Initial implementation by Per Øyvind Karlsen. 47db96d56Sopenharmony_ci Rewritten by Nadeem Vawda. 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ci*/ 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ci#define PY_SSIZE_T_CLEAN 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci#include "Python.h" 117db96d56Sopenharmony_ci#include "structmember.h" // PyMemberDef 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci#include <stdlib.h> // free() 147db96d56Sopenharmony_ci#include <string.h> 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci#include <lzma.h> 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ci// Blocks output buffer wrappers 197db96d56Sopenharmony_ci#include "pycore_blocks_output_buffer.h" 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci#if OUTPUT_BUFFER_MAX_BLOCK_SIZE > SIZE_MAX 227db96d56Sopenharmony_ci #error "The maximum block size accepted by liblzma is SIZE_MAX." 237db96d56Sopenharmony_ci#endif 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci/* On success, return value >= 0 267db96d56Sopenharmony_ci On failure, return -1 */ 277db96d56Sopenharmony_cistatic inline Py_ssize_t 287db96d56Sopenharmony_ciOutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, Py_ssize_t max_length, 297db96d56Sopenharmony_ci uint8_t **next_out, size_t *avail_out) 307db96d56Sopenharmony_ci{ 317db96d56Sopenharmony_ci Py_ssize_t allocated; 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci allocated = _BlocksOutputBuffer_InitAndGrow( 347db96d56Sopenharmony_ci buffer, max_length, (void**) next_out); 357db96d56Sopenharmony_ci *avail_out = (size_t) allocated; 367db96d56Sopenharmony_ci return allocated; 377db96d56Sopenharmony_ci} 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci/* On success, return value >= 0 407db96d56Sopenharmony_ci On failure, return -1 */ 417db96d56Sopenharmony_cistatic inline Py_ssize_t 427db96d56Sopenharmony_ciOutputBuffer_Grow(_BlocksOutputBuffer *buffer, 437db96d56Sopenharmony_ci uint8_t **next_out, size_t *avail_out) 447db96d56Sopenharmony_ci{ 457db96d56Sopenharmony_ci Py_ssize_t allocated; 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci allocated = _BlocksOutputBuffer_Grow( 487db96d56Sopenharmony_ci buffer, (void**) next_out, (Py_ssize_t) *avail_out); 497db96d56Sopenharmony_ci *avail_out = (size_t) allocated; 507db96d56Sopenharmony_ci return allocated; 517db96d56Sopenharmony_ci} 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_cistatic inline Py_ssize_t 547db96d56Sopenharmony_ciOutputBuffer_GetDataSize(_BlocksOutputBuffer *buffer, size_t avail_out) 557db96d56Sopenharmony_ci{ 567db96d56Sopenharmony_ci return _BlocksOutputBuffer_GetDataSize(buffer, (Py_ssize_t) avail_out); 577db96d56Sopenharmony_ci} 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_cistatic inline PyObject * 607db96d56Sopenharmony_ciOutputBuffer_Finish(_BlocksOutputBuffer *buffer, size_t avail_out) 617db96d56Sopenharmony_ci{ 627db96d56Sopenharmony_ci return _BlocksOutputBuffer_Finish(buffer, (Py_ssize_t) avail_out); 637db96d56Sopenharmony_ci} 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_cistatic inline void 667db96d56Sopenharmony_ciOutputBuffer_OnError(_BlocksOutputBuffer *buffer) 677db96d56Sopenharmony_ci{ 687db96d56Sopenharmony_ci _BlocksOutputBuffer_OnError(buffer); 697db96d56Sopenharmony_ci} 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ci#define ACQUIRE_LOCK(obj) do { \ 737db96d56Sopenharmony_ci if (!PyThread_acquire_lock((obj)->lock, 0)) { \ 747db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS \ 757db96d56Sopenharmony_ci PyThread_acquire_lock((obj)->lock, 1); \ 767db96d56Sopenharmony_ci Py_END_ALLOW_THREADS \ 777db96d56Sopenharmony_ci } } while (0) 787db96d56Sopenharmony_ci#define RELEASE_LOCK(obj) PyThread_release_lock((obj)->lock) 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_citypedef struct { 817db96d56Sopenharmony_ci PyTypeObject *lzma_compressor_type; 827db96d56Sopenharmony_ci PyTypeObject *lzma_decompressor_type; 837db96d56Sopenharmony_ci PyObject *error; 847db96d56Sopenharmony_ci PyObject *empty_tuple; 857db96d56Sopenharmony_ci} _lzma_state; 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_cistatic inline _lzma_state* 887db96d56Sopenharmony_ciget_lzma_state(PyObject *module) 897db96d56Sopenharmony_ci{ 907db96d56Sopenharmony_ci void *state = PyModule_GetState(module); 917db96d56Sopenharmony_ci assert(state != NULL); 927db96d56Sopenharmony_ci return (_lzma_state *)state; 937db96d56Sopenharmony_ci} 947db96d56Sopenharmony_ci 957db96d56Sopenharmony_ci/* Container formats: */ 967db96d56Sopenharmony_cienum { 977db96d56Sopenharmony_ci FORMAT_AUTO, 987db96d56Sopenharmony_ci FORMAT_XZ, 997db96d56Sopenharmony_ci FORMAT_ALONE, 1007db96d56Sopenharmony_ci FORMAT_RAW, 1017db96d56Sopenharmony_ci}; 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci#define LZMA_CHECK_UNKNOWN (LZMA_CHECK_ID_MAX + 1) 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_citypedef struct { 1077db96d56Sopenharmony_ci PyObject_HEAD 1087db96d56Sopenharmony_ci lzma_allocator alloc; 1097db96d56Sopenharmony_ci lzma_stream lzs; 1107db96d56Sopenharmony_ci int flushed; 1117db96d56Sopenharmony_ci PyThread_type_lock lock; 1127db96d56Sopenharmony_ci} Compressor; 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_citypedef struct { 1157db96d56Sopenharmony_ci PyObject_HEAD 1167db96d56Sopenharmony_ci lzma_allocator alloc; 1177db96d56Sopenharmony_ci lzma_stream lzs; 1187db96d56Sopenharmony_ci int check; 1197db96d56Sopenharmony_ci char eof; 1207db96d56Sopenharmony_ci PyObject *unused_data; 1217db96d56Sopenharmony_ci char needs_input; 1227db96d56Sopenharmony_ci uint8_t *input_buffer; 1237db96d56Sopenharmony_ci size_t input_buffer_size; 1247db96d56Sopenharmony_ci PyThread_type_lock lock; 1257db96d56Sopenharmony_ci} Decompressor; 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_ci/* Helper functions. */ 1287db96d56Sopenharmony_ci 1297db96d56Sopenharmony_cistatic int 1307db96d56Sopenharmony_cicatch_lzma_error(_lzma_state *state, lzma_ret lzret) 1317db96d56Sopenharmony_ci{ 1327db96d56Sopenharmony_ci switch (lzret) { 1337db96d56Sopenharmony_ci case LZMA_OK: 1347db96d56Sopenharmony_ci case LZMA_GET_CHECK: 1357db96d56Sopenharmony_ci case LZMA_NO_CHECK: 1367db96d56Sopenharmony_ci case LZMA_STREAM_END: 1377db96d56Sopenharmony_ci return 0; 1387db96d56Sopenharmony_ci case LZMA_UNSUPPORTED_CHECK: 1397db96d56Sopenharmony_ci PyErr_SetString(state->error, "Unsupported integrity check"); 1407db96d56Sopenharmony_ci return 1; 1417db96d56Sopenharmony_ci case LZMA_MEM_ERROR: 1427db96d56Sopenharmony_ci PyErr_NoMemory(); 1437db96d56Sopenharmony_ci return 1; 1447db96d56Sopenharmony_ci case LZMA_MEMLIMIT_ERROR: 1457db96d56Sopenharmony_ci PyErr_SetString(state->error, "Memory usage limit exceeded"); 1467db96d56Sopenharmony_ci return 1; 1477db96d56Sopenharmony_ci case LZMA_FORMAT_ERROR: 1487db96d56Sopenharmony_ci PyErr_SetString(state->error, "Input format not supported by decoder"); 1497db96d56Sopenharmony_ci return 1; 1507db96d56Sopenharmony_ci case LZMA_OPTIONS_ERROR: 1517db96d56Sopenharmony_ci PyErr_SetString(state->error, "Invalid or unsupported options"); 1527db96d56Sopenharmony_ci return 1; 1537db96d56Sopenharmony_ci case LZMA_DATA_ERROR: 1547db96d56Sopenharmony_ci PyErr_SetString(state->error, "Corrupt input data"); 1557db96d56Sopenharmony_ci return 1; 1567db96d56Sopenharmony_ci case LZMA_BUF_ERROR: 1577db96d56Sopenharmony_ci PyErr_SetString(state->error, "Insufficient buffer space"); 1587db96d56Sopenharmony_ci return 1; 1597db96d56Sopenharmony_ci case LZMA_PROG_ERROR: 1607db96d56Sopenharmony_ci PyErr_SetString(state->error, "Internal error"); 1617db96d56Sopenharmony_ci return 1; 1627db96d56Sopenharmony_ci default: 1637db96d56Sopenharmony_ci PyErr_Format(state->error, "Unrecognized error from liblzma: %d", lzret); 1647db96d56Sopenharmony_ci return 1; 1657db96d56Sopenharmony_ci } 1667db96d56Sopenharmony_ci} 1677db96d56Sopenharmony_ci 1687db96d56Sopenharmony_cistatic void* 1697db96d56Sopenharmony_ciPyLzma_Malloc(void *opaque, size_t items, size_t size) 1707db96d56Sopenharmony_ci{ 1717db96d56Sopenharmony_ci if (size != 0 && items > (size_t)PY_SSIZE_T_MAX / size) { 1727db96d56Sopenharmony_ci return NULL; 1737db96d56Sopenharmony_ci } 1747db96d56Sopenharmony_ci /* PyMem_Malloc() cannot be used: 1757db96d56Sopenharmony_ci the GIL is not held when lzma_code() is called */ 1767db96d56Sopenharmony_ci return PyMem_RawMalloc(items * size); 1777db96d56Sopenharmony_ci} 1787db96d56Sopenharmony_ci 1797db96d56Sopenharmony_cistatic void 1807db96d56Sopenharmony_ciPyLzma_Free(void *opaque, void *ptr) 1817db96d56Sopenharmony_ci{ 1827db96d56Sopenharmony_ci PyMem_RawFree(ptr); 1837db96d56Sopenharmony_ci} 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_ci/* Some custom type conversions for PyArg_ParseTupleAndKeywords(), 1877db96d56Sopenharmony_ci since the predefined conversion specifiers do not suit our needs: 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci uint32_t - the "I" (unsigned int) specifier is the right size, but 1907db96d56Sopenharmony_ci silently ignores overflows on conversion. 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_ci lzma_vli - the "K" (unsigned long long) specifier is the right 1937db96d56Sopenharmony_ci size, but like "I" it silently ignores overflows on conversion. 1947db96d56Sopenharmony_ci 1957db96d56Sopenharmony_ci lzma_mode and lzma_match_finder - these are enumeration types, and 1967db96d56Sopenharmony_ci so the size of each is implementation-defined. Worse, different 1977db96d56Sopenharmony_ci enum types can be of different sizes within the same program, so 1987db96d56Sopenharmony_ci to be strictly correct, we need to define two separate converters. 1997db96d56Sopenharmony_ci */ 2007db96d56Sopenharmony_ci 2017db96d56Sopenharmony_ci#define INT_TYPE_CONVERTER_FUNC(TYPE, FUNCNAME) \ 2027db96d56Sopenharmony_ci static int \ 2037db96d56Sopenharmony_ci FUNCNAME(PyObject *obj, void *ptr) \ 2047db96d56Sopenharmony_ci { \ 2057db96d56Sopenharmony_ci unsigned long long val; \ 2067db96d56Sopenharmony_ci \ 2077db96d56Sopenharmony_ci val = PyLong_AsUnsignedLongLong(obj); \ 2087db96d56Sopenharmony_ci if (PyErr_Occurred()) \ 2097db96d56Sopenharmony_ci return 0; \ 2107db96d56Sopenharmony_ci if ((unsigned long long)(TYPE)val != val) { \ 2117db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, \ 2127db96d56Sopenharmony_ci "Value too large for " #TYPE " type"); \ 2137db96d56Sopenharmony_ci return 0; \ 2147db96d56Sopenharmony_ci } \ 2157db96d56Sopenharmony_ci *(TYPE *)ptr = (TYPE)val; \ 2167db96d56Sopenharmony_ci return 1; \ 2177db96d56Sopenharmony_ci } 2187db96d56Sopenharmony_ci 2197db96d56Sopenharmony_ciINT_TYPE_CONVERTER_FUNC(uint32_t, uint32_converter) 2207db96d56Sopenharmony_ciINT_TYPE_CONVERTER_FUNC(lzma_vli, lzma_vli_converter) 2217db96d56Sopenharmony_ciINT_TYPE_CONVERTER_FUNC(lzma_mode, lzma_mode_converter) 2227db96d56Sopenharmony_ciINT_TYPE_CONVERTER_FUNC(lzma_match_finder, lzma_mf_converter) 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ci#undef INT_TYPE_CONVERTER_FUNC 2257db96d56Sopenharmony_ci 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci/* Filter specifier parsing. 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci This code handles converting filter specifiers (Python dicts) into 2307db96d56Sopenharmony_ci the C lzma_filter structs expected by liblzma. */ 2317db96d56Sopenharmony_ci 2327db96d56Sopenharmony_cistatic void * 2337db96d56Sopenharmony_ciparse_filter_spec_lzma(_lzma_state *state, PyObject *spec) 2347db96d56Sopenharmony_ci{ 2357db96d56Sopenharmony_ci static char *optnames[] = {"id", "preset", "dict_size", "lc", "lp", 2367db96d56Sopenharmony_ci "pb", "mode", "nice_len", "mf", "depth", NULL}; 2377db96d56Sopenharmony_ci PyObject *id; 2387db96d56Sopenharmony_ci PyObject *preset_obj; 2397db96d56Sopenharmony_ci uint32_t preset = LZMA_PRESET_DEFAULT; 2407db96d56Sopenharmony_ci lzma_options_lzma *options; 2417db96d56Sopenharmony_ci 2427db96d56Sopenharmony_ci /* First, fill in default values for all the options using a preset. 2437db96d56Sopenharmony_ci Then, override the defaults with any values given by the caller. */ 2447db96d56Sopenharmony_ci 2457db96d56Sopenharmony_ci preset_obj = PyMapping_GetItemString(spec, "preset"); 2467db96d56Sopenharmony_ci if (preset_obj == NULL) { 2477db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_KeyError)) { 2487db96d56Sopenharmony_ci PyErr_Clear(); 2497db96d56Sopenharmony_ci } 2507db96d56Sopenharmony_ci else { 2517db96d56Sopenharmony_ci return NULL; 2527db96d56Sopenharmony_ci } 2537db96d56Sopenharmony_ci } else { 2547db96d56Sopenharmony_ci int ok = uint32_converter(preset_obj, &preset); 2557db96d56Sopenharmony_ci Py_DECREF(preset_obj); 2567db96d56Sopenharmony_ci if (!ok) { 2577db96d56Sopenharmony_ci return NULL; 2587db96d56Sopenharmony_ci } 2597db96d56Sopenharmony_ci } 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ci options = (lzma_options_lzma *)PyMem_Calloc(1, sizeof *options); 2627db96d56Sopenharmony_ci if (options == NULL) { 2637db96d56Sopenharmony_ci return PyErr_NoMemory(); 2647db96d56Sopenharmony_ci } 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_ci if (lzma_lzma_preset(options, preset)) { 2677db96d56Sopenharmony_ci PyMem_Free(options); 2687db96d56Sopenharmony_ci PyErr_Format(state->error, "Invalid compression preset: %u", preset); 2697db96d56Sopenharmony_ci return NULL; 2707db96d56Sopenharmony_ci } 2717db96d56Sopenharmony_ci 2727db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(state->empty_tuple, spec, 2737db96d56Sopenharmony_ci "|OOO&O&O&O&O&O&O&O&", optnames, 2747db96d56Sopenharmony_ci &id, &preset_obj, 2757db96d56Sopenharmony_ci uint32_converter, &options->dict_size, 2767db96d56Sopenharmony_ci uint32_converter, &options->lc, 2777db96d56Sopenharmony_ci uint32_converter, &options->lp, 2787db96d56Sopenharmony_ci uint32_converter, &options->pb, 2797db96d56Sopenharmony_ci lzma_mode_converter, &options->mode, 2807db96d56Sopenharmony_ci uint32_converter, &options->nice_len, 2817db96d56Sopenharmony_ci lzma_mf_converter, &options->mf, 2827db96d56Sopenharmony_ci uint32_converter, &options->depth)) { 2837db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 2847db96d56Sopenharmony_ci "Invalid filter specifier for LZMA filter"); 2857db96d56Sopenharmony_ci PyMem_Free(options); 2867db96d56Sopenharmony_ci return NULL; 2877db96d56Sopenharmony_ci } 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_ci return options; 2907db96d56Sopenharmony_ci} 2917db96d56Sopenharmony_ci 2927db96d56Sopenharmony_cistatic void * 2937db96d56Sopenharmony_ciparse_filter_spec_delta(_lzma_state *state, PyObject *spec) 2947db96d56Sopenharmony_ci{ 2957db96d56Sopenharmony_ci static char *optnames[] = {"id", "dist", NULL}; 2967db96d56Sopenharmony_ci PyObject *id; 2977db96d56Sopenharmony_ci uint32_t dist = 1; 2987db96d56Sopenharmony_ci lzma_options_delta *options; 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(state->empty_tuple, spec, "|OO&", optnames, 3017db96d56Sopenharmony_ci &id, uint32_converter, &dist)) { 3027db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 3037db96d56Sopenharmony_ci "Invalid filter specifier for delta filter"); 3047db96d56Sopenharmony_ci return NULL; 3057db96d56Sopenharmony_ci } 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci options = (lzma_options_delta *)PyMem_Calloc(1, sizeof *options); 3087db96d56Sopenharmony_ci if (options == NULL) { 3097db96d56Sopenharmony_ci return PyErr_NoMemory(); 3107db96d56Sopenharmony_ci } 3117db96d56Sopenharmony_ci options->type = LZMA_DELTA_TYPE_BYTE; 3127db96d56Sopenharmony_ci options->dist = dist; 3137db96d56Sopenharmony_ci return options; 3147db96d56Sopenharmony_ci} 3157db96d56Sopenharmony_ci 3167db96d56Sopenharmony_cistatic void * 3177db96d56Sopenharmony_ciparse_filter_spec_bcj(_lzma_state *state, PyObject *spec) 3187db96d56Sopenharmony_ci{ 3197db96d56Sopenharmony_ci static char *optnames[] = {"id", "start_offset", NULL}; 3207db96d56Sopenharmony_ci PyObject *id; 3217db96d56Sopenharmony_ci uint32_t start_offset = 0; 3227db96d56Sopenharmony_ci lzma_options_bcj *options; 3237db96d56Sopenharmony_ci 3247db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(state->empty_tuple, spec, "|OO&", optnames, 3257db96d56Sopenharmony_ci &id, uint32_converter, &start_offset)) { 3267db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 3277db96d56Sopenharmony_ci "Invalid filter specifier for BCJ filter"); 3287db96d56Sopenharmony_ci return NULL; 3297db96d56Sopenharmony_ci } 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ci options = (lzma_options_bcj *)PyMem_Calloc(1, sizeof *options); 3327db96d56Sopenharmony_ci if (options == NULL) { 3337db96d56Sopenharmony_ci return PyErr_NoMemory(); 3347db96d56Sopenharmony_ci } 3357db96d56Sopenharmony_ci options->start_offset = start_offset; 3367db96d56Sopenharmony_ci return options; 3377db96d56Sopenharmony_ci} 3387db96d56Sopenharmony_ci 3397db96d56Sopenharmony_cistatic int 3407db96d56Sopenharmony_cilzma_filter_converter(_lzma_state *state, PyObject *spec, void *ptr) 3417db96d56Sopenharmony_ci{ 3427db96d56Sopenharmony_ci lzma_filter *f = (lzma_filter *)ptr; 3437db96d56Sopenharmony_ci PyObject *id_obj; 3447db96d56Sopenharmony_ci 3457db96d56Sopenharmony_ci if (!PyMapping_Check(spec)) { 3467db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 3477db96d56Sopenharmony_ci "Filter specifier must be a dict or dict-like object"); 3487db96d56Sopenharmony_ci return 0; 3497db96d56Sopenharmony_ci } 3507db96d56Sopenharmony_ci id_obj = PyMapping_GetItemString(spec, "id"); 3517db96d56Sopenharmony_ci if (id_obj == NULL) { 3527db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_KeyError)) 3537db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 3547db96d56Sopenharmony_ci "Filter specifier must have an \"id\" entry"); 3557db96d56Sopenharmony_ci return 0; 3567db96d56Sopenharmony_ci } 3577db96d56Sopenharmony_ci f->id = PyLong_AsUnsignedLongLong(id_obj); 3587db96d56Sopenharmony_ci Py_DECREF(id_obj); 3597db96d56Sopenharmony_ci if (PyErr_Occurred()) { 3607db96d56Sopenharmony_ci return 0; 3617db96d56Sopenharmony_ci } 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_ci switch (f->id) { 3647db96d56Sopenharmony_ci case LZMA_FILTER_LZMA1: 3657db96d56Sopenharmony_ci case LZMA_FILTER_LZMA2: 3667db96d56Sopenharmony_ci f->options = parse_filter_spec_lzma(state, spec); 3677db96d56Sopenharmony_ci return f->options != NULL; 3687db96d56Sopenharmony_ci case LZMA_FILTER_DELTA: 3697db96d56Sopenharmony_ci f->options = parse_filter_spec_delta(state, spec); 3707db96d56Sopenharmony_ci return f->options != NULL; 3717db96d56Sopenharmony_ci case LZMA_FILTER_X86: 3727db96d56Sopenharmony_ci case LZMA_FILTER_POWERPC: 3737db96d56Sopenharmony_ci case LZMA_FILTER_IA64: 3747db96d56Sopenharmony_ci case LZMA_FILTER_ARM: 3757db96d56Sopenharmony_ci case LZMA_FILTER_ARMTHUMB: 3767db96d56Sopenharmony_ci case LZMA_FILTER_SPARC: 3777db96d56Sopenharmony_ci f->options = parse_filter_spec_bcj(state, spec); 3787db96d56Sopenharmony_ci return f->options != NULL; 3797db96d56Sopenharmony_ci default: 3807db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "Invalid filter ID: %llu", f->id); 3817db96d56Sopenharmony_ci return 0; 3827db96d56Sopenharmony_ci } 3837db96d56Sopenharmony_ci} 3847db96d56Sopenharmony_ci 3857db96d56Sopenharmony_cistatic void 3867db96d56Sopenharmony_cifree_filter_chain(lzma_filter filters[]) 3877db96d56Sopenharmony_ci{ 3887db96d56Sopenharmony_ci for (int i = 0; filters[i].id != LZMA_VLI_UNKNOWN; i++) { 3897db96d56Sopenharmony_ci PyMem_Free(filters[i].options); 3907db96d56Sopenharmony_ci } 3917db96d56Sopenharmony_ci} 3927db96d56Sopenharmony_ci 3937db96d56Sopenharmony_cistatic int 3947db96d56Sopenharmony_ciparse_filter_chain_spec(_lzma_state *state, lzma_filter filters[], PyObject *filterspecs) 3957db96d56Sopenharmony_ci{ 3967db96d56Sopenharmony_ci Py_ssize_t i, num_filters; 3977db96d56Sopenharmony_ci 3987db96d56Sopenharmony_ci num_filters = PySequence_Length(filterspecs); 3997db96d56Sopenharmony_ci if (num_filters == -1) { 4007db96d56Sopenharmony_ci return -1; 4017db96d56Sopenharmony_ci } 4027db96d56Sopenharmony_ci if (num_filters > LZMA_FILTERS_MAX) { 4037db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, 4047db96d56Sopenharmony_ci "Too many filters - liblzma supports a maximum of %d", 4057db96d56Sopenharmony_ci LZMA_FILTERS_MAX); 4067db96d56Sopenharmony_ci return -1; 4077db96d56Sopenharmony_ci } 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_ci for (i = 0; i < num_filters; i++) { 4107db96d56Sopenharmony_ci int ok = 1; 4117db96d56Sopenharmony_ci PyObject *spec = PySequence_GetItem(filterspecs, i); 4127db96d56Sopenharmony_ci if (spec == NULL || !lzma_filter_converter(state, spec, &filters[i])) { 4137db96d56Sopenharmony_ci ok = 0; 4147db96d56Sopenharmony_ci } 4157db96d56Sopenharmony_ci Py_XDECREF(spec); 4167db96d56Sopenharmony_ci if (!ok) { 4177db96d56Sopenharmony_ci filters[i].id = LZMA_VLI_UNKNOWN; 4187db96d56Sopenharmony_ci free_filter_chain(filters); 4197db96d56Sopenharmony_ci return -1; 4207db96d56Sopenharmony_ci } 4217db96d56Sopenharmony_ci } 4227db96d56Sopenharmony_ci filters[num_filters].id = LZMA_VLI_UNKNOWN; 4237db96d56Sopenharmony_ci return 0; 4247db96d56Sopenharmony_ci} 4257db96d56Sopenharmony_ci 4267db96d56Sopenharmony_ci 4277db96d56Sopenharmony_ci/* Filter specifier construction. 4287db96d56Sopenharmony_ci 4297db96d56Sopenharmony_ci This code handles converting C lzma_filter structs into 4307db96d56Sopenharmony_ci Python-level filter specifiers (represented as dicts). */ 4317db96d56Sopenharmony_ci 4327db96d56Sopenharmony_cistatic int 4337db96d56Sopenharmony_cispec_add_field(PyObject *spec, const char *key, unsigned long long value) 4347db96d56Sopenharmony_ci{ 4357db96d56Sopenharmony_ci PyObject *value_object = PyLong_FromUnsignedLongLong(value); 4367db96d56Sopenharmony_ci if (value_object == NULL) { 4377db96d56Sopenharmony_ci return -1; 4387db96d56Sopenharmony_ci } 4397db96d56Sopenharmony_ci PyObject *key_object = PyUnicode_InternFromString(key); 4407db96d56Sopenharmony_ci if (key_object == NULL) { 4417db96d56Sopenharmony_ci Py_DECREF(value_object); 4427db96d56Sopenharmony_ci return -1; 4437db96d56Sopenharmony_ci } 4447db96d56Sopenharmony_ci int status = PyDict_SetItem(spec, key_object, value_object); 4457db96d56Sopenharmony_ci Py_DECREF(key_object); 4467db96d56Sopenharmony_ci Py_DECREF(value_object); 4477db96d56Sopenharmony_ci return status; 4487db96d56Sopenharmony_ci} 4497db96d56Sopenharmony_ci 4507db96d56Sopenharmony_cistatic PyObject * 4517db96d56Sopenharmony_cibuild_filter_spec(const lzma_filter *f) 4527db96d56Sopenharmony_ci{ 4537db96d56Sopenharmony_ci PyObject *spec; 4547db96d56Sopenharmony_ci 4557db96d56Sopenharmony_ci spec = PyDict_New(); 4567db96d56Sopenharmony_ci if (spec == NULL) { 4577db96d56Sopenharmony_ci return NULL; 4587db96d56Sopenharmony_ci } 4597db96d56Sopenharmony_ci 4607db96d56Sopenharmony_ci#define ADD_FIELD(SOURCE, FIELD) \ 4617db96d56Sopenharmony_ci do { \ 4627db96d56Sopenharmony_ci if (spec_add_field(spec, #FIELD, SOURCE->FIELD) == -1) \ 4637db96d56Sopenharmony_ci goto error;\ 4647db96d56Sopenharmony_ci } while (0) 4657db96d56Sopenharmony_ci 4667db96d56Sopenharmony_ci ADD_FIELD(f, id); 4677db96d56Sopenharmony_ci 4687db96d56Sopenharmony_ci switch (f->id) { 4697db96d56Sopenharmony_ci /* For LZMA1 filters, lzma_properties_{encode,decode}() only look at the 4707db96d56Sopenharmony_ci lc, lp, pb, and dict_size fields. For LZMA2 filters, only the 4717db96d56Sopenharmony_ci dict_size field is used. */ 4727db96d56Sopenharmony_ci case LZMA_FILTER_LZMA1: { 4737db96d56Sopenharmony_ci lzma_options_lzma *options = f->options; 4747db96d56Sopenharmony_ci ADD_FIELD(options, lc); 4757db96d56Sopenharmony_ci ADD_FIELD(options, lp); 4767db96d56Sopenharmony_ci ADD_FIELD(options, pb); 4777db96d56Sopenharmony_ci ADD_FIELD(options, dict_size); 4787db96d56Sopenharmony_ci break; 4797db96d56Sopenharmony_ci } 4807db96d56Sopenharmony_ci case LZMA_FILTER_LZMA2: { 4817db96d56Sopenharmony_ci lzma_options_lzma *options = f->options; 4827db96d56Sopenharmony_ci ADD_FIELD(options, dict_size); 4837db96d56Sopenharmony_ci break; 4847db96d56Sopenharmony_ci } 4857db96d56Sopenharmony_ci case LZMA_FILTER_DELTA: { 4867db96d56Sopenharmony_ci lzma_options_delta *options = f->options; 4877db96d56Sopenharmony_ci ADD_FIELD(options, dist); 4887db96d56Sopenharmony_ci break; 4897db96d56Sopenharmony_ci } 4907db96d56Sopenharmony_ci case LZMA_FILTER_X86: 4917db96d56Sopenharmony_ci case LZMA_FILTER_POWERPC: 4927db96d56Sopenharmony_ci case LZMA_FILTER_IA64: 4937db96d56Sopenharmony_ci case LZMA_FILTER_ARM: 4947db96d56Sopenharmony_ci case LZMA_FILTER_ARMTHUMB: 4957db96d56Sopenharmony_ci case LZMA_FILTER_SPARC: { 4967db96d56Sopenharmony_ci lzma_options_bcj *options = f->options; 4977db96d56Sopenharmony_ci ADD_FIELD(options, start_offset); 4987db96d56Sopenharmony_ci break; 4997db96d56Sopenharmony_ci } 5007db96d56Sopenharmony_ci default: 5017db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "Invalid filter ID: %llu", f->id); 5027db96d56Sopenharmony_ci goto error; 5037db96d56Sopenharmony_ci } 5047db96d56Sopenharmony_ci 5057db96d56Sopenharmony_ci#undef ADD_FIELD 5067db96d56Sopenharmony_ci 5077db96d56Sopenharmony_ci return spec; 5087db96d56Sopenharmony_ci 5097db96d56Sopenharmony_cierror: 5107db96d56Sopenharmony_ci Py_DECREF(spec); 5117db96d56Sopenharmony_ci return NULL; 5127db96d56Sopenharmony_ci} 5137db96d56Sopenharmony_ci 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_ci/*[clinic input] 5167db96d56Sopenharmony_cimodule _lzma 5177db96d56Sopenharmony_ciclass _lzma.LZMACompressor "Compressor *" "&Compressor_type" 5187db96d56Sopenharmony_ciclass _lzma.LZMADecompressor "Decompressor *" "&Decompressor_type" 5197db96d56Sopenharmony_ci[clinic start generated code]*/ 5207db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2c14bbe05ff0c147]*/ 5217db96d56Sopenharmony_ci 5227db96d56Sopenharmony_ci#include "clinic/_lzmamodule.c.h" 5237db96d56Sopenharmony_ci 5247db96d56Sopenharmony_ci/*[python input] 5257db96d56Sopenharmony_ci 5267db96d56Sopenharmony_ciclass lzma_vli_converter(CConverter): 5277db96d56Sopenharmony_ci type = 'lzma_vli' 5287db96d56Sopenharmony_ci converter = 'lzma_vli_converter' 5297db96d56Sopenharmony_ci 5307db96d56Sopenharmony_ciclass lzma_filter_converter(CConverter): 5317db96d56Sopenharmony_ci type = 'lzma_filter' 5327db96d56Sopenharmony_ci converter = 'lzma_filter_converter' 5337db96d56Sopenharmony_ci c_default = c_ignored_default = "{LZMA_VLI_UNKNOWN, NULL}" 5347db96d56Sopenharmony_ci 5357db96d56Sopenharmony_ci def cleanup(self): 5367db96d56Sopenharmony_ci name = ensure_legal_c_identifier(self.name) 5377db96d56Sopenharmony_ci return ('if (%(name)s.id != LZMA_VLI_UNKNOWN)\n' 5387db96d56Sopenharmony_ci ' PyMem_Free(%(name)s.options);\n') % {'name': name} 5397db96d56Sopenharmony_ci 5407db96d56Sopenharmony_ci[python start generated code]*/ 5417db96d56Sopenharmony_ci/*[python end generated code: output=da39a3ee5e6b4b0d input=74fe7631ce377a94]*/ 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ci 5447db96d56Sopenharmony_ci/* LZMACompressor class. */ 5457db96d56Sopenharmony_ci 5467db96d56Sopenharmony_cistatic PyObject * 5477db96d56Sopenharmony_cicompress(Compressor *c, uint8_t *data, size_t len, lzma_action action) 5487db96d56Sopenharmony_ci{ 5497db96d56Sopenharmony_ci PyObject *result; 5507db96d56Sopenharmony_ci _BlocksOutputBuffer buffer = {.list = NULL}; 5517db96d56Sopenharmony_ci _lzma_state *state = PyType_GetModuleState(Py_TYPE(c)); 5527db96d56Sopenharmony_ci assert(state != NULL); 5537db96d56Sopenharmony_ci 5547db96d56Sopenharmony_ci if (OutputBuffer_InitAndGrow(&buffer, -1, &c->lzs.next_out, &c->lzs.avail_out) < 0) { 5557db96d56Sopenharmony_ci goto error; 5567db96d56Sopenharmony_ci } 5577db96d56Sopenharmony_ci c->lzs.next_in = data; 5587db96d56Sopenharmony_ci c->lzs.avail_in = len; 5597db96d56Sopenharmony_ci 5607db96d56Sopenharmony_ci for (;;) { 5617db96d56Sopenharmony_ci lzma_ret lzret; 5627db96d56Sopenharmony_ci 5637db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 5647db96d56Sopenharmony_ci lzret = lzma_code(&c->lzs, action); 5657db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 5667db96d56Sopenharmony_ci 5677db96d56Sopenharmony_ci if (lzret == LZMA_BUF_ERROR && len == 0 && c->lzs.avail_out > 0) { 5687db96d56Sopenharmony_ci lzret = LZMA_OK; /* That wasn't a real error */ 5697db96d56Sopenharmony_ci } 5707db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) { 5717db96d56Sopenharmony_ci goto error; 5727db96d56Sopenharmony_ci } 5737db96d56Sopenharmony_ci if ((action == LZMA_RUN && c->lzs.avail_in == 0) || 5747db96d56Sopenharmony_ci (action == LZMA_FINISH && lzret == LZMA_STREAM_END)) { 5757db96d56Sopenharmony_ci break; 5767db96d56Sopenharmony_ci } else if (c->lzs.avail_out == 0) { 5777db96d56Sopenharmony_ci if (OutputBuffer_Grow(&buffer, &c->lzs.next_out, &c->lzs.avail_out) < 0) { 5787db96d56Sopenharmony_ci goto error; 5797db96d56Sopenharmony_ci } 5807db96d56Sopenharmony_ci } 5817db96d56Sopenharmony_ci } 5827db96d56Sopenharmony_ci 5837db96d56Sopenharmony_ci result = OutputBuffer_Finish(&buffer, c->lzs.avail_out); 5847db96d56Sopenharmony_ci if (result != NULL) { 5857db96d56Sopenharmony_ci return result; 5867db96d56Sopenharmony_ci } 5877db96d56Sopenharmony_ci 5887db96d56Sopenharmony_cierror: 5897db96d56Sopenharmony_ci OutputBuffer_OnError(&buffer); 5907db96d56Sopenharmony_ci return NULL; 5917db96d56Sopenharmony_ci} 5927db96d56Sopenharmony_ci 5937db96d56Sopenharmony_ci/*[clinic input] 5947db96d56Sopenharmony_ci_lzma.LZMACompressor.compress 5957db96d56Sopenharmony_ci 5967db96d56Sopenharmony_ci data: Py_buffer 5977db96d56Sopenharmony_ci / 5987db96d56Sopenharmony_ci 5997db96d56Sopenharmony_ciProvide data to the compressor object. 6007db96d56Sopenharmony_ci 6017db96d56Sopenharmony_ciReturns a chunk of compressed data if possible, or b'' otherwise. 6027db96d56Sopenharmony_ci 6037db96d56Sopenharmony_ciWhen you have finished providing data to the compressor, call the 6047db96d56Sopenharmony_ciflush() method to finish the compression process. 6057db96d56Sopenharmony_ci[clinic start generated code]*/ 6067db96d56Sopenharmony_ci 6077db96d56Sopenharmony_cistatic PyObject * 6087db96d56Sopenharmony_ci_lzma_LZMACompressor_compress_impl(Compressor *self, Py_buffer *data) 6097db96d56Sopenharmony_ci/*[clinic end generated code: output=31f615136963e00f input=64019eac7f2cc8d0]*/ 6107db96d56Sopenharmony_ci{ 6117db96d56Sopenharmony_ci PyObject *result = NULL; 6127db96d56Sopenharmony_ci 6137db96d56Sopenharmony_ci ACQUIRE_LOCK(self); 6147db96d56Sopenharmony_ci if (self->flushed) { 6157db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "Compressor has been flushed"); 6167db96d56Sopenharmony_ci } 6177db96d56Sopenharmony_ci else { 6187db96d56Sopenharmony_ci result = compress(self, data->buf, data->len, LZMA_RUN); 6197db96d56Sopenharmony_ci } 6207db96d56Sopenharmony_ci RELEASE_LOCK(self); 6217db96d56Sopenharmony_ci return result; 6227db96d56Sopenharmony_ci} 6237db96d56Sopenharmony_ci 6247db96d56Sopenharmony_ci/*[clinic input] 6257db96d56Sopenharmony_ci_lzma.LZMACompressor.flush 6267db96d56Sopenharmony_ci 6277db96d56Sopenharmony_ciFinish the compression process. 6287db96d56Sopenharmony_ci 6297db96d56Sopenharmony_ciReturns the compressed data left in internal buffers. 6307db96d56Sopenharmony_ci 6317db96d56Sopenharmony_ciThe compressor object may not be used after this method is called. 6327db96d56Sopenharmony_ci[clinic start generated code]*/ 6337db96d56Sopenharmony_ci 6347db96d56Sopenharmony_cistatic PyObject * 6357db96d56Sopenharmony_ci_lzma_LZMACompressor_flush_impl(Compressor *self) 6367db96d56Sopenharmony_ci/*[clinic end generated code: output=fec21f3e22504f50 input=6b369303f67ad0a8]*/ 6377db96d56Sopenharmony_ci{ 6387db96d56Sopenharmony_ci PyObject *result = NULL; 6397db96d56Sopenharmony_ci 6407db96d56Sopenharmony_ci ACQUIRE_LOCK(self); 6417db96d56Sopenharmony_ci if (self->flushed) { 6427db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "Repeated call to flush()"); 6437db96d56Sopenharmony_ci } else { 6447db96d56Sopenharmony_ci self->flushed = 1; 6457db96d56Sopenharmony_ci result = compress(self, NULL, 0, LZMA_FINISH); 6467db96d56Sopenharmony_ci } 6477db96d56Sopenharmony_ci RELEASE_LOCK(self); 6487db96d56Sopenharmony_ci return result; 6497db96d56Sopenharmony_ci} 6507db96d56Sopenharmony_ci 6517db96d56Sopenharmony_cistatic int 6527db96d56Sopenharmony_ciCompressor_init_xz(_lzma_state *state, lzma_stream *lzs, 6537db96d56Sopenharmony_ci int check, uint32_t preset, PyObject *filterspecs) 6547db96d56Sopenharmony_ci{ 6557db96d56Sopenharmony_ci lzma_ret lzret; 6567db96d56Sopenharmony_ci 6577db96d56Sopenharmony_ci if (filterspecs == Py_None) { 6587db96d56Sopenharmony_ci lzret = lzma_easy_encoder(lzs, preset, check); 6597db96d56Sopenharmony_ci } else { 6607db96d56Sopenharmony_ci lzma_filter filters[LZMA_FILTERS_MAX + 1]; 6617db96d56Sopenharmony_ci 6627db96d56Sopenharmony_ci if (parse_filter_chain_spec(state, filters, filterspecs) == -1) 6637db96d56Sopenharmony_ci return -1; 6647db96d56Sopenharmony_ci lzret = lzma_stream_encoder(lzs, filters, check); 6657db96d56Sopenharmony_ci free_filter_chain(filters); 6667db96d56Sopenharmony_ci } 6677db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) { 6687db96d56Sopenharmony_ci return -1; 6697db96d56Sopenharmony_ci } 6707db96d56Sopenharmony_ci else { 6717db96d56Sopenharmony_ci return 0; 6727db96d56Sopenharmony_ci } 6737db96d56Sopenharmony_ci} 6747db96d56Sopenharmony_ci 6757db96d56Sopenharmony_cistatic int 6767db96d56Sopenharmony_ciCompressor_init_alone(_lzma_state *state, lzma_stream *lzs, uint32_t preset, PyObject *filterspecs) 6777db96d56Sopenharmony_ci{ 6787db96d56Sopenharmony_ci lzma_ret lzret; 6797db96d56Sopenharmony_ci 6807db96d56Sopenharmony_ci if (filterspecs == Py_None) { 6817db96d56Sopenharmony_ci lzma_options_lzma options; 6827db96d56Sopenharmony_ci 6837db96d56Sopenharmony_ci if (lzma_lzma_preset(&options, preset)) { 6847db96d56Sopenharmony_ci PyErr_Format(state->error, "Invalid compression preset: %u", preset); 6857db96d56Sopenharmony_ci return -1; 6867db96d56Sopenharmony_ci } 6877db96d56Sopenharmony_ci lzret = lzma_alone_encoder(lzs, &options); 6887db96d56Sopenharmony_ci } else { 6897db96d56Sopenharmony_ci lzma_filter filters[LZMA_FILTERS_MAX + 1]; 6907db96d56Sopenharmony_ci 6917db96d56Sopenharmony_ci if (parse_filter_chain_spec(state, filters, filterspecs) == -1) 6927db96d56Sopenharmony_ci return -1; 6937db96d56Sopenharmony_ci if (filters[0].id == LZMA_FILTER_LZMA1 && 6947db96d56Sopenharmony_ci filters[1].id == LZMA_VLI_UNKNOWN) { 6957db96d56Sopenharmony_ci lzret = lzma_alone_encoder(lzs, filters[0].options); 6967db96d56Sopenharmony_ci } else { 6977db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 6987db96d56Sopenharmony_ci "Invalid filter chain for FORMAT_ALONE - " 6997db96d56Sopenharmony_ci "must be a single LZMA1 filter"); 7007db96d56Sopenharmony_ci lzret = LZMA_PROG_ERROR; 7017db96d56Sopenharmony_ci } 7027db96d56Sopenharmony_ci free_filter_chain(filters); 7037db96d56Sopenharmony_ci } 7047db96d56Sopenharmony_ci if (PyErr_Occurred() || catch_lzma_error(state, lzret)) { 7057db96d56Sopenharmony_ci return -1; 7067db96d56Sopenharmony_ci } 7077db96d56Sopenharmony_ci else { 7087db96d56Sopenharmony_ci return 0; 7097db96d56Sopenharmony_ci } 7107db96d56Sopenharmony_ci} 7117db96d56Sopenharmony_ci 7127db96d56Sopenharmony_cistatic int 7137db96d56Sopenharmony_ciCompressor_init_raw(_lzma_state *state, lzma_stream *lzs, PyObject *filterspecs) 7147db96d56Sopenharmony_ci{ 7157db96d56Sopenharmony_ci lzma_filter filters[LZMA_FILTERS_MAX + 1]; 7167db96d56Sopenharmony_ci lzma_ret lzret; 7177db96d56Sopenharmony_ci 7187db96d56Sopenharmony_ci if (filterspecs == Py_None) { 7197db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 7207db96d56Sopenharmony_ci "Must specify filters for FORMAT_RAW"); 7217db96d56Sopenharmony_ci return -1; 7227db96d56Sopenharmony_ci } 7237db96d56Sopenharmony_ci if (parse_filter_chain_spec(state, filters, filterspecs) == -1) { 7247db96d56Sopenharmony_ci return -1; 7257db96d56Sopenharmony_ci } 7267db96d56Sopenharmony_ci lzret = lzma_raw_encoder(lzs, filters); 7277db96d56Sopenharmony_ci free_filter_chain(filters); 7287db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) { 7297db96d56Sopenharmony_ci return -1; 7307db96d56Sopenharmony_ci } 7317db96d56Sopenharmony_ci else { 7327db96d56Sopenharmony_ci return 0; 7337db96d56Sopenharmony_ci } 7347db96d56Sopenharmony_ci} 7357db96d56Sopenharmony_ci 7367db96d56Sopenharmony_ci/*[-clinic input] 7377db96d56Sopenharmony_ci_lzma.LZMACompressor.__init__ 7387db96d56Sopenharmony_ci 7397db96d56Sopenharmony_ci format: int(c_default="FORMAT_XZ") = FORMAT_XZ 7407db96d56Sopenharmony_ci The container format to use for the output. This can 7417db96d56Sopenharmony_ci be FORMAT_XZ (default), FORMAT_ALONE, or FORMAT_RAW. 7427db96d56Sopenharmony_ci 7437db96d56Sopenharmony_ci check: int(c_default="-1") = unspecified 7447db96d56Sopenharmony_ci The integrity check to use. For FORMAT_XZ, the default 7457db96d56Sopenharmony_ci is CHECK_CRC64. FORMAT_ALONE and FORMAT_RAW do not support integrity 7467db96d56Sopenharmony_ci checks; for these formats, check must be omitted, or be CHECK_NONE. 7477db96d56Sopenharmony_ci 7487db96d56Sopenharmony_ci preset: object = None 7497db96d56Sopenharmony_ci If provided should be an integer in the range 0-9, optionally 7507db96d56Sopenharmony_ci OR-ed with the constant PRESET_EXTREME. 7517db96d56Sopenharmony_ci 7527db96d56Sopenharmony_ci filters: object = None 7537db96d56Sopenharmony_ci If provided should be a sequence of dicts. Each dict should 7547db96d56Sopenharmony_ci have an entry for "id" indicating the ID of the filter, plus 7557db96d56Sopenharmony_ci additional entries for options to the filter. 7567db96d56Sopenharmony_ci 7577db96d56Sopenharmony_ciCreate a compressor object for compressing data incrementally. 7587db96d56Sopenharmony_ci 7597db96d56Sopenharmony_ciThe settings used by the compressor can be specified either as a 7607db96d56Sopenharmony_cipreset compression level (with the 'preset' argument), or in detail 7617db96d56Sopenharmony_cias a custom filter chain (with the 'filters' argument). For FORMAT_XZ 7627db96d56Sopenharmony_ciand FORMAT_ALONE, the default is to use the PRESET_DEFAULT preset 7637db96d56Sopenharmony_cilevel. For FORMAT_RAW, the caller must always specify a filter chain; 7647db96d56Sopenharmony_cithe raw compressor does not support preset compression levels. 7657db96d56Sopenharmony_ci 7667db96d56Sopenharmony_ciFor one-shot compression, use the compress() function instead. 7677db96d56Sopenharmony_ci[-clinic start generated code]*/ 7687db96d56Sopenharmony_cistatic int 7697db96d56Sopenharmony_ciCompressor_init(Compressor *self, PyObject *args, PyObject *kwargs) 7707db96d56Sopenharmony_ci{ 7717db96d56Sopenharmony_ci static char *arg_names[] = {"format", "check", "preset", "filters", NULL}; 7727db96d56Sopenharmony_ci int format = FORMAT_XZ; 7737db96d56Sopenharmony_ci int check = -1; 7747db96d56Sopenharmony_ci uint32_t preset = LZMA_PRESET_DEFAULT; 7757db96d56Sopenharmony_ci PyObject *preset_obj = Py_None; 7767db96d56Sopenharmony_ci PyObject *filterspecs = Py_None; 7777db96d56Sopenharmony_ci _lzma_state *state = PyType_GetModuleState(Py_TYPE(self)); 7787db96d56Sopenharmony_ci assert(state != NULL); 7797db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwargs, 7807db96d56Sopenharmony_ci "|iiOO:LZMACompressor", arg_names, 7817db96d56Sopenharmony_ci &format, &check, &preset_obj, 7827db96d56Sopenharmony_ci &filterspecs)) { 7837db96d56Sopenharmony_ci return -1; 7847db96d56Sopenharmony_ci } 7857db96d56Sopenharmony_ci 7867db96d56Sopenharmony_ci if (format != FORMAT_XZ && check != -1 && check != LZMA_CHECK_NONE) { 7877db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 7887db96d56Sopenharmony_ci "Integrity checks are only supported by FORMAT_XZ"); 7897db96d56Sopenharmony_ci return -1; 7907db96d56Sopenharmony_ci } 7917db96d56Sopenharmony_ci 7927db96d56Sopenharmony_ci if (preset_obj != Py_None && filterspecs != Py_None) { 7937db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 7947db96d56Sopenharmony_ci "Cannot specify both preset and filter chain"); 7957db96d56Sopenharmony_ci return -1; 7967db96d56Sopenharmony_ci } 7977db96d56Sopenharmony_ci 7987db96d56Sopenharmony_ci if (preset_obj != Py_None) { 7997db96d56Sopenharmony_ci if (!uint32_converter(preset_obj, &preset)) { 8007db96d56Sopenharmony_ci return -1; 8017db96d56Sopenharmony_ci } 8027db96d56Sopenharmony_ci } 8037db96d56Sopenharmony_ci 8047db96d56Sopenharmony_ci self->alloc.opaque = NULL; 8057db96d56Sopenharmony_ci self->alloc.alloc = PyLzma_Malloc; 8067db96d56Sopenharmony_ci self->alloc.free = PyLzma_Free; 8077db96d56Sopenharmony_ci self->lzs.allocator = &self->alloc; 8087db96d56Sopenharmony_ci 8097db96d56Sopenharmony_ci self->lock = PyThread_allocate_lock(); 8107db96d56Sopenharmony_ci if (self->lock == NULL) { 8117db96d56Sopenharmony_ci PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock"); 8127db96d56Sopenharmony_ci return -1; 8137db96d56Sopenharmony_ci } 8147db96d56Sopenharmony_ci 8157db96d56Sopenharmony_ci self->flushed = 0; 8167db96d56Sopenharmony_ci switch (format) { 8177db96d56Sopenharmony_ci case FORMAT_XZ: 8187db96d56Sopenharmony_ci if (check == -1) { 8197db96d56Sopenharmony_ci check = LZMA_CHECK_CRC64; 8207db96d56Sopenharmony_ci } 8217db96d56Sopenharmony_ci if (Compressor_init_xz(state, &self->lzs, check, preset, filterspecs) != 0) { 8227db96d56Sopenharmony_ci break; 8237db96d56Sopenharmony_ci } 8247db96d56Sopenharmony_ci return 0; 8257db96d56Sopenharmony_ci 8267db96d56Sopenharmony_ci case FORMAT_ALONE: 8277db96d56Sopenharmony_ci if (Compressor_init_alone(state, &self->lzs, preset, filterspecs) != 0) { 8287db96d56Sopenharmony_ci break; 8297db96d56Sopenharmony_ci } 8307db96d56Sopenharmony_ci return 0; 8317db96d56Sopenharmony_ci 8327db96d56Sopenharmony_ci case FORMAT_RAW: 8337db96d56Sopenharmony_ci if (Compressor_init_raw(state, &self->lzs, filterspecs) != 0) { 8347db96d56Sopenharmony_ci break; 8357db96d56Sopenharmony_ci } 8367db96d56Sopenharmony_ci return 0; 8377db96d56Sopenharmony_ci 8387db96d56Sopenharmony_ci default: 8397db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, 8407db96d56Sopenharmony_ci "Invalid container format: %d", format); 8417db96d56Sopenharmony_ci break; 8427db96d56Sopenharmony_ci } 8437db96d56Sopenharmony_ci 8447db96d56Sopenharmony_ci PyThread_free_lock(self->lock); 8457db96d56Sopenharmony_ci self->lock = NULL; 8467db96d56Sopenharmony_ci return -1; 8477db96d56Sopenharmony_ci} 8487db96d56Sopenharmony_ci 8497db96d56Sopenharmony_cistatic void 8507db96d56Sopenharmony_ciCompressor_dealloc(Compressor *self) 8517db96d56Sopenharmony_ci{ 8527db96d56Sopenharmony_ci lzma_end(&self->lzs); 8537db96d56Sopenharmony_ci if (self->lock != NULL) { 8547db96d56Sopenharmony_ci PyThread_free_lock(self->lock); 8557db96d56Sopenharmony_ci } 8567db96d56Sopenharmony_ci PyTypeObject *tp = Py_TYPE(self); 8577db96d56Sopenharmony_ci tp->tp_free((PyObject *)self); 8587db96d56Sopenharmony_ci Py_DECREF(tp); 8597db96d56Sopenharmony_ci} 8607db96d56Sopenharmony_ci 8617db96d56Sopenharmony_cistatic PyMethodDef Compressor_methods[] = { 8627db96d56Sopenharmony_ci _LZMA_LZMACOMPRESSOR_COMPRESS_METHODDEF 8637db96d56Sopenharmony_ci _LZMA_LZMACOMPRESSOR_FLUSH_METHODDEF 8647db96d56Sopenharmony_ci {NULL} 8657db96d56Sopenharmony_ci}; 8667db96d56Sopenharmony_ci 8677db96d56Sopenharmony_cistatic int 8687db96d56Sopenharmony_ciCompressor_traverse(Compressor *self, visitproc visit, void *arg) 8697db96d56Sopenharmony_ci{ 8707db96d56Sopenharmony_ci Py_VISIT(Py_TYPE(self)); 8717db96d56Sopenharmony_ci return 0; 8727db96d56Sopenharmony_ci} 8737db96d56Sopenharmony_ci 8747db96d56Sopenharmony_ciPyDoc_STRVAR(Compressor_doc, 8757db96d56Sopenharmony_ci"LZMACompressor(format=FORMAT_XZ, check=-1, preset=None, filters=None)\n" 8767db96d56Sopenharmony_ci"\n" 8777db96d56Sopenharmony_ci"Create a compressor object for compressing data incrementally.\n" 8787db96d56Sopenharmony_ci"\n" 8797db96d56Sopenharmony_ci"format specifies the container format to use for the output. This can\n" 8807db96d56Sopenharmony_ci"be FORMAT_XZ (default), FORMAT_ALONE, or FORMAT_RAW.\n" 8817db96d56Sopenharmony_ci"\n" 8827db96d56Sopenharmony_ci"check specifies the integrity check to use. For FORMAT_XZ, the default\n" 8837db96d56Sopenharmony_ci"is CHECK_CRC64. FORMAT_ALONE and FORMAT_RAW do not support integrity\n" 8847db96d56Sopenharmony_ci"checks; for these formats, check must be omitted, or be CHECK_NONE.\n" 8857db96d56Sopenharmony_ci"\n" 8867db96d56Sopenharmony_ci"The settings used by the compressor can be specified either as a\n" 8877db96d56Sopenharmony_ci"preset compression level (with the 'preset' argument), or in detail\n" 8887db96d56Sopenharmony_ci"as a custom filter chain (with the 'filters' argument). For FORMAT_XZ\n" 8897db96d56Sopenharmony_ci"and FORMAT_ALONE, the default is to use the PRESET_DEFAULT preset\n" 8907db96d56Sopenharmony_ci"level. For FORMAT_RAW, the caller must always specify a filter chain;\n" 8917db96d56Sopenharmony_ci"the raw compressor does not support preset compression levels.\n" 8927db96d56Sopenharmony_ci"\n" 8937db96d56Sopenharmony_ci"preset (if provided) should be an integer in the range 0-9, optionally\n" 8947db96d56Sopenharmony_ci"OR-ed with the constant PRESET_EXTREME.\n" 8957db96d56Sopenharmony_ci"\n" 8967db96d56Sopenharmony_ci"filters (if provided) should be a sequence of dicts. Each dict should\n" 8977db96d56Sopenharmony_ci"have an entry for \"id\" indicating the ID of the filter, plus\n" 8987db96d56Sopenharmony_ci"additional entries for options to the filter.\n" 8997db96d56Sopenharmony_ci"\n" 9007db96d56Sopenharmony_ci"For one-shot compression, use the compress() function instead.\n"); 9017db96d56Sopenharmony_ci 9027db96d56Sopenharmony_cistatic PyType_Slot lzma_compressor_type_slots[] = { 9037db96d56Sopenharmony_ci {Py_tp_dealloc, Compressor_dealloc}, 9047db96d56Sopenharmony_ci {Py_tp_methods, Compressor_methods}, 9057db96d56Sopenharmony_ci {Py_tp_init, Compressor_init}, 9067db96d56Sopenharmony_ci {Py_tp_new, PyType_GenericNew}, 9077db96d56Sopenharmony_ci {Py_tp_doc, (char *)Compressor_doc}, 9087db96d56Sopenharmony_ci {Py_tp_traverse, Compressor_traverse}, 9097db96d56Sopenharmony_ci {0, 0} 9107db96d56Sopenharmony_ci}; 9117db96d56Sopenharmony_ci 9127db96d56Sopenharmony_cistatic PyType_Spec lzma_compressor_type_spec = { 9137db96d56Sopenharmony_ci .name = "_lzma.LZMACompressor", 9147db96d56Sopenharmony_ci .basicsize = sizeof(Compressor), 9157db96d56Sopenharmony_ci // Calling PyType_GetModuleState() on a subclass is not safe. 9167db96d56Sopenharmony_ci // lzma_compressor_type_spec does not have Py_TPFLAGS_BASETYPE flag 9177db96d56Sopenharmony_ci // which prevents to create a subclass. 9187db96d56Sopenharmony_ci // So calling PyType_GetModuleState() in this file is always safe. 9197db96d56Sopenharmony_ci .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), 9207db96d56Sopenharmony_ci .slots = lzma_compressor_type_slots, 9217db96d56Sopenharmony_ci}; 9227db96d56Sopenharmony_ci 9237db96d56Sopenharmony_ci/* LZMADecompressor class. */ 9247db96d56Sopenharmony_ci 9257db96d56Sopenharmony_ci/* Decompress data of length d->lzs.avail_in in d->lzs.next_in. The output 9267db96d56Sopenharmony_ci buffer is allocated dynamically and returned. At most max_length bytes are 9277db96d56Sopenharmony_ci returned, so some of the input may not be consumed. d->lzs.next_in and 9287db96d56Sopenharmony_ci d->lzs.avail_in are updated to reflect the consumed input. */ 9297db96d56Sopenharmony_cistatic PyObject* 9307db96d56Sopenharmony_cidecompress_buf(Decompressor *d, Py_ssize_t max_length) 9317db96d56Sopenharmony_ci{ 9327db96d56Sopenharmony_ci PyObject *result; 9337db96d56Sopenharmony_ci lzma_stream *lzs = &d->lzs; 9347db96d56Sopenharmony_ci _BlocksOutputBuffer buffer = {.list = NULL}; 9357db96d56Sopenharmony_ci _lzma_state *state = PyType_GetModuleState(Py_TYPE(d)); 9367db96d56Sopenharmony_ci assert(state != NULL); 9377db96d56Sopenharmony_ci 9387db96d56Sopenharmony_ci if (OutputBuffer_InitAndGrow(&buffer, max_length, &lzs->next_out, &lzs->avail_out) < 0) { 9397db96d56Sopenharmony_ci goto error; 9407db96d56Sopenharmony_ci } 9417db96d56Sopenharmony_ci 9427db96d56Sopenharmony_ci for (;;) { 9437db96d56Sopenharmony_ci lzma_ret lzret; 9447db96d56Sopenharmony_ci 9457db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 9467db96d56Sopenharmony_ci lzret = lzma_code(lzs, LZMA_RUN); 9477db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 9487db96d56Sopenharmony_ci 9497db96d56Sopenharmony_ci if (lzret == LZMA_BUF_ERROR && lzs->avail_in == 0 && lzs->avail_out > 0) { 9507db96d56Sopenharmony_ci lzret = LZMA_OK; /* That wasn't a real error */ 9517db96d56Sopenharmony_ci } 9527db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) { 9537db96d56Sopenharmony_ci goto error; 9547db96d56Sopenharmony_ci } 9557db96d56Sopenharmony_ci if (lzret == LZMA_GET_CHECK || lzret == LZMA_NO_CHECK) { 9567db96d56Sopenharmony_ci d->check = lzma_get_check(&d->lzs); 9577db96d56Sopenharmony_ci } 9587db96d56Sopenharmony_ci if (lzret == LZMA_STREAM_END) { 9597db96d56Sopenharmony_ci d->eof = 1; 9607db96d56Sopenharmony_ci break; 9617db96d56Sopenharmony_ci } else if (lzs->avail_out == 0) { 9627db96d56Sopenharmony_ci /* Need to check lzs->avail_out before lzs->avail_in. 9637db96d56Sopenharmony_ci Maybe lzs's internal state still have a few bytes 9647db96d56Sopenharmony_ci can be output, grow the output buffer and continue 9657db96d56Sopenharmony_ci if max_lengh < 0. */ 9667db96d56Sopenharmony_ci if (OutputBuffer_GetDataSize(&buffer, lzs->avail_out) == max_length) { 9677db96d56Sopenharmony_ci break; 9687db96d56Sopenharmony_ci } 9697db96d56Sopenharmony_ci if (OutputBuffer_Grow(&buffer, &lzs->next_out, &lzs->avail_out) < 0) { 9707db96d56Sopenharmony_ci goto error; 9717db96d56Sopenharmony_ci } 9727db96d56Sopenharmony_ci } else if (lzs->avail_in == 0) { 9737db96d56Sopenharmony_ci break; 9747db96d56Sopenharmony_ci } 9757db96d56Sopenharmony_ci } 9767db96d56Sopenharmony_ci 9777db96d56Sopenharmony_ci result = OutputBuffer_Finish(&buffer, lzs->avail_out); 9787db96d56Sopenharmony_ci if (result != NULL) { 9797db96d56Sopenharmony_ci return result; 9807db96d56Sopenharmony_ci } 9817db96d56Sopenharmony_ci 9827db96d56Sopenharmony_cierror: 9837db96d56Sopenharmony_ci OutputBuffer_OnError(&buffer); 9847db96d56Sopenharmony_ci return NULL; 9857db96d56Sopenharmony_ci} 9867db96d56Sopenharmony_ci 9877db96d56Sopenharmony_cistatic PyObject * 9887db96d56Sopenharmony_cidecompress(Decompressor *d, uint8_t *data, size_t len, Py_ssize_t max_length) 9897db96d56Sopenharmony_ci{ 9907db96d56Sopenharmony_ci char input_buffer_in_use; 9917db96d56Sopenharmony_ci PyObject *result; 9927db96d56Sopenharmony_ci lzma_stream *lzs = &d->lzs; 9937db96d56Sopenharmony_ci 9947db96d56Sopenharmony_ci /* Prepend unconsumed input if necessary */ 9957db96d56Sopenharmony_ci if (lzs->next_in != NULL) { 9967db96d56Sopenharmony_ci size_t avail_now, avail_total; 9977db96d56Sopenharmony_ci 9987db96d56Sopenharmony_ci /* Number of bytes we can append to input buffer */ 9997db96d56Sopenharmony_ci avail_now = (d->input_buffer + d->input_buffer_size) 10007db96d56Sopenharmony_ci - (lzs->next_in + lzs->avail_in); 10017db96d56Sopenharmony_ci 10027db96d56Sopenharmony_ci /* Number of bytes we can append if we move existing 10037db96d56Sopenharmony_ci contents to beginning of buffer (overwriting 10047db96d56Sopenharmony_ci consumed input) */ 10057db96d56Sopenharmony_ci avail_total = d->input_buffer_size - lzs->avail_in; 10067db96d56Sopenharmony_ci 10077db96d56Sopenharmony_ci if (avail_total < len) { 10087db96d56Sopenharmony_ci size_t offset = lzs->next_in - d->input_buffer; 10097db96d56Sopenharmony_ci uint8_t *tmp; 10107db96d56Sopenharmony_ci size_t new_size = d->input_buffer_size + len - avail_now; 10117db96d56Sopenharmony_ci 10127db96d56Sopenharmony_ci /* Assign to temporary variable first, so we don't 10137db96d56Sopenharmony_ci lose address of allocated buffer if realloc fails */ 10147db96d56Sopenharmony_ci tmp = PyMem_Realloc(d->input_buffer, new_size); 10157db96d56Sopenharmony_ci if (tmp == NULL) { 10167db96d56Sopenharmony_ci PyErr_SetNone(PyExc_MemoryError); 10177db96d56Sopenharmony_ci return NULL; 10187db96d56Sopenharmony_ci } 10197db96d56Sopenharmony_ci d->input_buffer = tmp; 10207db96d56Sopenharmony_ci d->input_buffer_size = new_size; 10217db96d56Sopenharmony_ci 10227db96d56Sopenharmony_ci lzs->next_in = d->input_buffer + offset; 10237db96d56Sopenharmony_ci } 10247db96d56Sopenharmony_ci else if (avail_now < len) { 10257db96d56Sopenharmony_ci memmove(d->input_buffer, lzs->next_in, 10267db96d56Sopenharmony_ci lzs->avail_in); 10277db96d56Sopenharmony_ci lzs->next_in = d->input_buffer; 10287db96d56Sopenharmony_ci } 10297db96d56Sopenharmony_ci memcpy((void*)(lzs->next_in + lzs->avail_in), data, len); 10307db96d56Sopenharmony_ci lzs->avail_in += len; 10317db96d56Sopenharmony_ci input_buffer_in_use = 1; 10327db96d56Sopenharmony_ci } 10337db96d56Sopenharmony_ci else { 10347db96d56Sopenharmony_ci lzs->next_in = data; 10357db96d56Sopenharmony_ci lzs->avail_in = len; 10367db96d56Sopenharmony_ci input_buffer_in_use = 0; 10377db96d56Sopenharmony_ci } 10387db96d56Sopenharmony_ci 10397db96d56Sopenharmony_ci result = decompress_buf(d, max_length); 10407db96d56Sopenharmony_ci if (result == NULL) { 10417db96d56Sopenharmony_ci lzs->next_in = NULL; 10427db96d56Sopenharmony_ci return NULL; 10437db96d56Sopenharmony_ci } 10447db96d56Sopenharmony_ci 10457db96d56Sopenharmony_ci if (d->eof) { 10467db96d56Sopenharmony_ci d->needs_input = 0; 10477db96d56Sopenharmony_ci if (lzs->avail_in > 0) { 10487db96d56Sopenharmony_ci Py_XSETREF(d->unused_data, 10497db96d56Sopenharmony_ci PyBytes_FromStringAndSize((char *)lzs->next_in, lzs->avail_in)); 10507db96d56Sopenharmony_ci if (d->unused_data == NULL) { 10517db96d56Sopenharmony_ci goto error; 10527db96d56Sopenharmony_ci } 10537db96d56Sopenharmony_ci } 10547db96d56Sopenharmony_ci } 10557db96d56Sopenharmony_ci else if (lzs->avail_in == 0) { 10567db96d56Sopenharmony_ci lzs->next_in = NULL; 10577db96d56Sopenharmony_ci 10587db96d56Sopenharmony_ci if (lzs->avail_out == 0) { 10597db96d56Sopenharmony_ci /* (avail_in==0 && avail_out==0) 10607db96d56Sopenharmony_ci Maybe lzs's internal state still have a few bytes can 10617db96d56Sopenharmony_ci be output, try to output them next time. */ 10627db96d56Sopenharmony_ci d->needs_input = 0; 10637db96d56Sopenharmony_ci 10647db96d56Sopenharmony_ci /* If max_length < 0, lzs->avail_out always > 0 */ 10657db96d56Sopenharmony_ci assert(max_length >= 0); 10667db96d56Sopenharmony_ci } else { 10677db96d56Sopenharmony_ci /* Input buffer exhausted, output buffer has space. */ 10687db96d56Sopenharmony_ci d->needs_input = 1; 10697db96d56Sopenharmony_ci } 10707db96d56Sopenharmony_ci } 10717db96d56Sopenharmony_ci else { 10727db96d56Sopenharmony_ci d->needs_input = 0; 10737db96d56Sopenharmony_ci 10747db96d56Sopenharmony_ci /* If we did not use the input buffer, we now have 10757db96d56Sopenharmony_ci to copy the tail from the caller's buffer into the 10767db96d56Sopenharmony_ci input buffer */ 10777db96d56Sopenharmony_ci if (!input_buffer_in_use) { 10787db96d56Sopenharmony_ci 10797db96d56Sopenharmony_ci /* Discard buffer if it's too small 10807db96d56Sopenharmony_ci (resizing it may needlessly copy the current contents) */ 10817db96d56Sopenharmony_ci if (d->input_buffer != NULL && 10827db96d56Sopenharmony_ci d->input_buffer_size < lzs->avail_in) { 10837db96d56Sopenharmony_ci PyMem_Free(d->input_buffer); 10847db96d56Sopenharmony_ci d->input_buffer = NULL; 10857db96d56Sopenharmony_ci } 10867db96d56Sopenharmony_ci 10877db96d56Sopenharmony_ci /* Allocate if necessary */ 10887db96d56Sopenharmony_ci if (d->input_buffer == NULL) { 10897db96d56Sopenharmony_ci d->input_buffer = PyMem_Malloc(lzs->avail_in); 10907db96d56Sopenharmony_ci if (d->input_buffer == NULL) { 10917db96d56Sopenharmony_ci PyErr_SetNone(PyExc_MemoryError); 10927db96d56Sopenharmony_ci goto error; 10937db96d56Sopenharmony_ci } 10947db96d56Sopenharmony_ci d->input_buffer_size = lzs->avail_in; 10957db96d56Sopenharmony_ci } 10967db96d56Sopenharmony_ci 10977db96d56Sopenharmony_ci /* Copy tail */ 10987db96d56Sopenharmony_ci memcpy(d->input_buffer, lzs->next_in, lzs->avail_in); 10997db96d56Sopenharmony_ci lzs->next_in = d->input_buffer; 11007db96d56Sopenharmony_ci } 11017db96d56Sopenharmony_ci } 11027db96d56Sopenharmony_ci 11037db96d56Sopenharmony_ci return result; 11047db96d56Sopenharmony_ci 11057db96d56Sopenharmony_cierror: 11067db96d56Sopenharmony_ci Py_XDECREF(result); 11077db96d56Sopenharmony_ci return NULL; 11087db96d56Sopenharmony_ci} 11097db96d56Sopenharmony_ci 11107db96d56Sopenharmony_ci/*[clinic input] 11117db96d56Sopenharmony_ci_lzma.LZMADecompressor.decompress 11127db96d56Sopenharmony_ci 11137db96d56Sopenharmony_ci data: Py_buffer 11147db96d56Sopenharmony_ci max_length: Py_ssize_t=-1 11157db96d56Sopenharmony_ci 11167db96d56Sopenharmony_ciDecompress *data*, returning uncompressed data as bytes. 11177db96d56Sopenharmony_ci 11187db96d56Sopenharmony_ciIf *max_length* is nonnegative, returns at most *max_length* bytes of 11197db96d56Sopenharmony_cidecompressed data. If this limit is reached and further output can be 11207db96d56Sopenharmony_ciproduced, *self.needs_input* will be set to ``False``. In this case, the next 11217db96d56Sopenharmony_cicall to *decompress()* may provide *data* as b'' to obtain more of the output. 11227db96d56Sopenharmony_ci 11237db96d56Sopenharmony_ciIf all of the input data was decompressed and returned (either because this 11247db96d56Sopenharmony_ciwas less than *max_length* bytes, or because *max_length* was negative), 11257db96d56Sopenharmony_ci*self.needs_input* will be set to True. 11267db96d56Sopenharmony_ci 11277db96d56Sopenharmony_ciAttempting to decompress data after the end of stream is reached raises an 11287db96d56Sopenharmony_ciEOFError. Any data found after the end of the stream is ignored and saved in 11297db96d56Sopenharmony_cithe unused_data attribute. 11307db96d56Sopenharmony_ci[clinic start generated code]*/ 11317db96d56Sopenharmony_ci 11327db96d56Sopenharmony_cistatic PyObject * 11337db96d56Sopenharmony_ci_lzma_LZMADecompressor_decompress_impl(Decompressor *self, Py_buffer *data, 11347db96d56Sopenharmony_ci Py_ssize_t max_length) 11357db96d56Sopenharmony_ci/*[clinic end generated code: output=ef4e20ec7122241d input=60c1f135820e309d]*/ 11367db96d56Sopenharmony_ci{ 11377db96d56Sopenharmony_ci PyObject *result = NULL; 11387db96d56Sopenharmony_ci 11397db96d56Sopenharmony_ci ACQUIRE_LOCK(self); 11407db96d56Sopenharmony_ci if (self->eof) 11417db96d56Sopenharmony_ci PyErr_SetString(PyExc_EOFError, "Already at end of stream"); 11427db96d56Sopenharmony_ci else 11437db96d56Sopenharmony_ci result = decompress(self, data->buf, data->len, max_length); 11447db96d56Sopenharmony_ci RELEASE_LOCK(self); 11457db96d56Sopenharmony_ci return result; 11467db96d56Sopenharmony_ci} 11477db96d56Sopenharmony_ci 11487db96d56Sopenharmony_cistatic int 11497db96d56Sopenharmony_ciDecompressor_init_raw(_lzma_state *state, lzma_stream *lzs, PyObject *filterspecs) 11507db96d56Sopenharmony_ci{ 11517db96d56Sopenharmony_ci lzma_filter filters[LZMA_FILTERS_MAX + 1]; 11527db96d56Sopenharmony_ci lzma_ret lzret; 11537db96d56Sopenharmony_ci 11547db96d56Sopenharmony_ci if (parse_filter_chain_spec(state, filters, filterspecs) == -1) { 11557db96d56Sopenharmony_ci return -1; 11567db96d56Sopenharmony_ci } 11577db96d56Sopenharmony_ci lzret = lzma_raw_decoder(lzs, filters); 11587db96d56Sopenharmony_ci free_filter_chain(filters); 11597db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) { 11607db96d56Sopenharmony_ci return -1; 11617db96d56Sopenharmony_ci } 11627db96d56Sopenharmony_ci else { 11637db96d56Sopenharmony_ci return 0; 11647db96d56Sopenharmony_ci } 11657db96d56Sopenharmony_ci} 11667db96d56Sopenharmony_ci 11677db96d56Sopenharmony_ci/*[clinic input] 11687db96d56Sopenharmony_ci_lzma.LZMADecompressor.__init__ 11697db96d56Sopenharmony_ci 11707db96d56Sopenharmony_ci format: int(c_default="FORMAT_AUTO") = FORMAT_AUTO 11717db96d56Sopenharmony_ci Specifies the container format of the input stream. If this is 11727db96d56Sopenharmony_ci FORMAT_AUTO (the default), the decompressor will automatically detect 11737db96d56Sopenharmony_ci whether the input is FORMAT_XZ or FORMAT_ALONE. Streams created with 11747db96d56Sopenharmony_ci FORMAT_RAW cannot be autodetected. 11757db96d56Sopenharmony_ci 11767db96d56Sopenharmony_ci memlimit: object = None 11777db96d56Sopenharmony_ci Limit the amount of memory used by the decompressor. This will cause 11787db96d56Sopenharmony_ci decompression to fail if the input cannot be decompressed within the 11797db96d56Sopenharmony_ci given limit. 11807db96d56Sopenharmony_ci 11817db96d56Sopenharmony_ci filters: object = None 11827db96d56Sopenharmony_ci A custom filter chain. This argument is required for FORMAT_RAW, and 11837db96d56Sopenharmony_ci not accepted with any other format. When provided, this should be a 11847db96d56Sopenharmony_ci sequence of dicts, each indicating the ID and options for a single 11857db96d56Sopenharmony_ci filter. 11867db96d56Sopenharmony_ci 11877db96d56Sopenharmony_ciCreate a decompressor object for decompressing data incrementally. 11887db96d56Sopenharmony_ci 11897db96d56Sopenharmony_ciFor one-shot decompression, use the decompress() function instead. 11907db96d56Sopenharmony_ci[clinic start generated code]*/ 11917db96d56Sopenharmony_ci 11927db96d56Sopenharmony_cistatic int 11937db96d56Sopenharmony_ci_lzma_LZMADecompressor___init___impl(Decompressor *self, int format, 11947db96d56Sopenharmony_ci PyObject *memlimit, PyObject *filters) 11957db96d56Sopenharmony_ci/*[clinic end generated code: output=3e1821f8aa36564c input=81fe684a6c2f8a27]*/ 11967db96d56Sopenharmony_ci{ 11977db96d56Sopenharmony_ci const uint32_t decoder_flags = LZMA_TELL_ANY_CHECK | LZMA_TELL_NO_CHECK; 11987db96d56Sopenharmony_ci uint64_t memlimit_ = UINT64_MAX; 11997db96d56Sopenharmony_ci lzma_ret lzret; 12007db96d56Sopenharmony_ci _lzma_state *state = PyType_GetModuleState(Py_TYPE(self)); 12017db96d56Sopenharmony_ci assert(state != NULL); 12027db96d56Sopenharmony_ci 12037db96d56Sopenharmony_ci if (memlimit != Py_None) { 12047db96d56Sopenharmony_ci if (format == FORMAT_RAW) { 12057db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 12067db96d56Sopenharmony_ci "Cannot specify memory limit with FORMAT_RAW"); 12077db96d56Sopenharmony_ci return -1; 12087db96d56Sopenharmony_ci } 12097db96d56Sopenharmony_ci memlimit_ = PyLong_AsUnsignedLongLong(memlimit); 12107db96d56Sopenharmony_ci if (PyErr_Occurred()) { 12117db96d56Sopenharmony_ci return -1; 12127db96d56Sopenharmony_ci } 12137db96d56Sopenharmony_ci } 12147db96d56Sopenharmony_ci 12157db96d56Sopenharmony_ci if (format == FORMAT_RAW && filters == Py_None) { 12167db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 12177db96d56Sopenharmony_ci "Must specify filters for FORMAT_RAW"); 12187db96d56Sopenharmony_ci return -1; 12197db96d56Sopenharmony_ci } else if (format != FORMAT_RAW && filters != Py_None) { 12207db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 12217db96d56Sopenharmony_ci "Cannot specify filters except with FORMAT_RAW"); 12227db96d56Sopenharmony_ci return -1; 12237db96d56Sopenharmony_ci } 12247db96d56Sopenharmony_ci 12257db96d56Sopenharmony_ci self->alloc.opaque = NULL; 12267db96d56Sopenharmony_ci self->alloc.alloc = PyLzma_Malloc; 12277db96d56Sopenharmony_ci self->alloc.free = PyLzma_Free; 12287db96d56Sopenharmony_ci self->lzs.allocator = &self->alloc; 12297db96d56Sopenharmony_ci self->lzs.next_in = NULL; 12307db96d56Sopenharmony_ci 12317db96d56Sopenharmony_ci PyThread_type_lock lock = PyThread_allocate_lock(); 12327db96d56Sopenharmony_ci if (lock == NULL) { 12337db96d56Sopenharmony_ci PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock"); 12347db96d56Sopenharmony_ci return -1; 12357db96d56Sopenharmony_ci } 12367db96d56Sopenharmony_ci if (self->lock != NULL) { 12377db96d56Sopenharmony_ci PyThread_free_lock(self->lock); 12387db96d56Sopenharmony_ci } 12397db96d56Sopenharmony_ci self->lock = lock; 12407db96d56Sopenharmony_ci 12417db96d56Sopenharmony_ci self->check = LZMA_CHECK_UNKNOWN; 12427db96d56Sopenharmony_ci self->needs_input = 1; 12437db96d56Sopenharmony_ci self->input_buffer = NULL; 12447db96d56Sopenharmony_ci self->input_buffer_size = 0; 12457db96d56Sopenharmony_ci Py_XSETREF(self->unused_data, PyBytes_FromStringAndSize(NULL, 0)); 12467db96d56Sopenharmony_ci if (self->unused_data == NULL) { 12477db96d56Sopenharmony_ci goto error; 12487db96d56Sopenharmony_ci } 12497db96d56Sopenharmony_ci 12507db96d56Sopenharmony_ci switch (format) { 12517db96d56Sopenharmony_ci case FORMAT_AUTO: 12527db96d56Sopenharmony_ci lzret = lzma_auto_decoder(&self->lzs, memlimit_, decoder_flags); 12537db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) { 12547db96d56Sopenharmony_ci break; 12557db96d56Sopenharmony_ci } 12567db96d56Sopenharmony_ci return 0; 12577db96d56Sopenharmony_ci 12587db96d56Sopenharmony_ci case FORMAT_XZ: 12597db96d56Sopenharmony_ci lzret = lzma_stream_decoder(&self->lzs, memlimit_, decoder_flags); 12607db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) { 12617db96d56Sopenharmony_ci break; 12627db96d56Sopenharmony_ci } 12637db96d56Sopenharmony_ci return 0; 12647db96d56Sopenharmony_ci 12657db96d56Sopenharmony_ci case FORMAT_ALONE: 12667db96d56Sopenharmony_ci self->check = LZMA_CHECK_NONE; 12677db96d56Sopenharmony_ci lzret = lzma_alone_decoder(&self->lzs, memlimit_); 12687db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) { 12697db96d56Sopenharmony_ci break; 12707db96d56Sopenharmony_ci } 12717db96d56Sopenharmony_ci return 0; 12727db96d56Sopenharmony_ci 12737db96d56Sopenharmony_ci case FORMAT_RAW: 12747db96d56Sopenharmony_ci self->check = LZMA_CHECK_NONE; 12757db96d56Sopenharmony_ci if (Decompressor_init_raw(state, &self->lzs, filters) == -1) { 12767db96d56Sopenharmony_ci break; 12777db96d56Sopenharmony_ci } 12787db96d56Sopenharmony_ci return 0; 12797db96d56Sopenharmony_ci 12807db96d56Sopenharmony_ci default: 12817db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, 12827db96d56Sopenharmony_ci "Invalid container format: %d", format); 12837db96d56Sopenharmony_ci break; 12847db96d56Sopenharmony_ci } 12857db96d56Sopenharmony_ci 12867db96d56Sopenharmony_cierror: 12877db96d56Sopenharmony_ci Py_CLEAR(self->unused_data); 12887db96d56Sopenharmony_ci PyThread_free_lock(self->lock); 12897db96d56Sopenharmony_ci self->lock = NULL; 12907db96d56Sopenharmony_ci return -1; 12917db96d56Sopenharmony_ci} 12927db96d56Sopenharmony_ci 12937db96d56Sopenharmony_cistatic void 12947db96d56Sopenharmony_ciDecompressor_dealloc(Decompressor *self) 12957db96d56Sopenharmony_ci{ 12967db96d56Sopenharmony_ci if(self->input_buffer != NULL) 12977db96d56Sopenharmony_ci PyMem_Free(self->input_buffer); 12987db96d56Sopenharmony_ci 12997db96d56Sopenharmony_ci lzma_end(&self->lzs); 13007db96d56Sopenharmony_ci Py_CLEAR(self->unused_data); 13017db96d56Sopenharmony_ci if (self->lock != NULL) { 13027db96d56Sopenharmony_ci PyThread_free_lock(self->lock); 13037db96d56Sopenharmony_ci } 13047db96d56Sopenharmony_ci PyTypeObject *tp = Py_TYPE(self); 13057db96d56Sopenharmony_ci tp->tp_free((PyObject *)self); 13067db96d56Sopenharmony_ci Py_DECREF(tp); 13077db96d56Sopenharmony_ci} 13087db96d56Sopenharmony_ci 13097db96d56Sopenharmony_cistatic int 13107db96d56Sopenharmony_ciDecompressor_traverse(Decompressor *self, visitproc visit, void *arg) 13117db96d56Sopenharmony_ci{ 13127db96d56Sopenharmony_ci Py_VISIT(Py_TYPE(self)); 13137db96d56Sopenharmony_ci return 0; 13147db96d56Sopenharmony_ci} 13157db96d56Sopenharmony_ci 13167db96d56Sopenharmony_cistatic PyMethodDef Decompressor_methods[] = { 13177db96d56Sopenharmony_ci _LZMA_LZMADECOMPRESSOR_DECOMPRESS_METHODDEF 13187db96d56Sopenharmony_ci {NULL} 13197db96d56Sopenharmony_ci}; 13207db96d56Sopenharmony_ci 13217db96d56Sopenharmony_ciPyDoc_STRVAR(Decompressor_check_doc, 13227db96d56Sopenharmony_ci"ID of the integrity check used by the input stream."); 13237db96d56Sopenharmony_ci 13247db96d56Sopenharmony_ciPyDoc_STRVAR(Decompressor_eof_doc, 13257db96d56Sopenharmony_ci"True if the end-of-stream marker has been reached."); 13267db96d56Sopenharmony_ci 13277db96d56Sopenharmony_ciPyDoc_STRVAR(Decompressor_needs_input_doc, 13287db96d56Sopenharmony_ci"True if more input is needed before more decompressed data can be produced."); 13297db96d56Sopenharmony_ci 13307db96d56Sopenharmony_ciPyDoc_STRVAR(Decompressor_unused_data_doc, 13317db96d56Sopenharmony_ci"Data found after the end of the compressed stream."); 13327db96d56Sopenharmony_ci 13337db96d56Sopenharmony_cistatic PyMemberDef Decompressor_members[] = { 13347db96d56Sopenharmony_ci {"check", T_INT, offsetof(Decompressor, check), READONLY, 13357db96d56Sopenharmony_ci Decompressor_check_doc}, 13367db96d56Sopenharmony_ci {"eof", T_BOOL, offsetof(Decompressor, eof), READONLY, 13377db96d56Sopenharmony_ci Decompressor_eof_doc}, 13387db96d56Sopenharmony_ci {"needs_input", T_BOOL, offsetof(Decompressor, needs_input), READONLY, 13397db96d56Sopenharmony_ci Decompressor_needs_input_doc}, 13407db96d56Sopenharmony_ci {"unused_data", T_OBJECT_EX, offsetof(Decompressor, unused_data), READONLY, 13417db96d56Sopenharmony_ci Decompressor_unused_data_doc}, 13427db96d56Sopenharmony_ci {NULL} 13437db96d56Sopenharmony_ci}; 13447db96d56Sopenharmony_ci 13457db96d56Sopenharmony_cistatic PyType_Slot lzma_decompressor_type_slots[] = { 13467db96d56Sopenharmony_ci {Py_tp_dealloc, Decompressor_dealloc}, 13477db96d56Sopenharmony_ci {Py_tp_methods, Decompressor_methods}, 13487db96d56Sopenharmony_ci {Py_tp_init, _lzma_LZMADecompressor___init__}, 13497db96d56Sopenharmony_ci {Py_tp_new, PyType_GenericNew}, 13507db96d56Sopenharmony_ci {Py_tp_doc, (char *)_lzma_LZMADecompressor___init____doc__}, 13517db96d56Sopenharmony_ci {Py_tp_traverse, Decompressor_traverse}, 13527db96d56Sopenharmony_ci {Py_tp_members, Decompressor_members}, 13537db96d56Sopenharmony_ci {0, 0} 13547db96d56Sopenharmony_ci}; 13557db96d56Sopenharmony_ci 13567db96d56Sopenharmony_cistatic PyType_Spec lzma_decompressor_type_spec = { 13577db96d56Sopenharmony_ci .name = "_lzma.LZMADecompressor", 13587db96d56Sopenharmony_ci .basicsize = sizeof(Decompressor), 13597db96d56Sopenharmony_ci // Calling PyType_GetModuleState() on a subclass is not safe. 13607db96d56Sopenharmony_ci // lzma_decompressor_type_spec does not have Py_TPFLAGS_BASETYPE flag 13617db96d56Sopenharmony_ci // which prevents to create a subclass. 13627db96d56Sopenharmony_ci // So calling PyType_GetModuleState() in this file is always safe. 13637db96d56Sopenharmony_ci .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), 13647db96d56Sopenharmony_ci .slots = lzma_decompressor_type_slots, 13657db96d56Sopenharmony_ci}; 13667db96d56Sopenharmony_ci 13677db96d56Sopenharmony_ci 13687db96d56Sopenharmony_ci/* Module-level functions. */ 13697db96d56Sopenharmony_ci 13707db96d56Sopenharmony_ci/*[clinic input] 13717db96d56Sopenharmony_ci_lzma.is_check_supported 13727db96d56Sopenharmony_ci check_id: int 13737db96d56Sopenharmony_ci / 13747db96d56Sopenharmony_ci 13757db96d56Sopenharmony_ciTest whether the given integrity check is supported. 13767db96d56Sopenharmony_ci 13777db96d56Sopenharmony_ciAlways returns True for CHECK_NONE and CHECK_CRC32. 13787db96d56Sopenharmony_ci[clinic start generated code]*/ 13797db96d56Sopenharmony_ci 13807db96d56Sopenharmony_cistatic PyObject * 13817db96d56Sopenharmony_ci_lzma_is_check_supported_impl(PyObject *module, int check_id) 13827db96d56Sopenharmony_ci/*[clinic end generated code: output=e4f14ba3ce2ad0a5 input=5518297b97b2318f]*/ 13837db96d56Sopenharmony_ci{ 13847db96d56Sopenharmony_ci return PyBool_FromLong(lzma_check_is_supported(check_id)); 13857db96d56Sopenharmony_ci} 13867db96d56Sopenharmony_ci 13877db96d56Sopenharmony_ciPyDoc_STRVAR(_lzma__encode_filter_properties__doc__, 13887db96d56Sopenharmony_ci"_encode_filter_properties($module, filter, /)\n" 13897db96d56Sopenharmony_ci"--\n" 13907db96d56Sopenharmony_ci"\n" 13917db96d56Sopenharmony_ci"Return a bytes object encoding the options (properties) of the filter specified by *filter* (a dict).\n" 13927db96d56Sopenharmony_ci"\n" 13937db96d56Sopenharmony_ci"The result does not include the filter ID itself, only the options."); 13947db96d56Sopenharmony_ci 13957db96d56Sopenharmony_ci#define _LZMA__ENCODE_FILTER_PROPERTIES_METHODDEF \ 13967db96d56Sopenharmony_ci {"_encode_filter_properties", (PyCFunction)_lzma__encode_filter_properties, METH_O, _lzma__encode_filter_properties__doc__}, 13977db96d56Sopenharmony_ci 13987db96d56Sopenharmony_cistatic PyObject * 13997db96d56Sopenharmony_ci_lzma__encode_filter_properties_impl(PyObject *module, lzma_filter filter); 14007db96d56Sopenharmony_ci 14017db96d56Sopenharmony_cistatic PyObject * 14027db96d56Sopenharmony_ci_lzma__encode_filter_properties(PyObject *module, PyObject *arg) 14037db96d56Sopenharmony_ci{ 14047db96d56Sopenharmony_ci PyObject *return_value = NULL; 14057db96d56Sopenharmony_ci lzma_filter filter = {LZMA_VLI_UNKNOWN, NULL}; 14067db96d56Sopenharmony_ci _lzma_state *state = get_lzma_state(module); 14077db96d56Sopenharmony_ci assert(state != NULL); 14087db96d56Sopenharmony_ci if (!lzma_filter_converter(state, arg, &filter)) { 14097db96d56Sopenharmony_ci goto exit; 14107db96d56Sopenharmony_ci } 14117db96d56Sopenharmony_ci return_value = _lzma__encode_filter_properties_impl(module, filter); 14127db96d56Sopenharmony_ci 14137db96d56Sopenharmony_ciexit: 14147db96d56Sopenharmony_ci /* Cleanup for filter */ 14157db96d56Sopenharmony_ci if (filter.id != LZMA_VLI_UNKNOWN) { 14167db96d56Sopenharmony_ci PyMem_Free(filter.options); 14177db96d56Sopenharmony_ci } 14187db96d56Sopenharmony_ci 14197db96d56Sopenharmony_ci return return_value; 14207db96d56Sopenharmony_ci} 14217db96d56Sopenharmony_ci 14227db96d56Sopenharmony_cistatic PyObject * 14237db96d56Sopenharmony_ci_lzma__encode_filter_properties_impl(PyObject *module, lzma_filter filter) 14247db96d56Sopenharmony_ci{ 14257db96d56Sopenharmony_ci lzma_ret lzret; 14267db96d56Sopenharmony_ci uint32_t encoded_size; 14277db96d56Sopenharmony_ci PyObject *result = NULL; 14287db96d56Sopenharmony_ci _lzma_state *state = get_lzma_state(module); 14297db96d56Sopenharmony_ci assert(state != NULL); 14307db96d56Sopenharmony_ci 14317db96d56Sopenharmony_ci lzret = lzma_properties_size(&encoded_size, &filter); 14327db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) 14337db96d56Sopenharmony_ci goto error; 14347db96d56Sopenharmony_ci 14357db96d56Sopenharmony_ci result = PyBytes_FromStringAndSize(NULL, encoded_size); 14367db96d56Sopenharmony_ci if (result == NULL) 14377db96d56Sopenharmony_ci goto error; 14387db96d56Sopenharmony_ci 14397db96d56Sopenharmony_ci lzret = lzma_properties_encode( 14407db96d56Sopenharmony_ci &filter, (uint8_t *)PyBytes_AS_STRING(result)); 14417db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) { 14427db96d56Sopenharmony_ci goto error; 14437db96d56Sopenharmony_ci } 14447db96d56Sopenharmony_ci 14457db96d56Sopenharmony_ci return result; 14467db96d56Sopenharmony_ci 14477db96d56Sopenharmony_cierror: 14487db96d56Sopenharmony_ci Py_XDECREF(result); 14497db96d56Sopenharmony_ci return NULL; 14507db96d56Sopenharmony_ci} 14517db96d56Sopenharmony_ci 14527db96d56Sopenharmony_ci 14537db96d56Sopenharmony_ci/*[clinic input] 14547db96d56Sopenharmony_ci_lzma._decode_filter_properties 14557db96d56Sopenharmony_ci filter_id: lzma_vli 14567db96d56Sopenharmony_ci encoded_props: Py_buffer 14577db96d56Sopenharmony_ci / 14587db96d56Sopenharmony_ci 14597db96d56Sopenharmony_ciReturn a bytes object encoding the options (properties) of the filter specified by *filter* (a dict). 14607db96d56Sopenharmony_ci 14617db96d56Sopenharmony_ciThe result does not include the filter ID itself, only the options. 14627db96d56Sopenharmony_ci[clinic start generated code]*/ 14637db96d56Sopenharmony_ci 14647db96d56Sopenharmony_cistatic PyObject * 14657db96d56Sopenharmony_ci_lzma__decode_filter_properties_impl(PyObject *module, lzma_vli filter_id, 14667db96d56Sopenharmony_ci Py_buffer *encoded_props) 14677db96d56Sopenharmony_ci/*[clinic end generated code: output=714fd2ef565d5c60 input=246410800782160c]*/ 14687db96d56Sopenharmony_ci{ 14697db96d56Sopenharmony_ci lzma_filter filter; 14707db96d56Sopenharmony_ci lzma_ret lzret; 14717db96d56Sopenharmony_ci PyObject *result = NULL; 14727db96d56Sopenharmony_ci filter.id = filter_id; 14737db96d56Sopenharmony_ci _lzma_state *state = get_lzma_state(module); 14747db96d56Sopenharmony_ci assert(state != NULL); 14757db96d56Sopenharmony_ci 14767db96d56Sopenharmony_ci lzret = lzma_properties_decode( 14777db96d56Sopenharmony_ci &filter, NULL, encoded_props->buf, encoded_props->len); 14787db96d56Sopenharmony_ci if (catch_lzma_error(state, lzret)) { 14797db96d56Sopenharmony_ci return NULL; 14807db96d56Sopenharmony_ci } 14817db96d56Sopenharmony_ci 14827db96d56Sopenharmony_ci result = build_filter_spec(&filter); 14837db96d56Sopenharmony_ci 14847db96d56Sopenharmony_ci /* We use vanilla free() here instead of PyMem_Free() - filter.options was 14857db96d56Sopenharmony_ci allocated by lzma_properties_decode() using the default allocator. */ 14867db96d56Sopenharmony_ci free(filter.options); 14877db96d56Sopenharmony_ci return result; 14887db96d56Sopenharmony_ci} 14897db96d56Sopenharmony_ci 14907db96d56Sopenharmony_ci/* Some of our constants are more than 32 bits wide, so PyModule_AddIntConstant 14917db96d56Sopenharmony_ci would not work correctly on platforms with 32-bit longs. */ 14927db96d56Sopenharmony_cistatic int 14937db96d56Sopenharmony_cimodule_add_int_constant(PyObject *m, const char *name, long long value) 14947db96d56Sopenharmony_ci{ 14957db96d56Sopenharmony_ci PyObject *o = PyLong_FromLongLong(value); 14967db96d56Sopenharmony_ci if (o == NULL) { 14977db96d56Sopenharmony_ci return -1; 14987db96d56Sopenharmony_ci } 14997db96d56Sopenharmony_ci if (PyModule_AddObject(m, name, o) == 0) { 15007db96d56Sopenharmony_ci return 0; 15017db96d56Sopenharmony_ci } 15027db96d56Sopenharmony_ci Py_DECREF(o); 15037db96d56Sopenharmony_ci return -1; 15047db96d56Sopenharmony_ci} 15057db96d56Sopenharmony_ci 15067db96d56Sopenharmony_cistatic int 15077db96d56Sopenharmony_cilzma_exec(PyObject *module) 15087db96d56Sopenharmony_ci{ 15097db96d56Sopenharmony_ci#define ADD_INT_PREFIX_MACRO(module, macro) \ 15107db96d56Sopenharmony_ci do { \ 15117db96d56Sopenharmony_ci if (module_add_int_constant(module, #macro, LZMA_ ## macro) < 0) { \ 15127db96d56Sopenharmony_ci return -1; \ 15137db96d56Sopenharmony_ci } \ 15147db96d56Sopenharmony_ci } while(0) 15157db96d56Sopenharmony_ci 15167db96d56Sopenharmony_ci#define ADD_INT_MACRO(module, macro) \ 15177db96d56Sopenharmony_ci do { \ 15187db96d56Sopenharmony_ci if (PyModule_AddIntMacro(module, macro) < 0) { \ 15197db96d56Sopenharmony_ci return -1; \ 15207db96d56Sopenharmony_ci } \ 15217db96d56Sopenharmony_ci } while (0) 15227db96d56Sopenharmony_ci 15237db96d56Sopenharmony_ci 15247db96d56Sopenharmony_ci _lzma_state *state = get_lzma_state(module); 15257db96d56Sopenharmony_ci 15267db96d56Sopenharmony_ci state->empty_tuple = PyTuple_New(0); 15277db96d56Sopenharmony_ci if (state->empty_tuple == NULL) { 15287db96d56Sopenharmony_ci return -1; 15297db96d56Sopenharmony_ci } 15307db96d56Sopenharmony_ci 15317db96d56Sopenharmony_ci ADD_INT_MACRO(module, FORMAT_AUTO); 15327db96d56Sopenharmony_ci ADD_INT_MACRO(module, FORMAT_XZ); 15337db96d56Sopenharmony_ci ADD_INT_MACRO(module, FORMAT_ALONE); 15347db96d56Sopenharmony_ci ADD_INT_MACRO(module, FORMAT_RAW); 15357db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, CHECK_NONE); 15367db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, CHECK_CRC32); 15377db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, CHECK_CRC64); 15387db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, CHECK_SHA256); 15397db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, CHECK_ID_MAX); 15407db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, CHECK_UNKNOWN); 15417db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, FILTER_LZMA1); 15427db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, FILTER_LZMA2); 15437db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, FILTER_DELTA); 15447db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, FILTER_X86); 15457db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, FILTER_IA64); 15467db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, FILTER_ARM); 15477db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, FILTER_ARMTHUMB); 15487db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, FILTER_SPARC); 15497db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, FILTER_POWERPC); 15507db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, MF_HC3); 15517db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, MF_HC4); 15527db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, MF_BT2); 15537db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, MF_BT3); 15547db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, MF_BT4); 15557db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, MODE_FAST); 15567db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, MODE_NORMAL); 15577db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, PRESET_DEFAULT); 15587db96d56Sopenharmony_ci ADD_INT_PREFIX_MACRO(module, PRESET_EXTREME); 15597db96d56Sopenharmony_ci 15607db96d56Sopenharmony_ci state->error = PyErr_NewExceptionWithDoc("_lzma.LZMAError", "Call to liblzma failed.", NULL, NULL); 15617db96d56Sopenharmony_ci if (state->error == NULL) { 15627db96d56Sopenharmony_ci return -1; 15637db96d56Sopenharmony_ci } 15647db96d56Sopenharmony_ci 15657db96d56Sopenharmony_ci if (PyModule_AddType(module, (PyTypeObject *)state->error) < 0) { 15667db96d56Sopenharmony_ci return -1; 15677db96d56Sopenharmony_ci } 15687db96d56Sopenharmony_ci 15697db96d56Sopenharmony_ci 15707db96d56Sopenharmony_ci state->lzma_compressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, 15717db96d56Sopenharmony_ci &lzma_compressor_type_spec, NULL); 15727db96d56Sopenharmony_ci if (state->lzma_compressor_type == NULL) { 15737db96d56Sopenharmony_ci return -1; 15747db96d56Sopenharmony_ci } 15757db96d56Sopenharmony_ci 15767db96d56Sopenharmony_ci if (PyModule_AddType(module, state->lzma_compressor_type) < 0) { 15777db96d56Sopenharmony_ci return -1; 15787db96d56Sopenharmony_ci } 15797db96d56Sopenharmony_ci 15807db96d56Sopenharmony_ci state->lzma_decompressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, 15817db96d56Sopenharmony_ci &lzma_decompressor_type_spec, NULL); 15827db96d56Sopenharmony_ci if (state->lzma_decompressor_type == NULL) { 15837db96d56Sopenharmony_ci return -1; 15847db96d56Sopenharmony_ci } 15857db96d56Sopenharmony_ci 15867db96d56Sopenharmony_ci if (PyModule_AddType(module, state->lzma_decompressor_type) < 0) { 15877db96d56Sopenharmony_ci return -1; 15887db96d56Sopenharmony_ci } 15897db96d56Sopenharmony_ci 15907db96d56Sopenharmony_ci return 0; 15917db96d56Sopenharmony_ci} 15927db96d56Sopenharmony_ci 15937db96d56Sopenharmony_cistatic PyMethodDef lzma_methods[] = { 15947db96d56Sopenharmony_ci _LZMA_IS_CHECK_SUPPORTED_METHODDEF 15957db96d56Sopenharmony_ci _LZMA__ENCODE_FILTER_PROPERTIES_METHODDEF 15967db96d56Sopenharmony_ci _LZMA__DECODE_FILTER_PROPERTIES_METHODDEF 15977db96d56Sopenharmony_ci {NULL} 15987db96d56Sopenharmony_ci}; 15997db96d56Sopenharmony_ci 16007db96d56Sopenharmony_cistatic PyModuleDef_Slot lzma_slots[] = { 16017db96d56Sopenharmony_ci {Py_mod_exec, lzma_exec}, 16027db96d56Sopenharmony_ci {0, NULL} 16037db96d56Sopenharmony_ci}; 16047db96d56Sopenharmony_ci 16057db96d56Sopenharmony_cistatic int 16067db96d56Sopenharmony_cilzma_traverse(PyObject *module, visitproc visit, void *arg) 16077db96d56Sopenharmony_ci{ 16087db96d56Sopenharmony_ci _lzma_state *state = get_lzma_state(module); 16097db96d56Sopenharmony_ci Py_VISIT(state->lzma_compressor_type); 16107db96d56Sopenharmony_ci Py_VISIT(state->lzma_decompressor_type); 16117db96d56Sopenharmony_ci Py_VISIT(state->error); 16127db96d56Sopenharmony_ci Py_VISIT(state->empty_tuple); 16137db96d56Sopenharmony_ci return 0; 16147db96d56Sopenharmony_ci} 16157db96d56Sopenharmony_ci 16167db96d56Sopenharmony_cistatic int 16177db96d56Sopenharmony_cilzma_clear(PyObject *module) 16187db96d56Sopenharmony_ci{ 16197db96d56Sopenharmony_ci _lzma_state *state = get_lzma_state(module); 16207db96d56Sopenharmony_ci Py_CLEAR(state->lzma_compressor_type); 16217db96d56Sopenharmony_ci Py_CLEAR(state->lzma_decompressor_type); 16227db96d56Sopenharmony_ci Py_CLEAR(state->error); 16237db96d56Sopenharmony_ci Py_CLEAR(state->empty_tuple); 16247db96d56Sopenharmony_ci return 0; 16257db96d56Sopenharmony_ci} 16267db96d56Sopenharmony_ci 16277db96d56Sopenharmony_cistatic void 16287db96d56Sopenharmony_cilzma_free(void *module) 16297db96d56Sopenharmony_ci{ 16307db96d56Sopenharmony_ci lzma_clear((PyObject *)module); 16317db96d56Sopenharmony_ci} 16327db96d56Sopenharmony_ci 16337db96d56Sopenharmony_cistatic PyModuleDef _lzmamodule = { 16347db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 16357db96d56Sopenharmony_ci .m_name = "_lzma", 16367db96d56Sopenharmony_ci .m_size = sizeof(_lzma_state), 16377db96d56Sopenharmony_ci .m_methods = lzma_methods, 16387db96d56Sopenharmony_ci .m_slots = lzma_slots, 16397db96d56Sopenharmony_ci .m_traverse = lzma_traverse, 16407db96d56Sopenharmony_ci .m_clear = lzma_clear, 16417db96d56Sopenharmony_ci .m_free = lzma_free, 16427db96d56Sopenharmony_ci}; 16437db96d56Sopenharmony_ci 16447db96d56Sopenharmony_ciPyMODINIT_FUNC 16457db96d56Sopenharmony_ciPyInit__lzma(void) 16467db96d56Sopenharmony_ci{ 16477db96d56Sopenharmony_ci return PyModuleDef_Init(&_lzmamodule); 16487db96d56Sopenharmony_ci} 1649