| #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} | 
 | }; | 
 |  | 
 | 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'."); | 
 | } |