From a629289e3297bcfd25648293df3e1d6dfd59df24 Mon Sep 17 00:00:00 2001 From: Eugene Kliuchnikov Date: Mon, 28 Aug 2017 11:31:29 +0200 Subject: Update (#590) * add transpiled JS decoder * make PY wrapper accept memview * fix dictionary generator * speedup compression of RLEish data --- python/README.md | 2 ++ python/_brotli.cc | 54 +++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 17 deletions(-) (limited to 'python') diff --git a/python/README.md b/python/README.md index 3b0d8b2..6a9068a 100644 --- a/python/README.md +++ b/python/README.md @@ -1,6 +1,8 @@ This directory contains the code for the Python `brotli` module, `bro.py` tool, and roundtrip tests. +Only Python 2.7+ is supported. + We provide a `Makefile` to simplify common development commands. ### Installation diff --git a/python/_brotli.cc b/python/_brotli.cc index d17b90d..a6f925e 100644 --- a/python/_brotli.cc +++ b/python/_brotli.cc @@ -88,7 +88,8 @@ static int lgblock_convertor(PyObject *o, int *lgblock) { } static BROTLI_BOOL compress_stream(BrotliEncoderState* enc, BrotliEncoderOperation op, - std::vector* output, uint8_t* input, size_t input_length) { + std::vector* output, + uint8_t* input, size_t input_length) { BROTLI_BOOL ok = BROTLI_TRUE; Py_BEGIN_ALLOW_THREADS @@ -222,11 +223,15 @@ PyDoc_STRVAR(brotli_Compressor_process_doc, static PyObject* brotli_Compressor_process(brotli_Compressor *self, PyObject *args) { PyObject* ret = NULL; std::vector output; - uint8_t* input; - size_t input_length; + Py_buffer input; BROTLI_BOOL ok = BROTLI_TRUE; - ok = (BROTLI_BOOL)PyArg_ParseTuple(args, "s#:process", &input, &input_length); +#if PY_MAJOR_VERSION >= 3 + ok = (BROTLI_BOOL)PyArg_ParseTuple(args, "y*:process", &input); +#else + ok = (BROTLI_BOOL)PyArg_ParseTuple(args, "s*:process", &input); +#endif + if (!ok) return NULL; @@ -236,9 +241,10 @@ static PyObject* brotli_Compressor_process(brotli_Compressor *self, PyObject *ar } ok = compress_stream(self->enc, BROTLI_OPERATION_PROCESS, - &output, input, input_length); + &output, static_cast(input.buf), input.len); end: + PyBuffer_Release(&input); if (ok) { ret = PyBytes_FromStringAndSize((char*)(output.size() ? &output[0] : NULL), output.size()); } else { @@ -387,7 +393,8 @@ static PyTypeObject brotli_CompressorType = { }; static BROTLI_BOOL decompress_stream(BrotliDecoderState* dec, - std::vector* output, uint8_t* input, size_t input_length) { + std::vector* output, + uint8_t* input, size_t input_length) { BROTLI_BOOL ok = BROTLI_TRUE; Py_BEGIN_ALLOW_THREADS @@ -485,11 +492,15 @@ PyDoc_STRVAR(brotli_Decompressor_process_doc, static PyObject* brotli_Decompressor_process(brotli_Decompressor *self, PyObject *args) { PyObject* ret = NULL; std::vector output; - uint8_t* input; - size_t input_length; + Py_buffer input; BROTLI_BOOL ok = BROTLI_TRUE; - ok = (BROTLI_BOOL)PyArg_ParseTuple(args, "s#:process", &input, &input_length); +#if PY_MAJOR_VERSION >= 3 + ok = (BROTLI_BOOL)PyArg_ParseTuple(args, "y*:process", &input); +#else + ok = (BROTLI_BOOL)PyArg_ParseTuple(args, "s*:process", &input); +#endif + if (!ok) return NULL; @@ -498,10 +509,10 @@ static PyObject* brotli_Decompressor_process(brotli_Decompressor *self, PyObject goto end; } - ok = decompress_stream(self->dec, - &output, input, input_length); + ok = decompress_stream(self->dec, &output, static_cast(input.buf), input.len); end: + PyBuffer_Release(&input); if (ok) { ret = PyBytes_FromStringAndSize((char*)(output.empty() ? NULL : &output[0]), output.size()); } else { @@ -625,15 +636,21 @@ PyDoc_STRVAR(brotli_decompress__doc__, static PyObject* brotli_decompress(PyObject *self, PyObject *args, PyObject *keywds) { PyObject *ret = NULL; - const uint8_t *input; - size_t length; + Py_buffer input; + const uint8_t* next_in; + size_t available_in; int ok; static const char *kwlist[] = {"string", NULL}; - ok = PyArg_ParseTupleAndKeywords(args, keywds, "s#|:decompress", - const_cast(kwlist), - &input, &length); +#if PY_MAJOR_VERSION >= 3 + ok = PyArg_ParseTupleAndKeywords(args, keywds, "y*|:decompress", + const_cast(kwlist), &input); +#else + ok = PyArg_ParseTupleAndKeywords(args, keywds, "s*|:decompress", + const_cast(kwlist), &input); +#endif + if (!ok) return NULL; @@ -645,9 +662,11 @@ static PyObject* brotli_decompress(PyObject *self, PyObject *args, PyObject *key BrotliDecoderState* state = BrotliDecoderCreateInstance(0, 0, 0); BrotliDecoderResult result = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; + next_in = static_cast(input.buf); + available_in = input.len; while (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { size_t available_out = 0; - result = BrotliDecoderDecompressStream(state, &length, &input, + result = BrotliDecoderDecompressStream(state, &available_in, &next_in, &available_out, 0, 0); const uint8_t* next_out = BrotliDecoderTakeOutput(state, &available_out); if (available_out != 0) @@ -659,6 +678,7 @@ static PyObject* brotli_decompress(PyObject *self, PyObject *args, PyObject *key Py_END_ALLOW_THREADS /* <<< Pure C block end. Python GIL reacquired. */ + PyBuffer_Release(&input); if (ok) { ret = PyBytes_FromStringAndSize((char*)(output.size() ? &output[0] : NULL), output.size()); } else { -- cgit v1.1