Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 2053a0d9eaaf755b990f80ce4df504a7 > files > 411

waf-1.5.9-1mdv2010.0.noarch.rpm

/*
fnv.c implemented from http://isthe.com/chongo/tech/comp/fnv/

Changing md5 for fnv:
* brings a 10% speed improvement on hashing files (tried on a fast computer for hashing divx files)
* reduces the signature size by 2 (128 bits -> 64 bits) pickling the cache is faster

Thomas Nagy 2008
*/

#include <Python.h>

/*
To compile, put the following in new file named "setup.py"
Then run the command "python setup.py build"

from distutils.core import setup, Extension
setup(name="fnv", version="0.1", ext_modules=[Extension("fnv", ["fnv.c"])])

To try the beast, put the .so in the current folder, or run
python setup.py install, and then try the following script

import fnv
x = fnv.new()
for num in xrange(15):
	x.update("blahla")
	print str(x.digest())
*/

#define INTSIZE 8
/* (sizeof(u_int64_t)) */
#define FNV1_64_INIT ((u_int64_t)14695981039346656037ULL)
#define FNV1_64_PRIME ((u_int64_t)1099511628211)

/* second line is much faster - why? */
/*#define FNV_64A_OP(hash, octet) (((u_int64_t)(hash) ^ (u_int8_t)(octet)) * FNV1_64_PRIME) */
#define FNV_64A_OP(hash, octet) ((hash ^ octet) * FNV1_64_PRIME)

typedef struct fnv_struct
{
	PyObject_HEAD
	u_int64_t sum;
} fnv_struct;

static PyObject * fnv_update(fnv_struct *self, PyObject *args)
{
	unsigned char *cp;
	int len;

	if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
		return NULL;

	int i;
	for (i = 0; i < len; ++i)
	{
		self->sum = FNV_64A_OP(self->sum, cp[i]);
	}

	Py_INCREF(Py_None);
	return Py_None;
}

static PyObject * fnv_hfile(fnv_struct *self, PyObject *args)
{
	unsigned char *cp;
	int len;
	if (!PyArg_ParseTuple(args, "s#:hfile", &cp, &len))
		return NULL;

	self->sum = FNV1_64_INIT;
	FILE *stream;
	unsigned char buf[8192];
	int i;
	int numread;
	if ((stream = fopen((char*)cp, "r")) != NULL)
	{
		do
		{
			numread = fread(buf, sizeof(unsigned char), 8192, stream);
			for (i=0; i<numread; ++i)
			{
				self->sum = FNV_64A_OP(self->sum, buf[i]);
			}
		}
		while (numread);
		fclose(stream);
	}
	else
	{
		return NULL;
	}
	return PyString_FromStringAndSize((char*) &self->sum, INTSIZE);
}

static PyObject * fnv_digest(fnv_struct *self)
{
	return PyString_FromStringAndSize((char*) &self->sum, INTSIZE);
}

static PyObject * fnv_hexdigest(fnv_struct *self)
{
    unsigned char hexdigest[2*INTSIZE];
    int i;
    for (i=0; i<INTSIZE; ++i)
    {
        char u = ((unsigned char*) &self->sum)[i];
        char c;
        c = (u >> 4) & 0xf;
        c = (c>9) ? c + 'a' - 10 : c + '0';
        hexdigest[2*i] = c;
        c = u & 0xf;
        c = c > 9 ? c + 'a' - 10 : c + '0';
        hexdigest[2*i+1] = c;
    }
	PyObject* ret = PyString_FromStringAndSize((char *) hexdigest, 2*INTSIZE);
	return ret;
}

static PyMethodDef fnv_methods[] = {
	{"update",    (PyCFunction)fnv_update,    METH_VARARGS, NULL},
	{"digest",    (PyCFunction)fnv_digest,    METH_NOARGS,  NULL},
	{"hexdigest", (PyCFunction)fnv_hexdigest, METH_NOARGS,  NULL},
	{"hfile",     (PyCFunction)fnv_hfile,     METH_VARARGS, NULL},
	{NULL}
};

static void fnv_dealloc(fnv_struct* self)
{
	PyObject_Del(self);
}

static PyTypeObject fnv_type;

static fnv_struct * fnv_new(void)
{
	fnv_struct * obj;
	obj = PyObject_New(fnv_struct, &fnv_type);
	if (obj == NULL) return NULL;
	obj->sum = FNV1_64_INIT;
	return obj;
}

static PyObject * new_fnv_new(PyObject *self, PyObject *args)
{
	fnv_struct *obj;
	if ((obj = fnv_new()) == NULL)
		return NULL;
	return (PyObject *)obj;
}

static PyTypeObject fnv_type = {
	PyObject_HEAD_INIT(NULL)
	0,                       /*ob_size*/
	"fnv",                   /*tp_name*/
	sizeof(fnv_struct),      /*tp_basicsize*/
	0,                       /*tp_itemsize*/
	(destructor)fnv_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,      /*tp_flags*/
	"fnv objects",           /* tp_doc */
	0,		         /* tp_traverse */
	0,		         /* tp_clear */
	0,		         /* tp_richcompare */
	0,		         /* tp_weaklistoffset */
	0,		         /* tp_iter */
	0,		         /* tp_iternext */
	fnv_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 */
	0,                       /* tp_new */
};

static PyMethodDef fnv_funs[] = {
	{"new",	(PyCFunction)new_fnv_new, METH_VARARGS, NULL},
	{NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC initfnv(void)
{
	PyObject* m;

	fnv_type.tp_new = PyType_GenericNew;
	if (PyType_Ready(&fnv_type) < 0)
		return;

	m = Py_InitModule3("fnv", fnv_funs, NULL);

	Py_INCREF(&fnv_type);
	PyModule_AddObject(m, "fnv", (PyObject *)&fnv_type);
}