2487 lines · 62.3 KB · C
RawDownload
		if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:file",						kwlist, &po, &mode, &bufsize)) {			wideargument = 1;			if (fill_file_fields(foself, NULL, po, mode,					     fclose) == NULL)				goto Error;		} else {			/* Drop the argument parsing error as narrow			   strings are also valid. */			PyErr_Clear();		}	}#endif 	if (!wideargument) {                PyObject *o_name; 		if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist,						 Py_FileSystemDefaultEncoding,						 &name,						 &mode, &bufsize))			return -1;                 /* We parse again to get the name as a PyObject */                if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|si:file",                                                  kwlist, &o_name, &mode,                                                  &bufsize))                        goto Error; 		if (fill_file_fields(foself, NULL, o_name, mode,				     fclose) == NULL)			goto Error;	}	if (open_the_file(foself, name, mode) == NULL)		goto Error;	foself->f_setbuf = NULL;	PyFile_SetBufSize(self, bufsize);	goto Done; Error:	ret = -1;	/* fall through */Done:	PyMem_Free(name); /* free the encoded string */	return ret;} PyDoc_VAR(file_doc) =PyDoc_STR("file(name[, mode[, buffering]]) -> file object\n""\n""Open a file.  The mode can be 'r', 'w' or 'a' for reading (default),\n""writing or appending.  The file will be created if it doesn't exist\n""when opened for writing or appending; it will be truncated when\n""opened for writing.  Add a 'b' to the mode for binary files.\n""Add a '+' to the mode to allow simultaneous reading and writing.\n""If the buffering argument is given, 0 means unbuffered, 1 means line\n""buffered, and larger numbers specify the buffer size.\n")PyDoc_STR("Add a 'U' to mode to open the file for input with universal newline\n""support.  Any line ending in the input file will be seen as a '\\n'\n""in Python.  Also, a file so opened gains the attribute 'newlines';\n""the value for this attribute is one of None (no newline read yet),\n""'\\r', '\\n', '\\r\\n' or a tuple containing all the newline types seen.\n""\n""'U' cannot be combined with 'w' or '+' mode.\n"); PyTypeObject PyFile_Type = {	PyObject_HEAD_INIT(&PyType_Type)	0,	"file",	sizeof(PyFileObject),	0,	(destructor)file_dealloc,		/* tp_dealloc */	0,					/* tp_print */	0,			 		/* tp_getattr */	0,			 		/* tp_setattr */	0,					/* tp_compare */	(reprfunc)file_repr, 			/* tp_repr */	0,					/* tp_as_number */	0,					/* tp_as_sequence */	0,					/* tp_as_mapping */	0,					/* tp_hash */	0,					/* tp_call */	0,					/* tp_str */	PyObject_GenericGetAttr,		/* tp_getattro */	/* softspace is writable:  we must supply tp_setattro */	PyObject_GenericSetAttr,		/* tp_setattro */	0,					/* tp_as_buffer */	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */	file_doc,				/* tp_doc */	0,					/* tp_traverse */	0,					/* tp_clear */	0,					/* tp_richcompare */	offsetof(PyFileObject, weakreflist),	/* tp_weaklistoffset */	(getiterfunc)file_self,			/* tp_iter */	(iternextfunc)file_iternext,		/* tp_iternext */	file_methods,				/* tp_methods */	file_memberlist,			/* tp_members */	file_getsetlist,			/* tp_getset */	0,					/* tp_base */	0,					/* tp_dict */	0,					/* tp_descr_get */	0,					/* tp_descr_set */	0,					/* tp_dictoffset */	file_init,				/* tp_init */	PyType_GenericAlloc,			/* tp_alloc */	file_new,				/* tp_new */	PyObject_Del,                           /* tp_free */}; /* Interface for the 'soft space' between print items. */ intPyFile_SoftSpace(PyObject *f, int newflag){	long oldflag = 0;	if (f == NULL) {		/* Do nothing */	}	else if (PyFile_Check(f)) {		oldflag = ((PyFileObject *)f)->f_softspace;		((PyFileObject *)f)->f_softspace = newflag;	}	else {		PyObject *v;		v = PyObject_GetAttrString(f, "softspace");		if (v == NULL)			PyErr_Clear();		else {			if (PyInt_Check(v))				oldflag = PyInt_AsLong(v);			assert(oldflag < INT_MAX);			Py_DECREF(v);		}		v = PyInt_FromLong((long)newflag);		if (v == NULL)			PyErr_Clear();		else {			if (PyObject_SetAttrString(f, "softspace", v) != 0)				PyErr_Clear();			Py_DECREF(v);		}	}	return (int)oldflag;} /* Interfaces to write objects/strings to file-like objects */ intPyFile_WriteObject(PyObject *v, PyObject *f, int flags){	PyObject *writer, *value, *args, *result;	if (f == NULL) {		PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");		return -1;	}	else if (PyFile_Check(f)) {		FILE *fp = PyFile_AsFile(f);#ifdef Py_USING_UNICODE		PyObject *enc = ((PyFileObject*)f)->f_encoding;		int result;#endif		if (fp == NULL) {			err_closed();			return -1;		}#ifdef Py_USING_UNICODE                if ((flags & Py_PRINT_RAW) &&		    PyUnicode_Check(v) && enc != Py_None) {			char *cenc = PyString_AS_STRING(enc);			value = PyUnicode_AsEncodedString(v, cenc, "strict");			if (value == NULL)				return -1;		} else {			value = v;			Py_INCREF(value);		}		result = PyObject_Print(value, fp, flags);		Py_DECREF(value);		return result;#else		return PyObject_Print(v, fp, flags);#endif	}	writer = PyObject_GetAttrString(f, "write");	if (writer == NULL)		return -1;	if (flags & Py_PRINT_RAW) {                if (PyUnicode_Check(v)) {                        value = v;                        Py_INCREF(value);                } else                        value = PyObject_Str(v);	}        else		value = PyObject_Repr(v);	if (value == NULL) {		Py_DECREF(writer);		return -1;	}	args = PyTuple_Pack(1, value);	if (args == NULL) {		Py_DECREF(value);		Py_DECREF(writer);		return -1;	}	result = PyEval_CallObject(writer, args);	Py_DECREF(args);	Py_DECREF(value);	Py_DECREF(writer);	if (result == NULL)		return -1;	Py_DECREF(result);	return 0;} intPyFile_WriteString(const char *s, PyObject *f){	if (f == NULL) {		/* Should be caused by a pre-existing error */		if (!PyErr_Occurred())			PyErr_SetString(PyExc_SystemError,					"null file for PyFile_WriteString");		return -1;	}	else if (PyFile_Check(f)) {		FILE *fp = PyFile_AsFile(f);		if (fp == NULL) {			err_closed();			return -1;		}		fputs(s, fp);		return 0;	}	else if (!PyErr_Occurred()) {		PyObject *v = PyString_FromString(s);		int err;		if (v == NULL)			return -1;		err = PyFile_WriteObject(v, f, Py_PRINT_RAW);		Py_DECREF(v);		return err;	}	else		return -1;} /* Try to get a file-descriptor from a Python object.  If the object   is an integer or long integer, its value is returned.  If not, the   object's fileno() method is called if it exists; the method must return   an integer or long integer, which is returned as the file descriptor value.   -1 is returned on failure.*/ int PyObject_AsFileDescriptor(PyObject *o){	int fd;	PyObject *meth; 	if (PyInt_Check(o)) {		fd = PyInt_AsLong(o);	}	else if (PyLong_Check(o)) {		fd = PyLong_AsLong(o);	}	else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)	{		PyObject *fno = PyEval_CallObject(meth, NULL);		Py_DECREF(meth);		if (fno == NULL)			return -1; 		if (PyInt_Check(fno)) {			fd = PyInt_AsLong(fno);			Py_DECREF(fno);		}		else if (PyLong_Check(fno)) {			fd = PyLong_AsLong(fno);			Py_DECREF(fno);		}		else {			PyErr_SetString(PyExc_TypeError,					"fileno() returned a non-integer");			Py_DECREF(fno);			return -1;		}	}	else {		PyErr_SetString(PyExc_TypeError,				"argument must be an int, or have a fileno() method.");		return -1;	} 	if (fd < 0) {		PyErr_Format(PyExc_ValueError,			     "file descriptor cannot be a negative integer (%i)",			     fd);		return -1;	}	return fd;} /* From here on we need access to the real fgets and fread */#undef fgets#undef fread /*** Py_UniversalNewlineFgets is an fgets variation that understands** all of \r, \n and \r\n conventions.** The stream should be opened in binary mode.** If fobj is NULL the routine always does newline conversion, and** it may peek one char ahead to gobble the second char in \r\n.** If fobj is non-NULL it must be a PyFileObject. In this case there** is no readahead but in stead a flag is used to skip a following** \n on the next read. Also, if the file is open in binary mode** the whole conversion is skipped. Finally, the routine keeps track of** the different types of newlines seen.** Note that we need no error handling: fgets() treats error and eof** identically.*/char *Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj){	char *p = buf;	int c;	int newlinetypes = 0;	int skipnextlf = 0;	int univ_newline = 1; 	if (fobj) {		if (!PyFile_Check(fobj)) {			errno = ENXIO;	/* What can you do... */			return NULL;		}		univ_newline = ((PyFileObject *)fobj)->f_univ_newline;		if ( !univ_newline )			return fgets(buf, n, stream);		newlinetypes = ((PyFileObject *)fobj)->f_newlinetypes;		skipnextlf = ((PyFileObject *)fobj)->f_skipnextlf;	}	FLOCKFILE(stream);	c = 'x'; /* Shut up gcc warning */	while (--n > 0 && (c = GETC(stream)) != EOF ) {		if (skipnextlf ) {			skipnextlf = 0;			if (c == '\n') {				/* Seeing a \n here with skipnextlf true				** means we saw a \r before.				*/				newlinetypes |= NEWLINE_CRLF;				c = GETC(stream);				if (c == EOF) break;			} else {				/*				** Note that c == EOF also brings us here,				** so we're okay if the last char in the file				** is a CR.				*/				newlinetypes |= NEWLINE_CR;			}		}		if (c == '\r') {			/* A \r is translated into a \n, and we skip			** an adjacent \n, if any. We don't set the			** newlinetypes flag until we've seen the next char.			*/			skipnextlf = 1;			c = '\n';		} else if ( c == '\n') {			newlinetypes |= NEWLINE_LF;		}		*p++ = c;		if (c == '\n') break;	}	if ( c == EOF && skipnextlf )		newlinetypes |= NEWLINE_CR;	FUNLOCKFILE(stream);	*p = '\0';	if (fobj) {		((PyFileObject *)fobj)->f_newlinetypes = newlinetypes;		((PyFileObject *)fobj)->f_skipnextlf = skipnextlf;	} else if ( skipnextlf ) {		/* If we have no file object we cannot save the		** skipnextlf flag. We have to readahead, which		** will cause a pause if we're reading from an		** interactive stream, but that is very unlikely		** unless we're doing something silly like		** execfile("/dev/tty").		*/		c = GETC(stream);		if ( c != '\n' )			ungetc(c, stream);	}	if (p == buf)		return NULL;	return buf;} /*** Py_UniversalNewlineFread is an fread variation that understands** all of \r, \n and \r\n conventions.** The stream should be opened in binary mode.** fobj must be a PyFileObject. In this case there** is no readahead but in stead a flag is used to skip a following** \n on the next read. Also, if the file is open in binary mode** the whole conversion is skipped. Finally, the routine keeps track of** the different types of newlines seen.*/size_tPy_UniversalNewlineFread(char *buf, size_t n,			 FILE *stream, PyObject *fobj){	char *dst = buf;	PyFileObject *f = (PyFileObject *)fobj;	int newlinetypes, skipnextlf; 	assert(buf != NULL);	assert(stream != NULL); 	if (!fobj || !PyFile_Check(fobj)) {		errno = ENXIO;	/* What can you do... */		return 0;	}	if (!f->f_univ_newline)		return fread(buf, 1, n, stream);	newlinetypes = f->f_newlinetypes;	skipnextlf = f->f_skipnextlf;	/* Invariant:  n is the number of bytes remaining to be filled	 * in the buffer.	 */	while (n) {		size_t nread;		int shortread;		char *src = dst; 		nread = fread(dst, 1, n, stream);		assert(nread <= n);		if (nread == 0)			break; 		n -= nread; /* assuming 1 byte out for each in; will adjust */		shortread = n != 0;	/* true iff EOF or error */		while (nread--) {			char c = *src++;			if (c == '\r') {				/* Save as LF and set flag to skip next LF. */				*dst++ = '\n';				skipnextlf = 1;			}			else if (skipnextlf && c == '\n') {				/* Skip LF, and remember we saw CR LF. */				skipnextlf = 0;				newlinetypes |= NEWLINE_CRLF;				++n;			}			else {				/* Normal char to be stored in buffer.  Also				 * update the newlinetypes flag if either this				 * is an LF or the previous char was a CR.				 */				if (c == '\n')					newlinetypes |= NEWLINE_LF;				else if (skipnextlf)					newlinetypes |= NEWLINE_CR;				*dst++ = c;				skipnextlf = 0;			}		}		if (shortread) {			/* If this is EOF, update type flags. */			if (skipnextlf && feof(stream))				newlinetypes |= NEWLINE_CR;			break;		}	}	f->f_newlinetypes = newlinetypes;	f->f_skipnextlf = skipnextlf;	return dst - buf;} #ifdef __cplusplus}#endif

Lines 2001–2487 of 2487. Previous lines