Mercurial > hg
view 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 |
line wrap: on
line source
/** * Copyright (c) 2016-present, Gregory Szorc * All rights reserved. * * This software may be modified and distributed under the terms * of the BSD license. See the LICENSE file for details. */ #include "python-zstandard.h" extern PyObject* ZstdError; PyDoc_STRVAR(ZstdDecompressionWriter__doc, """A context manager used for writing decompressed output.\n" ); static void ZstdDecompressionWriter_dealloc(ZstdDecompressionWriter* self) { Py_XDECREF(self->decompressor); Py_XDECREF(self->writer); PyObject_Del(self); } static PyObject* ZstdDecompressionWriter_enter(ZstdDecompressionWriter* self) { if (self->entered) { PyErr_SetString(ZstdError, "cannot __enter__ multiple times"); return NULL; } if (ensure_dctx(self->decompressor, 1)) { return NULL; } self->entered = 1; Py_INCREF(self); return (PyObject*)self; } static PyObject* ZstdDecompressionWriter_exit(ZstdDecompressionWriter* self, PyObject* args) { self->entered = 0; Py_RETURN_FALSE; } static PyObject* ZstdDecompressionWriter_memory_size(ZstdDecompressionWriter* self) { return PyLong_FromSize_t(ZSTD_sizeof_DCtx(self->decompressor->dctx)); } static PyObject* ZstdDecompressionWriter_write(ZstdDecompressionWriter* self, PyObject* args, PyObject* kwargs) { static char* kwlist[] = { "data", NULL }; PyObject* result = NULL; Py_buffer source; size_t zresult = 0; ZSTD_inBuffer input; ZSTD_outBuffer output; PyObject* res; Py_ssize_t totalWrite = 0; #if PY_MAJOR_VERSION >= 3 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*:write", #else if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*:write", #endif kwlist, &source)) { return NULL; } if (!PyBuffer_IsContiguous(&source, 'C') || source.ndim > 1) { PyErr_SetString(PyExc_ValueError, "data buffer should be contiguous and have at most one dimension"); goto finally; } if (!self->entered) { PyErr_SetString(ZstdError, "write must be called from an active context manager"); goto finally; } output.dst = PyMem_Malloc(self->outSize); if (!output.dst) { PyErr_NoMemory(); goto finally; } output.size = self->outSize; output.pos = 0; input.src = source.buf; input.size = source.len; input.pos = 0; while ((ssize_t)input.pos < source.len) { Py_BEGIN_ALLOW_THREADS zresult = ZSTD_decompress_generic(self->decompressor->dctx, &output, &input); Py_END_ALLOW_THREADS if (ZSTD_isError(zresult)) { PyMem_Free(output.dst); PyErr_Format(ZstdError, "zstd decompress error: %s", ZSTD_getErrorName(zresult)); goto finally; } if (output.pos) { #if PY_MAJOR_VERSION >= 3 res = PyObject_CallMethod(self->writer, "write", "y#", #else res = PyObject_CallMethod(self->writer, "write", "s#", #endif output.dst, output.pos); Py_XDECREF(res); totalWrite += output.pos; output.pos = 0; } } PyMem_Free(output.dst); result = PyLong_FromSsize_t(totalWrite); finally: PyBuffer_Release(&source); return result; } static PyMethodDef ZstdDecompressionWriter_methods[] = { { "__enter__", (PyCFunction)ZstdDecompressionWriter_enter, METH_NOARGS, PyDoc_STR("Enter a decompression context.") }, { "__exit__", (PyCFunction)ZstdDecompressionWriter_exit, METH_VARARGS, PyDoc_STR("Exit a decompression context.") }, { "memory_size", (PyCFunction)ZstdDecompressionWriter_memory_size, METH_NOARGS, PyDoc_STR("Obtain the memory size in bytes of the underlying decompressor.") }, { "write", (PyCFunction)ZstdDecompressionWriter_write, METH_VARARGS | METH_KEYWORDS, PyDoc_STR("Compress data") }, { NULL, NULL } }; PyTypeObject ZstdDecompressionWriterType = { PyVarObject_HEAD_INIT(NULL, 0) "zstd.ZstdDecompressionWriter", /* tp_name */ sizeof(ZstdDecompressionWriter),/* tp_basicsize */ 0, /* tp_itemsize */ (destructor)ZstdDecompressionWriter_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ ZstdDecompressionWriter__doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ZstdDecompressionWriter_methods,/* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ }; void decompressionwriter_module_init(PyObject* mod) { Py_TYPE(&ZstdDecompressionWriterType) = &PyType_Type; if (PyType_Ready(&ZstdDecompressionWriterType) < 0) { return; } }