Skip to content

Commit e3782ca

Browse files
committed
Macro-generate the 4 update() methods via XXHASH_UPDATE_METHOD
PYXXH32_update, PYXXH64_update, PYXXH3_64_update and PYXXH3_128_update were identical except for type prefixes and algorithm names. The new macro eliminates all four bodies, saving 148 lines.
1 parent 3a11027 commit e3782ca

1 file changed

Lines changed: 60 additions & 208 deletions

File tree

src/_xxhash.c

Lines changed: 60 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -853,58 +853,63 @@ static int PY##type##_init(PY##type##Object *self, PyObject *args, \
853853

854854
XXHASH_INIT(XXH32, XXH32_reset, XXH32_update, XXH32_hash_t)
855855

856-
PyDoc_STRVAR(
857-
PYXXH32_update_doc,
858-
"update (data)\n\n"
859-
"Update the xxh32 object with bytes-like data. Repeated calls are\n"
860-
"equivalent to a single call with the concatenation of all the arguments.");
861-
862-
static PyObject *PYXXH32_update(PYXXH32Object *self, PyObject *const *args,
863-
Py_ssize_t nargs, PyObject *kwnames)
864-
{
865-
PyObject *arg = NULL;
866-
867-
/* validate keywords first */
868-
if (kwnames) {
869-
Py_ssize_t nkw = PyTuple_GET_SIZE(kwnames);
870-
for (Py_ssize_t i = 0; i < nkw; i++) {
871-
PyObject *key = PyTuple_GET_ITEM(kwnames, i);
872-
if (PyUnicode_CompareWithASCIIString(key, "data") == 0) {
873-
if (nargs >= 1) {
874-
PyErr_SetString(PyExc_TypeError,
875-
"xxh32.update() got multiple values for argument 'data'");
876-
return NULL;
877-
}
878-
arg = args[nargs + i];
879-
} else {
880-
PyErr_Format(PyExc_TypeError,
881-
"'%U' is an invalid keyword argument for 'xxh32.update()'",
882-
key);
883-
return NULL;
884-
}
885-
}
886-
}
887-
888-
if (nargs >= 1) {
889-
if (nargs > 1) {
890-
PyErr_Format(PyExc_TypeError,
891-
"xxh32.update() takes at most 1 positional argument (%zd given)", nargs);
892-
return NULL;
893-
}
894-
arg = args[0];
895-
}
896-
897-
if (!arg) {
898-
PyErr_SetString(PyExc_TypeError, "xxh32.update() missing required argument 'data'");
899-
return NULL;
900-
}
901-
902-
Py_buffer buf;
903-
if (_get_buffer_or_str(arg, &buf) < 0)
904-
return NULL;
905-
PYXXH32_do_update(self, &buf);
906-
Py_RETURN_NONE;
907-
}
856+
#define XXHASH_UPDATE_METHOD(prefix, name) \
857+
PyDoc_STRVAR( \
858+
PY##prefix##_update_doc, \
859+
"update (data)\n\n" \
860+
"Update the " name " object with bytes-like data. Repeated calls are\n" \
861+
"equivalent to a single call with the concatenation of all the arguments."); \
862+
\
863+
static PyObject *PY##prefix##_update(PY##prefix##Object *self, \
864+
PyObject *const *args, \
865+
Py_ssize_t nargs, PyObject *kwnames) \
866+
{ \
867+
PyObject *arg = NULL; \
868+
\
869+
/* validate keywords first */ \
870+
if (kwnames) { \
871+
Py_ssize_t nkw = PyTuple_GET_SIZE(kwnames); \
872+
for (Py_ssize_t i = 0; i < nkw; i++) { \
873+
PyObject *key = PyTuple_GET_ITEM(kwnames, i); \
874+
if (PyUnicode_CompareWithASCIIString(key, "data") == 0) { \
875+
if (nargs >= 1) { \
876+
PyErr_SetString(PyExc_TypeError, \
877+
name ".update() got multiple values for argument 'data'"); \
878+
return NULL; \
879+
} \
880+
arg = args[nargs + i]; \
881+
} else { \
882+
PyErr_Format(PyExc_TypeError, \
883+
"'%U' is an invalid keyword argument for '" name ".update()'", \
884+
key); \
885+
return NULL; \
886+
} \
887+
} \
888+
} \
889+
\
890+
if (nargs >= 1) { \
891+
if (nargs > 1) { \
892+
PyErr_Format(PyExc_TypeError, \
893+
name ".update() takes at most 1 positional argument (%zd given)", nargs); \
894+
return NULL; \
895+
} \
896+
arg = args[0]; \
897+
} \
898+
\
899+
if (!arg) { \
900+
PyErr_SetString(PyExc_TypeError, \
901+
name ".update() missing required argument 'data'"); \
902+
return NULL; \
903+
} \
904+
\
905+
Py_buffer buf; \
906+
if (_get_buffer_or_str(arg, &buf) < 0) \
907+
return NULL; \
908+
PY##prefix##_do_update(self, &buf); \
909+
Py_RETURN_NONE; \
910+
}
911+
912+
XXHASH_UPDATE_METHOD(XXH32, "xxh32")
908913

