comparison contrib/python-zstandard/c-ext/decompressionwriter.c @ 37495:b1fb341d8a61

zstandard: vendor python-zstandard 0.9.0 This was just released. It features a number of goodies. More info at https://gregoryszorc.com/blog/2018/04/09/release-of-python-zstandard-0.9/. The clang-format ignore list was updated to reflect the new source of files. The project contains a vendored copy of zstandard 1.3.4. The old version was 1.1.3. One of the changes between those versions is that zstandard is now dual licensed BSD + GPLv2 and the patent rights grant has been removed. Good riddance. The API should be backwards compatible. So no changes in core should be needed. However, there were a number of changes in the library that we'll want to adapt to. Those will be addressed in subsequent commits. Differential Revision: https://phab.mercurial-scm.org/D3198
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 09 Apr 2018 10:13:29 -0700
parents e0dc40530c5a
children 675775c33ab6
comparison
equal deleted inserted replaced
37494:1ce7a55b09d1 37495:b1fb341d8a61
25 if (self->entered) { 25 if (self->entered) {
26 PyErr_SetString(ZstdError, "cannot __enter__ multiple times"); 26 PyErr_SetString(ZstdError, "cannot __enter__ multiple times");
27 return NULL; 27 return NULL;
28 } 28 }
29 29
30 if (0 != init_dstream(self->decompressor)) { 30 if (ensure_dctx(self->decompressor, 1)) {
31 return NULL; 31 return NULL;
32 } 32 }
33 33
34 self->entered = 1; 34 self->entered = 1;
35 35
42 42
43 Py_RETURN_FALSE; 43 Py_RETURN_FALSE;
44 } 44 }
45 45
46 static PyObject* ZstdDecompressionWriter_memory_size(ZstdDecompressionWriter* self) { 46 static PyObject* ZstdDecompressionWriter_memory_size(ZstdDecompressionWriter* self) {
47 if (!self->decompressor->dstream) { 47 return PyLong_FromSize_t(ZSTD_sizeof_DCtx(self->decompressor->dctx));
48 PyErr_SetString(ZstdError, "cannot determine size of inactive decompressor; "
49 "call when context manager is active");
50 return NULL;
51 }
52
53 return PyLong_FromSize_t(ZSTD_sizeof_DStream(self->decompressor->dstream));
54 } 48 }
55 49
56 static PyObject* ZstdDecompressionWriter_write(ZstdDecompressionWriter* self, PyObject* args) { 50 static PyObject* ZstdDecompressionWriter_write(ZstdDecompressionWriter* self, PyObject* args, PyObject* kwargs) {
57 const char* source; 51 static char* kwlist[] = {
58 Py_ssize_t sourceSize; 52 "data",
53 NULL
54 };
55
56 PyObject* result = NULL;
57 Py_buffer source;
59 size_t zresult = 0; 58 size_t zresult = 0;
60 ZSTD_inBuffer input; 59 ZSTD_inBuffer input;
61 ZSTD_outBuffer output; 60 ZSTD_outBuffer output;
62 PyObject* res; 61 PyObject* res;
63 Py_ssize_t totalWrite = 0; 62 Py_ssize_t totalWrite = 0;
64 63
65 #if PY_MAJOR_VERSION >= 3 64 #if PY_MAJOR_VERSION >= 3
66 if (!PyArg_ParseTuple(args, "y#:write", &source, &sourceSize)) { 65 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*:write",
67 #else 66 #else
68 if (!PyArg_ParseTuple(args, "s#:write", &source, &sourceSize)) { 67 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*:write",
69 #endif 68 #endif
69 kwlist, &source)) {
70 return NULL; 70 return NULL;
71 }
72
73 if (!PyBuffer_IsContiguous(&source, 'C') || source.ndim > 1) {
74 PyErr_SetString(PyExc_ValueError,
75 "data buffer should be contiguous and have at most one dimension");
76 goto finally;
71 } 77 }
72 78
73 if (!self->entered) { 79 if (!self->entered) {
74 PyErr_SetString(ZstdError, "write must be called from an active context manager"); 80 PyErr_SetString(ZstdError, "write must be called from an active context manager");
75 return NULL; 81 goto finally;
76 } 82 }
77
78 assert(self->decompressor->dstream);
79 83
80 output.dst = PyMem_Malloc(self->outSize); 84 output.dst = PyMem_Malloc(self->outSize);
81 if (!output.dst) { 85 if (!output.dst) {
82 return PyErr_NoMemory(); 86 PyErr_NoMemory();
87 goto finally;
83 } 88 }
84 output.size = self->outSize; 89 output.size = self->outSize;
85 output.pos = 0; 90 output.pos = 0;
86 91
87 input.src = source; 92 input.src = source.buf;
88 input.size = sourceSize; 93 input.size = source.len;
89 input.pos = 0; 94 input.pos = 0;
90 95
91 while ((ssize_t)input.pos < sourceSize) { 96 while ((ssize_t)input.pos < source.len) {
92 Py_BEGIN_ALLOW_THREADS 97 Py_BEGIN_ALLOW_THREADS
93 zresult = ZSTD_decompressStream(self->decompressor->dstream, &output, &input); 98 zresult = ZSTD_decompress_generic(self->decompressor->dctx, &output, &input);
94 Py_END_ALLOW_THREADS 99 Py_END_ALLOW_THREADS
95 100
96 if (ZSTD_isError(zresult)) { 101 if (ZSTD_isError(zresult)) {
97 PyMem_Free(output.dst); 102 PyMem_Free(output.dst);
98 PyErr_Format(ZstdError, "zstd decompress error: %s", 103 PyErr_Format(ZstdError, "zstd decompress error: %s",
99 ZSTD_getErrorName(zresult)); 104 ZSTD_getErrorName(zresult));
100 return NULL; 105 goto finally;
101 } 106 }
102 107
103 if (output.pos) { 108 if (output.pos) {
104 #if PY_MAJOR_VERSION >= 3 109 #if PY_MAJOR_VERSION >= 3
105 res = PyObject_CallMethod(self->writer, "write", "y#", 110 res = PyObject_CallMethod(self->writer, "write", "y#",
113 } 118 }
114 } 119 }
115 120
116 PyMem_Free(output.dst); 121 PyMem_Free(output.dst);
117 122
118 return PyLong_FromSsize_t(totalWrite); 123 result = PyLong_FromSsize_t(totalWrite);
124
125 finally:
126 PyBuffer_Release(&source);
127 return result;
119 } 128 }
120 129
121 static PyMethodDef ZstdDecompressionWriter_methods[] = { 130 static PyMethodDef ZstdDecompressionWriter_methods[] = {
122 { "__enter__", (PyCFunction)ZstdDecompressionWriter_enter, METH_NOARGS, 131 { "__enter__", (PyCFunction)ZstdDecompressionWriter_enter, METH_NOARGS,
123 PyDoc_STR("Enter a decompression context.") }, 132 PyDoc_STR("Enter a decompression context.") },
124 { "__exit__", (PyCFunction)ZstdDecompressionWriter_exit, METH_VARARGS, 133 { "__exit__", (PyCFunction)ZstdDecompressionWriter_exit, METH_VARARGS,
125 PyDoc_STR("Exit a decompression context.") }, 134 PyDoc_STR("Exit a decompression context.") },
126 { "memory_size", (PyCFunction)ZstdDecompressionWriter_memory_size, METH_NOARGS, 135 { "memory_size", (PyCFunction)ZstdDecompressionWriter_memory_size, METH_NOARGS,
127 PyDoc_STR("Obtain the memory size in bytes of the underlying decompressor.") }, 136 PyDoc_STR("Obtain the memory size in bytes of the underlying decompressor.") },
128 { "write", (PyCFunction)ZstdDecompressionWriter_write, METH_VARARGS, 137 { "write", (PyCFunction)ZstdDecompressionWriter_write, METH_VARARGS | METH_KEYWORDS,
129 PyDoc_STR("Compress data") }, 138 PyDoc_STR("Compress data") },
130 { NULL, NULL } 139 { NULL, NULL }
131 }; 140 };
132 141
133 PyTypeObject ZstdDecompressionWriterType = { 142 PyTypeObject ZstdDecompressionWriterType = {