borg/dedupestore/_speedups.c

166 lines
4.6 KiB
C
Raw Normal View History

2010-02-28 19:22:45 +00:00
#include <Python/Python.h>
#include <Python/structmember.h>
typedef struct {
PyObject_HEAD
long int m;
long int i;
long int chunk_size;
unsigned long int sum;
PyObject *data;
PyObject *fd;
PyObject *chunks;
} ChunkifyIter;
PyObject* ChunkifyIter_iter(PyObject *self)
{
Py_INCREF(self);
return self;
}
PyObject* ChunkifyIter_iternext(PyObject *self)
{
ChunkifyIter *p = (ChunkifyIter *)self;
if (p->i < p->m) {
PyObject *tmp = Py_BuildValue("l", p->i);
(p->i)++;
return tmp;
} else {
/* Raising of standard StopIteration exception with empty value. */
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
}
static PyTypeObject ChunkifyIterType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"_chunkifier._ChunkifyIter", /*tp_name*/
sizeof(ChunkifyIter), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*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 | Py_TPFLAGS_HAVE_ITER,
/* tp_flags: Py_TPFLAGS_HAVE_ITER tells python to
use tp_iter and tp_iternext fields. */
"", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
ChunkifyIter_iter, /* tp_iter: __iter__() method */
ChunkifyIter_iternext /* tp_iternext: next() method */
};
static PyObject *
chunkify(PyObject *self, PyObject *args)
{
PyObject *fd;
PyObject *chunks;
long int chunk_size;
ChunkifyIter *p;
if (!PyArg_ParseTuple(args, "OlO", &fd, &chunk_size, &chunks)) return NULL;
/* I don't need python callable __init__() method for this iterator,
so I'll simply allocate it as PyObject and initialize it by hand. */
p = PyObject_New(ChunkifyIter, &ChunkifyIterType);
if (!p) return NULL;
/* I'm not sure if it's strictly necessary. */
if (!PyObject_Init((PyObject *)p, &ChunkifyIterType)) {
Py_DECREF(p);
return NULL;
}
2010-03-01 22:39:14 +00:00
p->m = 10;
p->i = 0;
p->fd = fd;
p->chunk_size = chunk_size;
p->chunks = chunks;
return (PyObject *)p;
}
static PyObject *
checksum(PyObject *self, PyObject *args)
{
2010-03-01 22:39:14 +00:00
unsigned long int sum = 0, s1, s2;
PyObject *data;
Py_ssize_t i, len;
const char *ptr;
if(!PyArg_ParseTuple(args, "O|l", &data, &sum)) return NULL;
if(!PyString_Check(data))
{
PyErr_SetNone(PyExc_TypeError);
Py_INCREF(data);
return NULL;
}
2010-03-01 22:39:14 +00:00
len = PyString_Size(data);
ptr = PyString_AsString(data);
s1 = sum & 0xffff;
s2 = sum >> 16;
for(i=0; i < len; i++)
{
s1 += ptr[i] + 1;
s2 += s1;
}
return PyInt_FromLong(((s2 & 0xffff) << 16) | (s1 & 0xffff));
2010-02-28 19:22:45 +00:00
}
static PyObject *
roll_checksum(PyObject *self, PyObject *args)
{
unsigned long int sum = 0, len, s1, s2, a, r;
PyObject *add, *remove;
if (!PyArg_ParseTuple(args, "lOOl", &sum, &remove, &add, &len)) return NULL;
if(!PyString_Check(remove) || !PyString_Check(add) ||
PyString_Size(remove) != 1 || PyString_Size(add) != 1)
{
PyErr_SetNone(PyExc_TypeError);
Py_INCREF(remove);
Py_INCREF(add);
return NULL;
}
a = *((const unsigned char *)PyString_AsString(add));
r = *((const unsigned char *)PyString_AsString(remove));
s1 = sum & 0xffff;
s2 = sum >> 16;
s1 -= r - a;
s2 -= len * (r + 1) - s1;
return PyInt_FromLong(((s2 & 0xffff) << 16) | (s1 & 0xffff));
}
2010-02-28 19:22:45 +00:00
static PyMethodDef ChunkifierMethods[] = {
{"chunkify", chunkify, METH_VARARGS, ""},
2010-03-01 22:39:14 +00:00
{"checksum", checksum, METH_VARARGS, ""},
{"roll_checksum", roll_checksum, METH_VARARGS, ""},
2010-02-28 19:22:45 +00:00
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC
2010-03-01 22:39:14 +00:00
init_speedups(void)
2010-02-28 19:22:45 +00:00
{
PyObject* m;
ChunkifyIterType.tp_new = PyType_GenericNew;
if (PyType_Ready(&ChunkifyIterType) < 0) return;
2010-03-01 22:39:14 +00:00
m = Py_InitModule("_speedups", ChunkifierMethods);
2010-02-28 19:22:45 +00:00
Py_INCREF(&ChunkifyIterType);
PyModule_AddObject(m, "_ChunkifyIter", (PyObject *)&ChunkifyIterType);
}