|
|
|
#include "Python.h"
|
|
|
|
|
|
|
|
PyDoc_STRVAR(xreadlines_doc,
|
|
|
|
"xreadlines(f)\n\
|
|
|
|
\n\
|
|
|
|
Return an xreadlines object for the file f.");
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
PyObject_HEAD
|
|
|
|
PyObject *file;
|
|
|
|
PyObject *lines;
|
|
|
|
int lineslen;
|
|
|
|
int lineno;
|
|
|
|
int abslineno;
|
|
|
|
} PyXReadlinesObject;
|
|
|
|
|
|
|
|
static PyTypeObject XReadlinesObject_Type;
|
|
|
|
|
|
|
|
static void
|
|
|
|
xreadlines_dealloc(PyXReadlinesObject *op)
|
|
|
|
{
|
|
|
|
Py_XDECREF(op->file);
|
|
|
|
Py_XDECREF(op->lines);
|
|
|
|
PyObject_DEL(op);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* A larger chunk size doesn't seem to make a difference */
|
|
|
|
#define CHUNKSIZE 8192
|
|
|
|
|
|
|
|
static PyXReadlinesObject *
|
|
|
|
newreadlinesobject(PyObject *file)
|
|
|
|
{
|
|
|
|
PyXReadlinesObject *op;
|
|
|
|
op = PyObject_NEW(PyXReadlinesObject, &XReadlinesObject_Type);
|
|
|
|
if (op == NULL)
|
|
|
|
return NULL;
|
|
|
|
Py_XINCREF(file);
|
|
|
|
op->file = file;
|
|
|
|
op->lines = NULL;
|
|
|
|
op->abslineno = op->lineno = op->lineslen = 0;
|
|
|
|
return op;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
xreadlines(PyObject *self, PyObject *args)
|
|
|
|
{
|
|
|
|
PyObject *file;
|
|
|
|
PyXReadlinesObject *ret;
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, "O:xreadlines", &file))
|
|
|
|
return NULL;
|
|
|
|
ret = newreadlinesobject(file);
|
|
|
|
return (PyObject*)ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
xreadlines_common(PyXReadlinesObject *a)
|
|
|
|
{
|
|
|
|
if (a->lineno >= a->lineslen) {
|
|
|
|
Py_XDECREF(a->lines);
|
|
|
|
a->lines = PyObject_CallMethod(a->file, "readlines", "(i)",
|
|
|
|
CHUNKSIZE);
|
|
|
|
if (a->lines == NULL)
|
|
|
|
return NULL;
|
|
|
|
a->lineno = 0;
|
|
|
|
if ((a->lineslen = PySequence_Size(a->lines)) < 0)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
a->abslineno++;
|
|
|
|
return PySequence_GetItem(a->lines, a->lineno++);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
xreadlines_item(PyXReadlinesObject *a, int i)
|
|
|
|
{
|
|
|
|
if (i != a->abslineno) {
|
|
|
|
PyErr_SetString(PyExc_RuntimeError,
|
|
|
|
"xreadlines object accessed out of order");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return xreadlines_common(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
xreadlines_iternext(PyXReadlinesObject *a)
|
|
|
|
{
|
|
|
|
PyObject *res;
|
|
|
|
|
|
|
|
res = xreadlines_common(a);
|
|
|
|
if (res == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
|
|
|
|
PyErr_Clear();
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
xreadlines_next(PyXReadlinesObject *a, PyObject *args)
|
|
|
|
{
|
|
|
|
PyObject *res;
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
|
|
return NULL;
|
|
|
|
res = xreadlines_common(a);
|
|
|
|
if (res == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
|
|
|
|
PyErr_SetObject(PyExc_StopIteration, Py_None);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyDoc_STRVAR(next_doc, "x.next() -> the next line or raise StopIteration");
|
|
|
|
|
|
|
|
static PyMethodDef xreadlines_methods[] = {
|
|
|
|
{"next", (PyCFunction)xreadlines_next, METH_VARARGS, next_doc},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
xreadlines_getattr(PyObject *a, char *name)
|
|
|
|
{
|
|
|
|
return Py_FindMethod(xreadlines_methods, a, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PySequenceMethods xreadlines_as_sequence = {
|
|
|
|
0, /*sq_length*/
|
|
|
|
0, /*sq_concat*/
|
|
|
|
0, /*sq_repeat*/
|
|
|
|
(intargfunc)xreadlines_item, /*sq_item*/
|
|
|
|
};
|
|
|
|
|
|
|
|
static PyTypeObject XReadlinesObject_Type = {
|
|
|
|
PyObject_HEAD_INIT(NULL)
|
|
|
|
0,
|
|
|
|
"xreadlines.xreadlines",
|
|
|
|
sizeof(PyXReadlinesObject),
|
|
|
|
0,
|
|
|
|
(destructor)xreadlines_dealloc, /* tp_dealloc */
|
|
|
|
0, /* tp_print */
|
|
|
|
xreadlines_getattr, /* tp_getattr */
|
|
|
|
0, /* tp_setattr */
|
|
|
|
0, /* tp_compare */
|
|
|
|
0, /* tp_repr */
|
|
|
|
0, /* tp_as_number */
|
|
|
|
&xreadlines_as_sequence, /* 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 */
|
|
|
|
0, /* tp_doc */
|
|
|
|
0, /* tp_traverse */
|
|
|
|
0, /* tp_clear */
|
|
|
|
0, /* tp_richcompare */
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
PyObject_SelfIter, /* tp_iter */
|
|
|
|
(iternextfunc)xreadlines_iternext, /* tp_iternext */
|
|
|
|
};
|
|
|
|
|
|
|
|
static PyMethodDef xreadlines_functions[] = {
|
|
|
|
{"xreadlines", xreadlines, METH_VARARGS, xreadlines_doc},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
PyMODINIT_FUNC
|
|
|
|
initxreadlines(void)
|
|
|
|
{
|
|
|
|
XReadlinesObject_Type.ob_type = &PyType_Type;
|
|
|
|
Py_InitModule("xreadlines", xreadlines_functions);
|
|
|
|
PyErr_Warn(PyExc_DeprecationWarning,
|
|
|
|
"xreadlines is deprecated; use 'for line in file'.");
|
|
|
|
}
|