[Python-checkins] CVS: python/dist/src/Objects fileobject.c,2.96,2.97

Guido van Rossum python-dev@python.org
Fri, 05 Jan 2001 06:43:07 -0800


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv3183

Modified Files:
	fileobject.c 
Log Message:
Restructured get_line() for clarity and speed.

- The raw_input() functionality is moved to a separate function.

- Drop GNU getline() in favor of getc_unlocked(), which exists on more
  platforms (and is even a tad faster on my system).


Index: fileobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v
retrieving revision 2.96
retrieving revision 2.97
diff -C2 -r2.96 -r2.97
*** fileobject.c	2000/12/20 00:55:07	2.96
--- fileobject.c	2001/01/05 14:43:05	2.97
***************
*** 640,686 ****
     > 0: max length;
     = 0: read arbitrary line;
!    < 0: strip trailing '\n', raise EOFError if EOF reached immediately
  */
  
  static PyObject *
  get_line(PyFileObject *f, int n)
  {
! 	register FILE *fp = f->f_fp;
! 	register int c;
  	char *buf, *end;
  	size_t n1, n2;
  	PyObject *v;
  
- #if defined(HAVE_GETLINE) && defined(_GNU_SOURCE)
- 	/* Use GNU libc extension getline() for arbitrary-sized lines */
- 	if (n == 0) {
- 		size_t size = 0;
- 		buf = NULL;
- 		Py_BEGIN_ALLOW_THREADS
- 		n1 = getline(&buf, &size, fp);
- 		Py_END_ALLOW_THREADS
- 		if (n1 == -1) {
- 			if (buf){
- 				free(buf);
- 			}
- 			clearerr(fp);
- 			if (PyErr_CheckSignals()) {
- 				return NULL;
- 			}
- 			if (n < 0 && feof(fp)) {
- 				PyErr_SetString(PyExc_EOFError,
- 						"EOF when reading a line");
- 				return NULL;
- 			}
- 			return PyString_FromStringAndSize(NULL, 0);
- 		}
- 		/* No error */
- 		
- 		v = PyString_FromStringAndSize(buf, n1);
- 		free(buf);
- 		return v;
- 	}
- #endif
- 
  	n2 = n > 0 ? n : 100;
  	v = PyString_FromStringAndSize((char *)NULL, n2);
--- 640,665 ----
     > 0: max length;
     = 0: read arbitrary line;
!    < 0: illegal (use get_line_raw() instead)
  */
  
+ #ifdef HAVE_GETC_UNLOCKED
+ #define GETC(f) getc_unlocked(f)
+ #define FLOCKFILE(f) flockfile(f)
+ #define FUNLOCKFILE(f) funlockfile(f)
+ #else
+ #define GETC(f) getc(f)
+ #define FLOCKFILE(f)
+ #define FUNLOCKFILE(f)
+ #endif
+ 
  static PyObject *
  get_line(PyFileObject *f, int n)
  {
! 	FILE *fp = f->f_fp;
! 	int c;
  	char *buf, *end;
  	size_t n1, n2;
  	PyObject *v;
  
  	n2 = n > 0 ? n : 100;
  	v = PyString_FromStringAndSize((char *)NULL, n2);
***************
*** 690,735 ****
  	end = buf + n2;
  
- 	Py_BEGIN_ALLOW_THREADS
  	for (;;) {
! 		if ((c = getc(fp)) == EOF) {
  			clearerr(fp);
- 			Py_BLOCK_THREADS
  			if (PyErr_CheckSignals()) {
  				Py_DECREF(v);
  				return NULL;
  			}
- 			if (n < 0 && buf == BUF(v)) {
- 				Py_DECREF(v);
- 				PyErr_SetString(PyExc_EOFError,
- 					   "EOF when reading a line");
- 				return NULL;
- 			}
- 			Py_UNBLOCK_THREADS
  			break;
  		}
! 		if ((*buf++ = c) == '\n') {
! 			if (n < 0)
! 				buf--;
  			break;
! 		}
! 		if (buf == end) {
! 			if (n > 0)
! 				break;
! 			n1 = n2;
! 			n2 += 1000;
! 			if (n2 > INT_MAX) {
! 				PyErr_SetString(PyExc_OverflowError,
! 					"line is longer than a Python string can hold");
! 				return NULL;
! 			}
! 			Py_BLOCK_THREADS
! 			if (_PyString_Resize(&v, n2) < 0)
! 				return NULL;
! 			Py_UNBLOCK_THREADS
! 			buf = BUF(v) + n1;
! 			end = BUF(v) + n2;
  		}
  	}
- 	Py_END_ALLOW_THREADS
  
  	n1 = buf - BUF(v);
--- 669,706 ----
  	end = buf + n2;
  
  	for (;;) {
! 		Py_BEGIN_ALLOW_THREADS
! 		FLOCKFILE(fp);
! 		while ((c = GETC(fp)) != EOF &&
! 		       (*buf++ = c) != '\n' &&
! 			buf != end)
! 			;
! 		FUNLOCKFILE(fp);
! 		Py_END_ALLOW_THREADS
! 		if (c == '\n')
! 			break;
! 		if (c == EOF) {
  			clearerr(fp);
  			if (PyErr_CheckSignals()) {
  				Py_DECREF(v);
  				return NULL;
  			}
  			break;
  		}
! 		/* Must be because buf == end */
! 		if (n > 0)
  			break;
! 		n1 = n2;
! 		n2 += 1000;
! 		if (n2 > INT_MAX) {
! 			PyErr_SetString(PyExc_OverflowError,
! 			    "line is longer than a Python string can hold");
! 			return NULL;
  		}
+ 		if (_PyString_Resize(&v, n2) < 0)
+ 			return NULL;
+ 		buf = BUF(v) + n1;
+ 		end = BUF(v) + n2;
  	}
  
  	n1 = buf - BUF(v);
***************
*** 739,742 ****
--- 710,732 ----
  }
  
+ /* Internal routine to get a line for raw_input():
+    strip trailing '\n', raise EOFError if EOF reached immediately
+ */
+ 
+ static PyObject *
+ get_line_raw(PyFileObject *f)
+ {
+ 	PyObject *line;
+ 
+ 	line = get_line(f, 0);
+ 	if (line == NULL || PyString_GET_SIZE(line) > 0)
+ 		return line;
+ 	else {
+ 		Py_DECREF(line);
+ 		PyErr_SetString(PyExc_EOFError, "EOF when reading a line");
+ 		return NULL;
+ 	}
+ }
+ 
  /* External C interface */
  
***************
*** 797,801 ****
  	if (((PyFileObject*)f)->f_fp == NULL)
  		return err_closed();
! 	return get_line((PyFileObject *)f, n);
  }
  
--- 787,794 ----
  	if (((PyFileObject*)f)->f_fp == NULL)
  		return err_closed();
! 	if (n < 0)
! 		return get_line_raw((PyFileObject *)f);
! 	else
! 		return get_line((PyFileObject *)f, n);
  }