cinap_lenrekadd hg and python4bb9e2215 years agoHistory
1604 lines · 42.3 KB · C
RawDownload
/* csv module */ /* This module provides the low-level underpinnings of a CSV reading/writingmodule.  Users should not use this module directly, but import the csv.pymodule instead. **** For people modifying this code, please note that as of this writing**** (2003-03-23), it is intended that this code should work with Python**** 2.2. */ #define MODULE_VERSION "1.0" #include "Python.h"#include "structmember.h"  /* begin 2.2 compatibility macros */#ifndef PyDoc_STRVAR/* Define macros for inline documentation. */#define PyDoc_VAR(name) static char name[]#define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str)#ifdef WITH_DOC_STRINGS#define PyDoc_STR(str) str#else#define PyDoc_STR(str) ""#endif#endif /* ifndef PyDoc_STRVAR */ #ifndef PyMODINIT_FUNC#	if defined(__cplusplus)#		define PyMODINIT_FUNC extern "C" void#	else /* __cplusplus */#		define PyMODINIT_FUNC void#	endif /* __cplusplus */#endif #ifndef Py_CLEAR#define Py_CLEAR(op)						\	do {							\		if (op) {					\			PyObject *tmp = (PyObject *)(op);	\			(op) = NULL;				\			Py_DECREF(tmp);				\		}						\	} while (0)#endif#ifndef Py_VISIT#define Py_VISIT(op)							\        do { 								\                if (op) {						\                        int vret = visit((PyObject *)(op), arg);	\                        if (vret)					\                                return vret;				\                }							\        } while (0)#endif /* end 2.2 compatibility macros */ #define IS_BASESTRING(o) \	PyObject_TypeCheck(o, &PyBaseString_Type) static PyObject *error_obj;	/* CSV exception */static PyObject *dialects;      /* Dialect registry */static long field_limit = 128 * 1024;	/* max parsed field size */ typedef enum {	START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD, 	IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, QUOTE_IN_QUOTED_FIELD,	EAT_CRNL} ParserState; typedef enum {	QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE} QuoteStyle; typedef struct {	QuoteStyle style;	char *name;} StyleDesc; static StyleDesc quote_styles[] = {	{ QUOTE_MINIMAL,    "QUOTE_MINIMAL" },	{ QUOTE_ALL,        "QUOTE_ALL" },	{ QUOTE_NONNUMERIC, "QUOTE_NONNUMERIC" },	{ QUOTE_NONE,       "QUOTE_NONE" },	{ 0 }}; typedef struct {        PyObject_HEAD        	int doublequote;	/* is " represented by ""? */	char delimiter;		/* field separator */	char quotechar;		/* quote character */	char escapechar;	/* escape character */	int skipinitialspace;	/* ignore spaces following delimiter? */	PyObject *lineterminator; /* string to write between records */	int quoting;		/* style of quoting to write */ 	int strict;		/* raise exception on bad CSV */} DialectObj; staticforward PyTypeObject Dialect_Type; typedef struct {        PyObject_HEAD         PyObject *input_iter;   /* iterate over this for input lines */         DialectObj *dialect;    /* parsing dialect */ 	PyObject *fields;	/* field list for current record */	ParserState state;	/* current CSV parse state */	char *field;		/* build current field in here */	int field_size;		/* size of allocated buffer */	int field_len;		/* length of current field */	int numeric_field;	/* treat field as numeric */	unsigned long line_num;	/* Source-file line number */} ReaderObj; staticforward PyTypeObject Reader_Type; #define ReaderObject_Check(v)   ((v)->ob_type == &Reader_Type) typedef struct {        PyObject_HEAD         PyObject *writeline;    /* write output lines to this file */         DialectObj *dialect;    /* parsing dialect */ 	char *rec;		/* buffer for parser.join */	int rec_size;		/* size of allocated record */	int rec_len;		/* length of record */	int num_fields;		/* number of fields in record */} WriterObj;         staticforward PyTypeObject Writer_Type; /* * DIALECT class */ static PyObject *get_dialect_from_registry(PyObject * name_obj){        PyObject *dialect_obj;         dialect_obj = PyDict_GetItem(dialects, name_obj);	if (dialect_obj == NULL) {		if (!PyErr_Occurred())			PyErr_Format(error_obj, "unknown dialect");	}	else		Py_INCREF(dialect_obj);        return dialect_obj;} static PyObject *get_string(PyObject *str){        Py_XINCREF(str);        return str;} static PyObject *get_nullchar_as_None(char c){        if (c == '\0') {                Py_INCREF(Py_None);                return Py_None;        }        else                return PyString_FromStringAndSize((char*)&c, 1);} static PyObject *Dialect_get_lineterminator(DialectObj *self){        return get_string(self->lineterminator);} static PyObject *Dialect_get_escapechar(DialectObj *self){        return get_nullchar_as_None(self->escapechar);} static PyObject *Dialect_get_quotechar(DialectObj *self){        return get_nullchar_as_None(self->quotechar);} static PyObject *Dialect_get_quoting(DialectObj *self){        return PyInt_FromLong(self->quoting);} static int_set_bool(const char *name, int *target, PyObject *src, int dflt){	if (src == NULL)		*target = dflt;	else		*target = PyObject_IsTrue(src);	return 0;} static int_set_int(const char *name, int *target, PyObject *src, int dflt){	if (src == NULL)		*target = dflt;	else {		if (!PyInt_Check(src)) {			PyErr_Format(PyExc_TypeError, 				     "\"%s\" must be an integer", name);			return -1;		}		*target = PyInt_AsLong(src);	}	return 0;} static int_set_char(const char *name, char *target, PyObject *src, char dflt){	if (src == NULL)		*target = dflt;	else {		if (src == Py_None || PyString_Size(src) == 0)			*target = '\0';		else if (!PyString_Check(src) || PyString_Size(src) != 1) {			PyErr_Format(PyExc_TypeError, 				     "\"%s\" must be an 1-character string", 				     name);			return -1;		}		else {			char *s = PyString_AsString(src);			if (s == NULL)				return -1;			*target = s[0];		}	}        return 0;} static int_set_str(const char *name, PyObject **target, PyObject *src, const char *dflt){	if (src == NULL)		*target = PyString_FromString(dflt);	else {		if (src == Py_None)			*target = NULL;		else if (!IS_BASESTRING(src)) {			PyErr_Format(PyExc_TypeError, 				     "\"%s\" must be an string", name);			return -1;		}		else {			Py_XDECREF(*target);			Py_INCREF(src);			*target = src;		}	}        return 0;} static intdialect_check_quoting(int quoting){        StyleDesc *qs = quote_styles; 	for (qs = quote_styles; qs->name; qs++) {		if (qs->style == quoting)                        return 0;        }	PyErr_Format(PyExc_TypeError, "bad \"quoting\" value");        return -1;} #define D_OFF(x) offsetof(DialectObj, x) static struct PyMemberDef Dialect_memberlist[] = {	{ "delimiter",          T_CHAR, D_OFF(delimiter), READONLY },	{ "skipinitialspace",   T_INT, D_OFF(skipinitialspace), READONLY },	{ "doublequote",        T_INT, D_OFF(doublequote), READONLY },	{ "strict",             T_INT, D_OFF(strict), READONLY },	{ NULL }}; static PyGetSetDef Dialect_getsetlist[] = {	{ "escapechar",		(getter)Dialect_get_escapechar},	{ "lineterminator",	(getter)Dialect_get_lineterminator},	{ "quotechar",		(getter)Dialect_get_quotechar},	{ "quoting",		(getter)Dialect_get_quoting},	{NULL},}; static voidDialect_dealloc(DialectObj *self){        Py_XDECREF(self->lineterminator);        self->ob_type->tp_free((PyObject *)self);} static char *dialect_kws[] = {	"dialect",	"delimiter",	"doublequote",	"escapechar",	"lineterminator",	"quotechar",	"quoting",	"skipinitialspace",	"strict",	NULL}; static PyObject *dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs){	DialectObj *self;	PyObject *ret = NULL;	PyObject *dialect = NULL;	PyObject *delimiter = NULL;	PyObject *doublequote = NULL;	PyObject *escapechar = NULL;	PyObject *lineterminator = NULL;	PyObject *quotechar = NULL;	PyObject *quoting = NULL;	PyObject *skipinitialspace = NULL;	PyObject *strict = NULL; 	if (!PyArg_ParseTupleAndKeywords(args, kwargs,					 "|OOOOOOOOO", dialect_kws,					 &dialect,					 &delimiter,					 &doublequote,					 &escapechar,					 &lineterminator,					 &quotechar,					 &quoting,					 &skipinitialspace,					 &strict))		return NULL; 	if (dialect != NULL) {		if (IS_BASESTRING(dialect)) {			dialect = get_dialect_from_registry(dialect);			if (dialect == NULL)				return NULL;		}		else			Py_INCREF(dialect);		/* Can we reuse this instance? */		if (PyObject_TypeCheck(dialect, &Dialect_Type) &&		    delimiter == 0 &&		    doublequote == 0 &&		    escapechar == 0 &&		    lineterminator == 0 &&		    quotechar == 0 &&		    quoting == 0 &&		    skipinitialspace == 0 &&		    strict == 0)			return dialect;	} 	self = (DialectObj *)type->tp_alloc(type, 0);	if (self == NULL) {		Py_XDECREF(dialect);		return NULL;	}	self->lineterminator = NULL; 	Py_XINCREF(delimiter);	Py_XINCREF(doublequote);	Py_XINCREF(escapechar);	Py_XINCREF(lineterminator);	Py_XINCREF(quotechar);	Py_XINCREF(quoting);	Py_XINCREF(skipinitialspace);	Py_XINCREF(strict);	if (dialect != NULL) {#define DIALECT_GETATTR(v, n) \		if (v == NULL) \			v = PyObject_GetAttrString(dialect, n)		DIALECT_GETATTR(delimiter, "delimiter");		DIALECT_GETATTR(doublequote, "doublequote");		DIALECT_GETATTR(escapechar, "escapechar");		DIALECT_GETATTR(lineterminator, "lineterminator");		DIALECT_GETATTR(quotechar, "quotechar");		DIALECT_GETATTR(quoting, "quoting");		DIALECT_GETATTR(skipinitialspace, "skipinitialspace");		DIALECT_GETATTR(strict, "strict");		PyErr_Clear();	} 	/* check types and convert to C values */#define DIASET(meth, name, target, src, dflt) \	if (meth(name, target, src, dflt)) \		goto err	DIASET(_set_char, "delimiter", &self->delimiter, delimiter, ',');	DIASET(_set_bool, "doublequote", &self->doublequote, doublequote, 1);	DIASET(_set_char, "escapechar", &self->escapechar, escapechar, 0);	DIASET(_set_str, "lineterminator", &self->lineterminator, lineterminator, "\r\n");	DIASET(_set_char, "quotechar", &self->quotechar, quotechar, '"');	DIASET(_set_int, "quoting", &self->quoting, quoting, QUOTE_MINIMAL);	DIASET(_set_bool, "skipinitialspace", &self->skipinitialspace, skipinitialspace, 0);	DIASET(_set_bool, "strict", &self->strict, strict, 0); 	/* validate options */	if (dialect_check_quoting(self->quoting))		goto err;	if (self->delimiter == 0) {                PyErr_SetString(PyExc_TypeError, "delimiter must be set");		goto err;	}	if (quotechar == Py_None && quoting == NULL)		self->quoting = QUOTE_NONE;	if (self->quoting != QUOTE_NONE && self->quotechar == 0) {                PyErr_SetString(PyExc_TypeError, 				"quotechar must be set if quoting enabled");		goto err;	}	if (self->lineterminator == 0) {		PyErr_SetString(PyExc_TypeError, "lineterminator must be set");		goto err;	} 	ret = (PyObject *)self;	Py_INCREF(self);err:	Py_XDECREF(self);	Py_XDECREF(dialect);	Py_XDECREF(delimiter);	Py_XDECREF(doublequote);	Py_XDECREF(escapechar);	Py_XDECREF(lineterminator);	Py_XDECREF(quotechar);	Py_XDECREF(quoting);	Py_XDECREF(skipinitialspace);	Py_XDECREF(strict);	return ret;}  PyDoc_STRVAR(Dialect_Type_doc, "CSV dialect\n""\n""The Dialect type records CSV parsing and generation options.\n"); static PyTypeObject Dialect_Type = {	PyObject_HEAD_INIT(NULL)	0,                                      /* ob_size */	"_csv.Dialect",                         /* tp_name */	sizeof(DialectObj),                     /* tp_basicsize */	0,                                      /* tp_itemsize */	/*  methods  */	(destructor)Dialect_dealloc,            /* tp_dealloc */	(printfunc)0,                           /* tp_print */	(getattrfunc)0,                         /* tp_getattr */	(setattrfunc)0,                         /* tp_setattr */	(cmpfunc)0,                             /* tp_compare */	(reprfunc)0,                            /* tp_repr */	0,                                      /* tp_as_number */	0,                                      /* tp_as_sequence */	0,                                      /* tp_as_mapping */	(hashfunc)0,                            /* tp_hash */	(ternaryfunc)0,                         /* tp_call */	(reprfunc)0,                    	/* tp_str */	0,                                      /* tp_getattro */        0,                                      /* tp_setattro */        0,                                      /* tp_as_buffer */        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */	Dialect_Type_doc,                       /* tp_doc */        0,                                      /* tp_traverse */        0,                                      /* tp_clear */        0,                                      /* tp_richcompare */        0,                                      /* tp_weaklistoffset */        0,                                      /* tp_iter */        0,                                      /* tp_iternext */	0,					/* tp_methods */        Dialect_memberlist,                     /* tp_members */        Dialect_getsetlist,                     /* tp_getset */	0,					/* tp_base */	0,					/* tp_dict */	0,					/* tp_descr_get */	0,					/* tp_descr_set */	0,					/* tp_dictoffset */	0,					/* tp_init */

Lines 1–500 of 1604.