909914
PyDoc_STRVAR(
910915
PYXXH32_digest_doc,
@@ -1205,58 +1210,7 @@ static PyObject *PYXXH64_new(PyTypeObject *type, PyObject *args, PyObject *kwarg
12051210

12061211
XXHASH_INIT(XXH64, XXH64_reset, XXH64_update, XXH64_hash_t)
12071212

1208-
PyDoc_STRVAR(
1209-
PYXXH64_update_doc,
1210-
"update (data)\n\n"
1211-
"Update the xxh64 object with bytes-like data. Repeated calls are\n"
1212-
"equivalent to a single call with the concatenation of all the arguments.");
1213-
1214-
static PyObject *PYXXH64_update(PYXXH64Object *self, PyObject *const *args,
1215-
Py_ssize_t nargs, PyObject *kwnames)
1216-
{
1217-
PyObject *arg = NULL;
1218-
1219-
/* validate keywords first */
1220-
if (kwnames) {
1221-
Py_ssize_t nkw = PyTuple_GET_SIZE(kwnames);
1222-
for (Py_ssize_t i = 0; i < nkw; i++) {
1223-
PyObject *key = PyTuple_GET_ITEM(kwnames, i);
1224-
if (PyUnicode_CompareWithASCIIString(key, "data") == 0) {
1225-
if (nargs >= 1) {
1226-
PyErr_SetString(PyExc_TypeError,
1227-
"xxh64.update() got multiple values for argument 'data'");
1228-
return NULL;
1229-
}
1230-
arg = args[nargs + i];
1231-
} else {
1232-
PyErr_Format(PyExc_TypeError,
1233-
"'%U' is an invalid keyword argument for 'xxh64.update()'",
1234-
key);
1235-
return NULL;
1236-
}
1237-
}
1238-
}
1239-
1240-
if (nargs >= 1) {
1241-
if (nargs > 1) {
1242-
PyErr_Format(PyExc_TypeError,
1243-
"xxh64.update() takes at most 1 positional argument (%zd given)", nargs);
1244-
return NULL;
1245-
}
1246-
arg = args[0];
1247-
}
1248-
1249-
if (!arg) {
1250-
PyErr_SetString(PyExc_TypeError, "xxh64.update() missing required argument 'data'");
1251-
return NULL;
1252-
}
1253-
1254-
Py_buffer buf;
1255-
if (_get_buffer_or_str(arg, &buf) < 0)
1256-
return NULL;
1257-
PYXXH64_do_update(self, &buf);
1258-
Py_RETURN_NONE;
1259-
}
1213+
XXHASH_UPDATE_METHOD(XXH64, "xxh64")
12601214

12611215
PyDoc_STRVAR(
12621216
PYXXH64_digest_doc,
@@ -1557,58 +1511,7 @@ static PyObject *PYXXH3_64_new(PyTypeObject *type, PyObject *args, PyObject *kwa
15571511

15581512
XXHASH_INIT(XXH3_64, XXH3_64bits_reset_withSeed, XXH3_64bits_update, XXH64_hash_t)
15591513

1560-
PyDoc_STRVAR(
1561-
PYXXH3_64_update_doc,
1562-
"update (data)\n\n"
1563-
"Update the xxh3_64 object with bytes-like data. Repeated calls are\n"
1564-
"equivalent to a single call with the concatenation of all the arguments.");
1565-
1566-
static PyObject *PYXXH3_64_update(PYXXH3_64Object *self, PyObject *const *args,
1567-
Py_ssize_t nargs, PyObject *kwnames)
1568-
{
1569-
PyObject *arg = NULL;
1570-
1571-
/* validate keywords first */
1572-
if (kwnames) {
1573-
Py_ssize_t nkw = PyTuple_GET_SIZE(kwnames);
1574-
for (Py_ssize_t i = 0; i < nkw; i++) {
1575-
PyObject *key = PyTuple_GET_ITEM(kwnames, i);
1576-
if (PyUnicode_CompareWithASCIIString(key, "data") == 0) {
1577-
if (nargs >= 1) {
1578-
PyErr_SetString(PyExc_TypeError,
1579-
"xxh3_64.update() got multiple values for argument 'data'");
1580-
return NULL;
1581-
}
1582-
arg = args[nargs + i];
1583-
} else {
1584-
PyErr_Format(PyExc_TypeError,
1585-
"'%U' is an invalid keyword argument for 'xxh3_64.update()'",
1586-
key);
1587-
return NULL;
1588-
}
1589-
}
1590-
}
1591-
1592-
if (nargs >= 1) {
1593-
if (nargs > 1) {
1594-
PyErr_Format(PyExc_TypeError,
1595-
"xxh3_64.update() takes at most 1 positional argument (%zd given)", nargs);
1596-
return NULL;
1597-
}
1598-
arg = args[0];
1599-
}
1600-
1601-
if (!arg) {
1602-
PyErr_SetString(PyExc_TypeError, "xxh3_64.update() missing required argument 'data'");
1603-
return NULL;
1604-
}
1605-
1606-
Py_buffer buf;
1607-
if (_get_buffer_or_str(arg, &buf) < 0)
1608-
return NULL;
1609-
PYXXH3_64_do_update(self, &buf);
1610-
Py_RETURN_NONE;
1611-
}
1514+
XXHASH_UPDATE_METHOD(XXH3_64, "xxh3_64")
16121515

16131516
PyDoc_STRVAR(
16141517
PYXXH3_64_digest_doc,
@@ -1916,58 +1819,7 @@ static PyObject *PYXXH3_128_new(PyTypeObject *type, PyObject *args, PyObject *kw
19161819

19171820
XXHASH_INIT(XXH3_128, XXH3_128bits_reset_withSeed, XXH3_128bits_update, XXH64_hash_t)
19181821

1919-
PyDoc_STRVAR(
1920-
PYXXH3_128_update_doc,
1921-
"update (data)\n\n"
1922-
"Update the xxh3_128 object with bytes-like data. Repeated calls are\n"
1923-
"equivalent to a single call with the concatenation of all the arguments.");
1924-
1925-
static PyObject *PYXXH3_128_update(PYXXH3_128Object *self, PyObject *const *args,
1926-
Py_ssize_t nargs, PyObject *kwnames)
1927-
{
1928-
PyObject *arg = NULL;
1929-
1930-
/* validate keywords first */
1931-
if (kwnames) {
1932-
Py_ssize_t nkw = PyTuple_GET_SIZE(kwnames);
1933-
for (Py_ssize_t i = 0; i < nkw; i++) {
1934-
PyObject *key = PyTuple_GET_ITEM(kwnames, i);
1935-
if (PyUnicode_CompareWithASCIIString(key, "data") == 0) {
1936-
if (nargs >= 1) {
1937-
PyErr_SetString(PyExc_TypeError,
1938-
"xxh3_128.update() got multiple values for argument 'data'");
1939-
return NULL;
1940-
}
1941-
arg = args[nargs + i];
1942-
} else {
1943-
PyErr_Format(PyExc_TypeError,
1944-
"'%U' is an invalid keyword argument for 'xxh3_128.update()'",
1945-
key);
1946-
return NULL;
1947-
}
1948-
}
1949-
}
1950-
1951-
if (nargs >= 1) {
1952-
if (nargs > 1) {
1953-
PyErr_Format(PyExc_TypeError,
1954-
"xxh3_128.update() takes at most 1 positional argument (%zd given)", nargs);
1955-
return NULL;
1956-
}
1957-
arg = args[0];
1958-
}
1959-
1960-
if (!arg) {
1961-
PyErr_SetString(PyExc_TypeError, "xxh3_128.update() missing required argument 'data'");
1962-
return NULL;
1963-
}
1964-
1965-
Py_buffer buf;
1966-
if (_get_buffer_or_str(arg, &buf) < 0)
1967-
return NULL;
1968-
PYXXH3_128_do_update(self, &buf);
1969-
Py_RETURN_NONE;
1970-
}
1822+
XXHASH_UPDATE_METHOD(XXH3_128, "xxh3_128")
19711823

19721824
PyDoc_STRVAR(
19731825
PYXXH3_128_digest_doc,

0 commit comments

Comments
 (0)