blob: 6e8a8b545ba2a217a5eb650e6991a7ad57098a7d [file] [log] [blame]
Marc-André Lemburg93c409a2000-06-28 16:48:05 +00001#include <Python.h>
2
3static PyObject * hashFunction(PyObject *self, PyObject *args, PyObject *kw)
4{
5 PyStringObject *a;
6 register int len;
7 register unsigned char *p;
Jeremy Hylton4d6381d2000-07-26 03:56:06 +00008 register unsigned long x;
9 unsigned long ulSeed;
Marc-André Lemburg93c409a2000-06-28 16:48:05 +000010 unsigned long cchSeed;
Jeremy Hylton4d6381d2000-07-26 03:56:06 +000011 unsigned long cHashElements;
Marc-André Lemburg93c409a2000-06-28 16:48:05 +000012
Jeremy Hylton4d6381d2000-07-26 03:56:06 +000013 if (!PyArg_ParseTuple(args, "llOl:hash",
14 &ulSeed, &cchSeed, &a, &cHashElements))
Marc-André Lemburg93c409a2000-06-28 16:48:05 +000015 return NULL;
16 if (!PyString_Check(a))
17 {
18 PyErr_SetString(PyExc_TypeError, "arg 3 needs to be a string");
19 return NULL;
20 }
21
22 len = a->ob_size;
23 p = (unsigned char *) a->ob_sval;
Jeremy Hylton4d6381d2000-07-26 03:56:06 +000024 x = ulSeed;
Marc-André Lemburg93c409a2000-06-28 16:48:05 +000025 while (--len >= 0)
Jeremy Hylton4d6381d2000-07-26 03:56:06 +000026 {
27 /* (1000003 * x) ^ *p++
28 * translated to handle > 32 bit longs
29 */
30 x = (0xf4243 * x);
31 x = x & 0xFFFFFFFF;
32 x = x ^ *p++;
33 }
Marc-André Lemburg93c409a2000-06-28 16:48:05 +000034 x ^= a->ob_size + cchSeed;
Jeremy Hylton4d6381d2000-07-26 03:56:06 +000035 if (x == 0xFFFFFFFF)
36 x = 0xfffffffe;
37 if (x & 0x80000000)
38 {
39 /* Emulate Python 32-bit signed (2's complement)
40 * modulo operation
41 */
42 x = (~x & 0xFFFFFFFF) + 1;
43 x %= cHashElements;
44 if (x != 0)
45 {
46 x = x + (~cHashElements & 0xFFFFFFFF) + 1;
47 x = (~x & 0xFFFFFFFF) + 1;
48 }
49 }
50 else
51 x %= cHashElements;
52 return PyInt_FromLong((long)x);
Marc-André Lemburg93c409a2000-06-28 16:48:05 +000053}
54
55static PyObject * calcSeed(PyObject *self, PyObject *args, PyObject *kw)
56{
57 PyStringObject *a;
58 register int len;
59 register unsigned char *p;
Jeremy Hylton4d6381d2000-07-26 03:56:06 +000060 register unsigned long x;
Marc-André Lemburg93c409a2000-06-28 16:48:05 +000061
62 if (!PyString_Check(args))
63 {
64 PyErr_SetString(PyExc_TypeError, "arg 1 expected a string, but didn't get it.");
65 return NULL;
66 }
67
68 a = (PyStringObject *)args;
69
70 len = a->ob_size;
71 p = (unsigned char *) a->ob_sval;
Jeremy Hylton4d6381d2000-07-26 03:56:06 +000072 x = (*p << 7) & 0xFFFFFFFF;
Marc-André Lemburg93c409a2000-06-28 16:48:05 +000073 while (--len >= 0)
Jeremy Hylton4d6381d2000-07-26 03:56:06 +000074 {
75 /* (1000003 * x) ^ *p++
76 * translated to handle > 32 bit longs
77 */
78 x = (0xf4243 * x);
79 x = x & 0xFFFFFFFF;
80 x = x ^ *p++;
81 }
82 return PyInt_FromLong((long)x);
Marc-André Lemburg93c409a2000-06-28 16:48:05 +000083}
84
85
86static struct PyMethodDef hashMethods[] = {
87 { "calcSeed", calcSeed, 0, NULL },
88 { "hash", hashFunction, 0, NULL },
89 { NULL, NULL, 0, NULL } /* sentinel */
90};
91
92#ifdef _MSC_VER
93_declspec(dllexport)
94#endif
Thomas Wouters78890102000-07-22 19:25:51 +000095void initperfhash(void)
Marc-André Lemburg93c409a2000-06-28 16:48:05 +000096{
97 PyObject *m;
98
99 m = Py_InitModule4("perfhash", hashMethods,
100 NULL, NULL, PYTHON_API_VERSION);
101 if ( m == NULL )
Jeremy Hylton4d6381d2000-07-26 03:56:06 +0000102 Py_FatalError("can't initialize module perfhash");
Marc-André Lemburg93c409a2000-06-28 16:48:05 +0000103}
Jeremy Hylton4d6381d2000-07-26 03:56:06 +0000104
105
106
107
108
109
110
111
112
113
114