| #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_getiter(PyXReadlinesObject *a) |
| { |
| Py_INCREF(a); |
| return (PyObject *)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 */ |
| (getiterfunc)xreadlines_getiter, /* tp_iter */ |
| (iternextfunc)xreadlines_iternext, /* tp_iternext */ |
| }; |
| |
| static PyMethodDef xreadlines_functions[] = { |
| {"xreadlines", xreadlines, METH_VARARGS, xreadlines_doc}, |
| {NULL, NULL} |
| }; |
| |
| DL_EXPORT(void) |
| initxreadlines(void) |
| { |
| XReadlinesObject_Type.ob_type = &PyType_Type; |
| Py_InitModule("xreadlines", xreadlines_functions); |
| } |