diff --git a/_crc32c.c b/_crc32c.c index 1d0f58f..4462d06 100644 --- a/_crc32c.c +++ b/_crc32c.c @@ -37,10 +37,13 @@ static crc_function crc_fn; int is_big_endian; static -PyObject* crc32c_crc32c(PyObject *self, PyObject *args) { +PyObject* crc32c_crc32c(PyObject *self, PyObject *args, PyObject *kwargs) { Py_buffer pbin; unsigned char *bin_data = NULL; uint32_t crc = 0U, result; + int release_gil = -1; + + static char *kwlist[] = {"inp", "crc", "release_gil", NULL}; /* In python 3 we accept only bytes-like objects */ const char *format = @@ -49,31 +52,37 @@ PyObject* crc32c_crc32c(PyObject *self, PyObject *args) { #else "s*" #endif - "|I:crc32"; + "|Ii:crc32"; - if (!PyArg_ParseTuple(args, format, &pbin, &crc) ) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwlist, &pbin, &crc, &release_gil) ) return NULL; bin_data = pbin.buf; - Py_BEGIN_ALLOW_THREADS - crc ^= 0xffffffff; - result = crc_fn(crc, bin_data, pbin.len); - result ^= 0xffffffff; - Py_END_ALLOW_THREADS + if ((release_gil < 0 && pbin.len >= 32768) || release_gil >= 1) { + Py_BEGIN_ALLOW_THREADS + crc ^= 0xffffffff; + result = crc_fn(crc, bin_data, pbin.len); + result ^= 0xffffffff; + Py_END_ALLOW_THREADS + } else { + crc ^= 0xffffffff; + result = crc_fn(crc, bin_data, pbin.len); + result ^= 0xffffffff; + } PyBuffer_Release(&pbin); return PyLong_FromUnsignedLong(result); } static -PyObject *crc32c_crc32(PyObject *self, PyObject *args) +PyObject *crc32c_crc32(PyObject *self, PyObject *args, PyObject *kwargs) { if (PyErr_WarnEx(PyExc_DeprecationWarning, - "crc32c.crc32 will be eventually removed, use crc32c.crc32c instead", - 1) == -1) { + "crc32c.crc32 will be eventually removed, use crc32c.crc32c instead", + 1) == -1) { return NULL; } - return crc32c_crc32c(self, args); + return crc32c_crc32c(self, args, kwargs); } /* The different values the SW mode preference can take */ @@ -103,8 +112,8 @@ static enum crc32c_sw_mode get_sw_mode(void) } static PyMethodDef CRC32CMethods[] = { - {"crc32", crc32c_crc32, METH_VARARGS, "Calculate crc32c incrementally (deprecated)"}, - {"crc32c", crc32c_crc32c, METH_VARARGS, "Calculate crc32c incrementally"}, + {"crc32", (PyCFunction)crc32c_crc32, METH_VARARGS | METH_KEYWORDS, "Calculate crc32c incrementally (deprecated)"}, + {"crc32c", (PyCFunction)crc32c_crc32c, METH_VARARGS | METH_KEYWORDS, "Calculate crc32c incrementally"}, {NULL, NULL, 0, NULL} /* Sentinel */ }; diff --git a/test/test_crc32c.py b/test/test_crc32c.py index 480610a..2deea66 100644 --- a/test/test_crc32c.py +++ b/test/test_crc32c.py @@ -80,6 +80,9 @@ class TestMisc(unittest.TestCase): def test_zero(self): self.assertEqual(0, crc32c.crc32c(b'')) + def test_keyword(self): + self.assertEqual(10, crc32c.crc32c(b'', crc=10)) + def test_crc32_deprecated(self): with warning_catcher() as warns: crc32c.crc32(b'')