LCOV - code coverage report
Current view: top level - Modules - _csv.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 52 757 6.9 %
Date: 2023-03-20 08:15:36 Functions: 6 52 11.5 %
Branches: 34 635 5.4 %

           Branch data     Line data    Source code
       1                 :            : /* csv module */
       2                 :            : 
       3                 :            : /*
       4                 :            : 
       5                 :            : This module provides the low-level underpinnings of a CSV reading/writing
       6                 :            : module.  Users should not use this module directly, but import the csv.py
       7                 :            : module instead.
       8                 :            : 
       9                 :            : */
      10                 :            : 
      11                 :            : #define MODULE_VERSION "1.0"
      12                 :            : 
      13                 :            : #include "Python.h"
      14                 :            : #include "structmember.h"         // PyMemberDef
      15                 :            : #include <stdbool.h>
      16                 :            : 
      17                 :            : /*[clinic input]
      18                 :            : module _csv
      19                 :            : [clinic start generated code]*/
      20                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=385118b71aa43706]*/
      21                 :            : 
      22                 :            : #include "clinic/_csv.c.h"
      23                 :            : #define NOT_SET ((Py_UCS4)-1)
      24                 :            : #define EOL ((Py_UCS4)-2)
      25                 :            : 
      26                 :            : 
      27                 :            : typedef struct {
      28                 :            :     PyObject *error_obj;   /* CSV exception */
      29                 :            :     PyObject *dialects;   /* Dialect registry */
      30                 :            :     PyTypeObject *dialect_type;
      31                 :            :     PyTypeObject *reader_type;
      32                 :            :     PyTypeObject *writer_type;
      33                 :            :     long field_limit;   /* max parsed field size */
      34                 :            :     PyObject *str_write;
      35                 :            : } _csvstate;
      36                 :            : 
      37                 :            : static struct PyModuleDef _csvmodule;
      38                 :            : 
      39                 :            : static inline _csvstate*
      40                 :          1 : get_csv_state(PyObject *module)
      41                 :            : {
      42                 :          1 :     void *state = PyModule_GetState(module);
      43                 :            :     assert(state != NULL);
      44                 :          1 :     return (_csvstate *)state;
      45                 :            : }
      46                 :            : 
      47                 :            : static int
      48                 :          2 : _csv_clear(PyObject *module)
      49                 :            : {
      50                 :          2 :     _csvstate *module_state = PyModule_GetState(module);
      51         [ +  + ]:          2 :     Py_CLEAR(module_state->error_obj);
      52         [ +  + ]:          2 :     Py_CLEAR(module_state->dialects);
      53         [ +  + ]:          2 :     Py_CLEAR(module_state->dialect_type);
      54         [ +  + ]:          2 :     Py_CLEAR(module_state->reader_type);
      55         [ +  + ]:          2 :     Py_CLEAR(module_state->writer_type);
      56         [ +  + ]:          2 :     Py_CLEAR(module_state->str_write);
      57                 :          2 :     return 0;
      58                 :            : }
      59                 :            : 
      60                 :            : static int
      61                 :          8 : _csv_traverse(PyObject *module, visitproc visit, void *arg)
      62                 :            : {
      63                 :          8 :     _csvstate *module_state = PyModule_GetState(module);
      64   [ +  -  -  + ]:          8 :     Py_VISIT(module_state->error_obj);
      65   [ +  -  -  + ]:          8 :     Py_VISIT(module_state->dialects);
      66   [ +  -  -  + ]:          8 :     Py_VISIT(module_state->dialect_type);
      67   [ +  -  -  + ]:          8 :     Py_VISIT(module_state->reader_type);
      68   [ +  -  -  + ]:          8 :     Py_VISIT(module_state->writer_type);
      69                 :          8 :     return 0;
      70                 :            : }
      71                 :            : 
      72                 :            : static void
      73                 :          1 : _csv_free(void *module)
      74                 :            : {
      75                 :          1 :    _csv_clear((PyObject *)module);
      76                 :          1 : }
      77                 :            : 
      78                 :            : typedef enum {
      79                 :            :     START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD,
      80                 :            :     IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, QUOTE_IN_QUOTED_FIELD,
      81                 :            :     EAT_CRNL,AFTER_ESCAPED_CRNL
      82                 :            : } ParserState;
      83                 :            : 
      84                 :            : typedef enum {
      85                 :            :     QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE
      86                 :            : } QuoteStyle;
      87                 :            : 
      88                 :            : typedef struct {
      89                 :            :     QuoteStyle style;
      90                 :            :     const char *name;
      91                 :            : } StyleDesc;
      92                 :            : 
      93                 :            : static const StyleDesc quote_styles[] = {
      94                 :            :     { QUOTE_MINIMAL,    "QUOTE_MINIMAL" },
      95                 :            :     { QUOTE_ALL,        "QUOTE_ALL" },
      96                 :            :     { QUOTE_NONNUMERIC, "QUOTE_NONNUMERIC" },
      97                 :            :     { QUOTE_NONE,       "QUOTE_NONE" },
      98                 :            :     { 0 }
      99                 :            : };
     100                 :            : 
     101                 :            : typedef struct {
     102                 :            :     PyObject_HEAD
     103                 :            : 
     104                 :            :     char doublequote;           /* is " represented by ""? */
     105                 :            :     char skipinitialspace;      /* ignore spaces following delimiter? */
     106                 :            :     char strict;                /* raise exception on bad CSV */
     107                 :            :     int quoting;                /* style of quoting to write */
     108                 :            :     Py_UCS4 delimiter;          /* field separator */
     109                 :            :     Py_UCS4 quotechar;          /* quote character */
     110                 :            :     Py_UCS4 escapechar;         /* escape character */
     111                 :            :     PyObject *lineterminator;   /* string to write between records */
     112                 :            : 
     113                 :            : } DialectObj;
     114                 :            : 
     115                 :            : typedef struct {
     116                 :            :     PyObject_HEAD
     117                 :            : 
     118                 :            :     PyObject *input_iter;   /* iterate over this for input lines */
     119                 :            : 
     120                 :            :     DialectObj *dialect;    /* parsing dialect */
     121                 :            : 
     122                 :            :     PyObject *fields;           /* field list for current record */
     123                 :            :     ParserState state;          /* current CSV parse state */
     124                 :            :     Py_UCS4 *field;             /* temporary buffer */
     125                 :            :     Py_ssize_t field_size;      /* size of allocated buffer */
     126                 :            :     Py_ssize_t field_len;       /* length of current field */
     127                 :            :     int numeric_field;          /* treat field as numeric */
     128                 :            :     unsigned long line_num;     /* Source-file line number */
     129                 :            : } ReaderObj;
     130                 :            : 
     131                 :            : typedef struct {
     132                 :            :     PyObject_HEAD
     133                 :            : 
     134                 :            :     PyObject *write;    /* write output lines to this file */
     135                 :            : 
     136                 :            :     DialectObj *dialect;    /* parsing dialect */
     137                 :            : 
     138                 :            :     Py_UCS4 *rec;            /* buffer for parser.join */
     139                 :            :     Py_ssize_t rec_size;        /* size of allocated record */
     140                 :            :     Py_ssize_t rec_len;         /* length of record */
     141                 :            :     int num_fields;             /* number of fields in record */
     142                 :            : 
     143                 :            :     PyObject *error_obj;       /* cached error object */
     144                 :            : } WriterObj;
     145                 :            : 
     146                 :            : /*
     147                 :            :  * DIALECT class
     148                 :            :  */
     149                 :            : 
     150                 :            : static PyObject *
     151                 :          0 : get_dialect_from_registry(PyObject *name_obj, _csvstate *module_state)
     152                 :            : {
     153                 :            :     PyObject *dialect_obj;
     154                 :            : 
     155                 :          0 :     dialect_obj = PyDict_GetItemWithError(module_state->dialects, name_obj);
     156         [ #  # ]:          0 :     if (dialect_obj == NULL) {
     157         [ #  # ]:          0 :         if (!PyErr_Occurred())
     158                 :          0 :             PyErr_Format(module_state->error_obj, "unknown dialect");
     159                 :            :     }
     160                 :            :     else
     161                 :          0 :         Py_INCREF(dialect_obj);
     162                 :            : 
     163                 :          0 :     return dialect_obj;
     164                 :            : }
     165                 :            : 
     166                 :            : static PyObject *
     167                 :          0 : get_char_or_None(Py_UCS4 c)
     168                 :            : {
     169         [ #  # ]:          0 :     if (c == NOT_SET) {
     170                 :          0 :         Py_RETURN_NONE;
     171                 :            :     }
     172                 :            :     else
     173                 :          0 :         return PyUnicode_FromOrdinal(c);
     174                 :            : }
     175                 :            : 
     176                 :            : static PyObject *
     177                 :          0 : Dialect_get_lineterminator(DialectObj *self, void *Py_UNUSED(ignored))
     178                 :            : {
     179                 :          0 :     return Py_XNewRef(self->lineterminator);
     180                 :            : }
     181                 :            : 
     182                 :            : static PyObject *
     183                 :          0 : Dialect_get_delimiter(DialectObj *self, void *Py_UNUSED(ignored))
     184                 :            : {
     185                 :          0 :     return get_char_or_None(self->delimiter);
     186                 :            : }
     187                 :            : 
     188                 :            : static PyObject *
     189                 :          0 : Dialect_get_escapechar(DialectObj *self, void *Py_UNUSED(ignored))
     190                 :            : {
     191                 :          0 :     return get_char_or_None(self->escapechar);
     192                 :            : }
     193                 :            : 
     194                 :            : static PyObject *
     195                 :          0 : Dialect_get_quotechar(DialectObj *self, void *Py_UNUSED(ignored))
     196                 :            : {
     197                 :          0 :     return get_char_or_None(self->quotechar);
     198                 :            : }
     199                 :            : 
     200                 :            : static PyObject *
     201                 :          0 : Dialect_get_quoting(DialectObj *self, void *Py_UNUSED(ignored))
     202                 :            : {
     203                 :          0 :     return PyLong_FromLong(self->quoting);
     204                 :            : }
     205                 :            : 
     206                 :            : static int
     207                 :          0 : _set_bool(const char *name, char *target, PyObject *src, bool dflt)
     208                 :            : {
     209         [ #  # ]:          0 :     if (src == NULL)
     210                 :          0 :         *target = dflt;
     211                 :            :     else {
     212                 :          0 :         int b = PyObject_IsTrue(src);
     213         [ #  # ]:          0 :         if (b < 0)
     214                 :          0 :             return -1;
     215                 :          0 :         *target = (char)b;
     216                 :            :     }
     217                 :          0 :     return 0;
     218                 :            : }
     219                 :            : 
     220                 :            : static int
     221                 :          0 : _set_int(const char *name, int *target, PyObject *src, int dflt)
     222                 :            : {
     223         [ #  # ]:          0 :     if (src == NULL)
     224                 :          0 :         *target = dflt;
     225                 :            :     else {
     226                 :            :         int value;
     227         [ #  # ]:          0 :         if (!PyLong_CheckExact(src)) {
     228                 :          0 :             PyErr_Format(PyExc_TypeError,
     229                 :            :                          "\"%s\" must be an integer", name);
     230                 :          0 :             return -1;
     231                 :            :         }
     232                 :          0 :         value = _PyLong_AsInt(src);
     233   [ #  #  #  # ]:          0 :         if (value == -1 && PyErr_Occurred()) {
     234                 :          0 :             return -1;
     235                 :            :         }
     236                 :          0 :         *target = value;
     237                 :            :     }
     238                 :          0 :     return 0;
     239                 :            : }
     240                 :            : 
     241                 :            : static int
     242                 :          0 : _set_char_or_none(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt)
     243                 :            : {
     244         [ #  # ]:          0 :     if (src == NULL) {
     245                 :          0 :         *target = dflt;
     246                 :            :     }
     247                 :            :     else {
     248                 :          0 :         *target = NOT_SET;
     249         [ #  # ]:          0 :         if (src != Py_None) {
     250         [ #  # ]:          0 :             if (!PyUnicode_Check(src)) {
     251                 :          0 :                 PyErr_Format(PyExc_TypeError,
     252                 :            :                     "\"%s\" must be string or None, not %.200s", name,
     253                 :          0 :                     Py_TYPE(src)->tp_name);
     254                 :          0 :                 return -1;
     255                 :            :             }
     256                 :          0 :             Py_ssize_t len = PyUnicode_GetLength(src);
     257         [ #  # ]:          0 :             if (len < 0) {
     258                 :          0 :                 return -1;
     259                 :            :             }
     260         [ #  # ]:          0 :             if (len != 1) {
     261                 :          0 :                 PyErr_Format(PyExc_TypeError,
     262                 :            :                     "\"%s\" must be a 1-character string",
     263                 :            :                     name);
     264                 :          0 :                 return -1;
     265                 :            :             }
     266                 :            :             /* PyUnicode_READY() is called in PyUnicode_GetLength() */
     267                 :          0 :             *target = PyUnicode_READ_CHAR(src, 0);
     268                 :            :         }
     269                 :            :     }
     270                 :          0 :     return 0;
     271                 :            : }
     272                 :            : 
     273                 :            : static int
     274                 :          0 : _set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt)
     275                 :            : {
     276         [ #  # ]:          0 :     if (src == NULL) {
     277                 :          0 :         *target = dflt;
     278                 :            :     }
     279                 :            :     else {
     280         [ #  # ]:          0 :         if (!PyUnicode_Check(src)) {
     281                 :          0 :             PyErr_Format(PyExc_TypeError,
     282                 :            :                          "\"%s\" must be string, not %.200s", name,
     283                 :          0 :                          Py_TYPE(src)->tp_name);
     284                 :          0 :                 return -1;
     285                 :            :         }
     286                 :          0 :         Py_ssize_t len = PyUnicode_GetLength(src);
     287         [ #  # ]:          0 :         if (len < 0) {
     288                 :          0 :             return -1;
     289                 :            :         }
     290         [ #  # ]:          0 :         if (len != 1) {
     291                 :          0 :             PyErr_Format(PyExc_TypeError,
     292                 :            :                          "\"%s\" must be a 1-character string",
     293                 :            :                          name);
     294                 :          0 :             return -1;
     295                 :            :         }
     296                 :            :         /* PyUnicode_READY() is called in PyUnicode_GetLength() */
     297                 :          0 :         *target = PyUnicode_READ_CHAR(src, 0);
     298                 :            :     }
     299                 :          0 :     return 0;
     300                 :            : }
     301                 :            : 
     302                 :            : static int
     303                 :          0 : _set_str(const char *name, PyObject **target, PyObject *src, const char *dflt)
     304                 :            : {
     305         [ #  # ]:          0 :     if (src == NULL)
     306                 :          0 :         *target = PyUnicode_DecodeASCII(dflt, strlen(dflt), NULL);
     307                 :            :     else {
     308         [ #  # ]:          0 :         if (src == Py_None)
     309                 :          0 :             *target = NULL;
     310         [ #  # ]:          0 :         else if (!PyUnicode_Check(src)) {
     311                 :          0 :             PyErr_Format(PyExc_TypeError,
     312                 :            :                          "\"%s\" must be a string", name);
     313                 :          0 :             return -1;
     314                 :            :         }
     315                 :            :         else {
     316         [ #  # ]:          0 :             if (PyUnicode_READY(src) == -1)
     317                 :          0 :                 return -1;
     318                 :          0 :             Py_XSETREF(*target, Py_NewRef(src));
     319                 :            :         }
     320                 :            :     }
     321                 :          0 :     return 0;
     322                 :            : }
     323                 :            : 
     324                 :            : static int
     325                 :          0 : dialect_check_quoting(int quoting)
     326                 :            : {
     327                 :            :     const StyleDesc *qs;
     328                 :            : 
     329         [ #  # ]:          0 :     for (qs = quote_styles; qs->name; qs++) {
     330         [ #  # ]:          0 :         if ((int)qs->style == quoting)
     331                 :          0 :             return 0;
     332                 :            :     }
     333                 :          0 :     PyErr_Format(PyExc_TypeError, "bad \"quoting\" value");
     334                 :          0 :     return -1;
     335                 :            : }
     336                 :            : 
     337                 :            : #define D_OFF(x) offsetof(DialectObj, x)
     338                 :            : 
     339                 :            : static struct PyMemberDef Dialect_memberlist[] = {
     340                 :            :     { "skipinitialspace",   T_BOOL, D_OFF(skipinitialspace), READONLY },
     341                 :            :     { "doublequote",        T_BOOL, D_OFF(doublequote), READONLY },
     342                 :            :     { "strict",             T_BOOL, D_OFF(strict), READONLY },
     343                 :            :     { NULL }
     344                 :            : };
     345                 :            : 
     346                 :            : static PyGetSetDef Dialect_getsetlist[] = {
     347                 :            :     { "delimiter",          (getter)Dialect_get_delimiter},
     348                 :            :     { "escapechar",             (getter)Dialect_get_escapechar},
     349                 :            :     { "lineterminator",         (getter)Dialect_get_lineterminator},
     350                 :            :     { "quotechar",              (getter)Dialect_get_quotechar},
     351                 :            :     { "quoting",                (getter)Dialect_get_quoting},
     352                 :            :     {NULL},
     353                 :            : };
     354                 :            : 
     355                 :            : static void
     356                 :          0 : Dialect_dealloc(DialectObj *self)
     357                 :            : {
     358                 :          0 :     PyTypeObject *tp = Py_TYPE(self);
     359                 :          0 :     PyObject_GC_UnTrack(self);
     360                 :          0 :     tp->tp_clear((PyObject *)self);
     361                 :          0 :     PyObject_GC_Del(self);
     362                 :          0 :     Py_DECREF(tp);
     363                 :          0 : }
     364                 :            : 
     365                 :            : static char *dialect_kws[] = {
     366                 :            :     "dialect",
     367                 :            :     "delimiter",
     368                 :            :     "doublequote",
     369                 :            :     "escapechar",
     370                 :            :     "lineterminator",
     371                 :            :     "quotechar",
     372                 :            :     "quoting",
     373                 :            :     "skipinitialspace",
     374                 :            :     "strict",
     375                 :            :     NULL
     376                 :            : };
     377                 :            : 
     378                 :            : static _csvstate *
     379                 :          0 : _csv_state_from_type(PyTypeObject *type, const char *name)
     380                 :            : {
     381                 :          0 :     PyObject *module = PyType_GetModuleByDef(type, &_csvmodule);
     382         [ #  # ]:          0 :     if (module == NULL) {
     383                 :          0 :         return NULL;
     384                 :            :     }
     385                 :          0 :     _csvstate *module_state = PyModule_GetState(module);
     386         [ #  # ]:          0 :     if (module_state == NULL) {
     387                 :          0 :         PyErr_Format(PyExc_SystemError,
     388                 :            :                      "%s: No _csv module state found", name);
     389                 :          0 :         return NULL;
     390                 :            :     }
     391                 :          0 :     return module_state;
     392                 :            : }
     393                 :            : 
     394                 :            : static PyObject *
     395                 :          0 : dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     396                 :            : {
     397                 :            :     DialectObj *self;
     398                 :          0 :     PyObject *ret = NULL;
     399                 :          0 :     PyObject *dialect = NULL;
     400                 :          0 :     PyObject *delimiter = NULL;
     401                 :          0 :     PyObject *doublequote = NULL;
     402                 :          0 :     PyObject *escapechar = NULL;
     403                 :          0 :     PyObject *lineterminator = NULL;
     404                 :          0 :     PyObject *quotechar = NULL;
     405                 :          0 :     PyObject *quoting = NULL;
     406                 :          0 :     PyObject *skipinitialspace = NULL;
     407                 :          0 :     PyObject *strict = NULL;
     408                 :            : 
     409         [ #  # ]:          0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
     410                 :            :                                      "|OOOOOOOOO", dialect_kws,
     411                 :            :                                      &dialect,
     412                 :            :                                      &delimiter,
     413                 :            :                                      &doublequote,
     414                 :            :                                      &escapechar,
     415                 :            :                                      &lineterminator,
     416                 :            :                                      &quotechar,
     417                 :            :                                      &quoting,
     418                 :            :                                      &skipinitialspace,
     419                 :            :                                      &strict))
     420                 :          0 :         return NULL;
     421                 :            : 
     422                 :          0 :     _csvstate *module_state = _csv_state_from_type(type, "dialect_new");
     423         [ #  # ]:          0 :     if (module_state == NULL) {
     424                 :          0 :         return NULL;
     425                 :            :     }
     426                 :            : 
     427         [ #  # ]:          0 :     if (dialect != NULL) {
     428         [ #  # ]:          0 :         if (PyUnicode_Check(dialect)) {
     429                 :          0 :             dialect = get_dialect_from_registry(dialect, module_state);
     430         [ #  # ]:          0 :             if (dialect == NULL)
     431                 :          0 :                 return NULL;
     432                 :            :         }
     433                 :            :         else
     434                 :          0 :             Py_INCREF(dialect);
     435                 :            :         /* Can we reuse this instance? */
     436         [ #  # ]:          0 :         if (PyObject_TypeCheck(dialect, module_state->dialect_type) &&
     437         [ #  # ]:          0 :             delimiter == NULL &&
     438         [ #  # ]:          0 :             doublequote == NULL &&
     439         [ #  # ]:          0 :             escapechar == NULL &&
     440         [ #  # ]:          0 :             lineterminator == NULL &&
     441         [ #  # ]:          0 :             quotechar == NULL &&
     442         [ #  # ]:          0 :             quoting == NULL &&
     443         [ #  # ]:          0 :             skipinitialspace == NULL &&
     444         [ #  # ]:          0 :             strict == NULL)
     445                 :          0 :             return dialect;
     446                 :            :     }
     447                 :            : 
     448                 :          0 :     self = (DialectObj *)type->tp_alloc(type, 0);
     449         [ #  # ]:          0 :     if (self == NULL) {
     450         [ #  # ]:          0 :         Py_CLEAR(dialect);
     451                 :          0 :         return NULL;
     452                 :            :     }
     453                 :          0 :     self->lineterminator = NULL;
     454                 :            : 
     455                 :          0 :     Py_XINCREF(delimiter);
     456                 :          0 :     Py_XINCREF(doublequote);
     457                 :          0 :     Py_XINCREF(escapechar);
     458                 :          0 :     Py_XINCREF(lineterminator);
     459                 :          0 :     Py_XINCREF(quotechar);
     460                 :          0 :     Py_XINCREF(quoting);
     461                 :          0 :     Py_XINCREF(skipinitialspace);
     462                 :          0 :     Py_XINCREF(strict);
     463         [ #  # ]:          0 :     if (dialect != NULL) {
     464                 :            : #define DIALECT_GETATTR(v, n)                            \
     465                 :            :         do {                                             \
     466                 :            :             if (v == NULL) {                             \
     467                 :            :                 v = PyObject_GetAttrString(dialect, n);  \
     468                 :            :                 if (v == NULL)                           \
     469                 :            :                     PyErr_Clear();                       \
     470                 :            :             }                                            \
     471                 :            :         } while (0)
     472   [ #  #  #  # ]:          0 :         DIALECT_GETATTR(delimiter, "delimiter");
     473   [ #  #  #  # ]:          0 :         DIALECT_GETATTR(doublequote, "doublequote");
     474   [ #  #  #  # ]:          0 :         DIALECT_GETATTR(escapechar, "escapechar");
     475   [ #  #  #  # ]:          0 :         DIALECT_GETATTR(lineterminator, "lineterminator");
     476   [ #  #  #  # ]:          0 :         DIALECT_GETATTR(quotechar, "quotechar");
     477   [ #  #  #  # ]:          0 :         DIALECT_GETATTR(quoting, "quoting");
     478   [ #  #  #  # ]:          0 :         DIALECT_GETATTR(skipinitialspace, "skipinitialspace");
     479   [ #  #  #  # ]:          0 :         DIALECT_GETATTR(strict, "strict");
     480                 :            :     }
     481                 :            : 
     482                 :            :     /* check types and convert to C values */
     483                 :            : #define DIASET(meth, name, target, src, dflt) \
     484                 :            :     if (meth(name, target, src, dflt)) \
     485                 :            :         goto err
     486         [ #  # ]:          0 :     DIASET(_set_char, "delimiter", &self->delimiter, delimiter, ',');
     487         [ #  # ]:          0 :     DIASET(_set_bool, "doublequote", &self->doublequote, doublequote, true);
     488         [ #  # ]:          0 :     DIASET(_set_char_or_none, "escapechar", &self->escapechar, escapechar, NOT_SET);
     489         [ #  # ]:          0 :     DIASET(_set_str, "lineterminator", &self->lineterminator, lineterminator, "\r\n");
     490         [ #  # ]:          0 :     DIASET(_set_char_or_none, "quotechar", &self->quotechar, quotechar, '"');
     491         [ #  # ]:          0 :     DIASET(_set_int, "quoting", &self->quoting, quoting, QUOTE_MINIMAL);
     492         [ #  # ]:          0 :     DIASET(_set_bool, "skipinitialspace", &self->skipinitialspace, skipinitialspace, false);
     493         [ #  # ]:          0 :     DIASET(_set_bool, "strict", &self->strict, strict, false);
     494                 :            : 
     495                 :            :     /* validate options */
     496         [ #  # ]:          0 :     if (dialect_check_quoting(self->quoting))
     497                 :          0 :         goto err;
     498         [ #  # ]:          0 :     if (self->delimiter == NOT_SET) {
     499                 :          0 :         PyErr_SetString(PyExc_TypeError,
     500                 :            :                         "\"delimiter\" must be a 1-character string");
     501                 :          0 :         goto err;
     502                 :            :     }
     503   [ #  #  #  # ]:          0 :     if (quotechar == Py_None && quoting == NULL)
     504                 :          0 :         self->quoting = QUOTE_NONE;
     505   [ #  #  #  # ]:          0 :     if (self->quoting != QUOTE_NONE && self->quotechar == NOT_SET) {
     506                 :          0 :         PyErr_SetString(PyExc_TypeError,
     507                 :            :                         "quotechar must be set if quoting enabled");
     508                 :          0 :         goto err;
     509                 :            :     }
     510         [ #  # ]:          0 :     if (self->lineterminator == NULL) {
     511                 :          0 :         PyErr_SetString(PyExc_TypeError, "lineterminator must be set");
     512                 :          0 :         goto err;
     513                 :            :     }
     514                 :            : 
     515                 :          0 :     ret = Py_NewRef(self);
     516                 :          0 : err:
     517         [ #  # ]:          0 :     Py_CLEAR(self);
     518         [ #  # ]:          0 :     Py_CLEAR(dialect);
     519         [ #  # ]:          0 :     Py_CLEAR(delimiter);
     520         [ #  # ]:          0 :     Py_CLEAR(doublequote);
     521         [ #  # ]:          0 :     Py_CLEAR(escapechar);
     522         [ #  # ]:          0 :     Py_CLEAR(lineterminator);
     523         [ #  # ]:          0 :     Py_CLEAR(quotechar);
     524         [ #  # ]:          0 :     Py_CLEAR(quoting);
     525         [ #  # ]:          0 :     Py_CLEAR(skipinitialspace);
     526         [ #  # ]:          0 :     Py_CLEAR(strict);
     527                 :          0 :     return ret;
     528                 :            : }
     529                 :            : 
     530                 :            : /* Since dialect is now a heap type, it inherits pickling method for
     531                 :            :  * protocol 0 and 1 from object, therefore it needs to be overridden */
     532                 :            : 
     533                 :            : PyDoc_STRVAR(dialect_reduce_doc, "raises an exception to avoid pickling");
     534                 :            : 
     535                 :            : static PyObject *
     536                 :          0 : Dialect_reduce(PyObject *self, PyObject *args) {
     537                 :          0 :     PyErr_Format(PyExc_TypeError,
     538                 :            :         "cannot pickle '%.100s' instances", _PyType_Name(Py_TYPE(self)));
     539                 :          0 :     return NULL;
     540                 :            : }
     541                 :            : 
     542                 :            : static struct PyMethodDef dialect_methods[] = {
     543                 :            :     {"__reduce__", Dialect_reduce, METH_VARARGS, dialect_reduce_doc},
     544                 :            :     {"__reduce_ex__", Dialect_reduce, METH_VARARGS, dialect_reduce_doc},
     545                 :            :     {NULL, NULL}
     546                 :            : };
     547                 :            : 
     548                 :            : PyDoc_STRVAR(Dialect_Type_doc,
     549                 :            : "CSV dialect\n"
     550                 :            : "\n"
     551                 :            : "The Dialect type records CSV parsing and generation options.\n");
     552                 :            : 
     553                 :            : static int
     554                 :          0 : Dialect_clear(DialectObj *self)
     555                 :            : {
     556         [ #  # ]:          0 :     Py_CLEAR(self->lineterminator);
     557                 :          0 :     return 0;
     558                 :            : }
     559                 :            : 
     560                 :            : static int
     561                 :          0 : Dialect_traverse(DialectObj *self, visitproc visit, void *arg)
     562                 :            : {
     563   [ #  #  #  # ]:          0 :     Py_VISIT(self->lineterminator);
     564   [ #  #  #  # ]:          0 :     Py_VISIT(Py_TYPE(self));
     565                 :          0 :     return 0;
     566                 :            : }
     567                 :            : 
     568                 :            : static PyType_Slot Dialect_Type_slots[] = {
     569                 :            :     {Py_tp_doc, (char*)Dialect_Type_doc},
     570                 :            :     {Py_tp_members, Dialect_memberlist},
     571                 :            :     {Py_tp_getset, Dialect_getsetlist},
     572                 :            :     {Py_tp_new, dialect_new},
     573                 :            :     {Py_tp_methods, dialect_methods},
     574                 :            :     {Py_tp_dealloc, Dialect_dealloc},
     575                 :            :     {Py_tp_clear, Dialect_clear},
     576                 :            :     {Py_tp_traverse, Dialect_traverse},
     577                 :            :     {0, NULL}
     578                 :            : };
     579                 :            : 
     580                 :            : PyType_Spec Dialect_Type_spec = {
     581                 :            :     .name = "_csv.Dialect",
     582                 :            :     .basicsize = sizeof(DialectObj),
     583                 :            :     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
     584                 :            :               Py_TPFLAGS_IMMUTABLETYPE),
     585                 :            :     .slots = Dialect_Type_slots,
     586                 :            : };
     587                 :            : 
     588                 :            : 
     589                 :            : /*
     590                 :            :  * Return an instance of the dialect type, given a Python instance or kwarg
     591                 :            :  * description of the dialect
     592                 :            :  */
     593                 :            : static PyObject *
     594                 :          0 : _call_dialect(_csvstate *module_state, PyObject *dialect_inst, PyObject *kwargs)
     595                 :            : {
     596                 :          0 :     PyObject *type = (PyObject *)module_state->dialect_type;
     597         [ #  # ]:          0 :     if (dialect_inst) {
     598                 :          0 :         return PyObject_VectorcallDict(type, &dialect_inst, 1, kwargs);
     599                 :            :     }
     600                 :            :     else {
     601                 :          0 :         return PyObject_VectorcallDict(type, NULL, 0, kwargs);
     602                 :            :     }
     603                 :            : }
     604                 :            : 
     605                 :            : /*
     606                 :            :  * READER
     607                 :            :  */
     608                 :            : static int
     609                 :          0 : parse_save_field(ReaderObj *self)
     610                 :            : {
     611                 :            :     PyObject *field;
     612                 :            : 
     613                 :          0 :     field = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
     614                 :          0 :                                       (void *) self->field, self->field_len);
     615         [ #  # ]:          0 :     if (field == NULL)
     616                 :          0 :         return -1;
     617                 :          0 :     self->field_len = 0;
     618         [ #  # ]:          0 :     if (self->numeric_field) {
     619                 :            :         PyObject *tmp;
     620                 :            : 
     621                 :          0 :         self->numeric_field = 0;
     622                 :          0 :         tmp = PyNumber_Float(field);
     623                 :          0 :         Py_DECREF(field);
     624         [ #  # ]:          0 :         if (tmp == NULL)
     625                 :          0 :             return -1;
     626                 :          0 :         field = tmp;
     627                 :            :     }
     628         [ #  # ]:          0 :     if (PyList_Append(self->fields, field) < 0) {
     629                 :          0 :         Py_DECREF(field);
     630                 :          0 :         return -1;
     631                 :            :     }
     632                 :          0 :     Py_DECREF(field);
     633                 :          0 :     return 0;
     634                 :            : }
     635                 :            : 
     636                 :            : static int
     637                 :          0 : parse_grow_buff(ReaderObj *self)
     638                 :            : {
     639                 :            :     assert((size_t)self->field_size <= PY_SSIZE_T_MAX / sizeof(Py_UCS4));
     640                 :            : 
     641         [ #  # ]:          0 :     Py_ssize_t field_size_new = self->field_size ? 2 * self->field_size : 4096;
     642                 :          0 :     Py_UCS4 *field_new = self->field;
     643         [ #  # ]:          0 :     PyMem_Resize(field_new, Py_UCS4, field_size_new);
     644         [ #  # ]:          0 :     if (field_new == NULL) {
     645                 :          0 :         PyErr_NoMemory();
     646                 :          0 :         return 0;
     647                 :            :     }
     648                 :          0 :     self->field = field_new;
     649                 :          0 :     self->field_size = field_size_new;
     650                 :          0 :     return 1;
     651                 :            : }
     652                 :            : 
     653                 :            : static int
     654                 :          0 : parse_add_char(ReaderObj *self, _csvstate *module_state, Py_UCS4 c)
     655                 :            : {
     656         [ #  # ]:          0 :     if (self->field_len >= module_state->field_limit) {
     657                 :          0 :         PyErr_Format(module_state->error_obj,
     658                 :            :                      "field larger than field limit (%ld)",
     659                 :            :                      module_state->field_limit);
     660                 :          0 :         return -1;
     661                 :            :     }
     662   [ #  #  #  # ]:          0 :     if (self->field_len == self->field_size && !parse_grow_buff(self))
     663                 :          0 :         return -1;
     664                 :          0 :     self->field[self->field_len++] = c;
     665                 :          0 :     return 0;
     666                 :            : }
     667                 :            : 
     668                 :            : static int
     669                 :          0 : parse_process_char(ReaderObj *self, _csvstate *module_state, Py_UCS4 c)
     670                 :            : {
     671                 :          0 :     DialectObj *dialect = self->dialect;
     672                 :            : 
     673   [ #  #  #  #  :          0 :     switch (self->state) {
          #  #  #  #  #  
                      # ]
     674                 :          0 :     case START_RECORD:
     675                 :            :         /* start of record */
     676         [ #  # ]:          0 :         if (c == EOL)
     677                 :            :             /* empty line - return [] */
     678                 :          0 :             break;
     679   [ #  #  #  # ]:          0 :         else if (c == '\n' || c == '\r') {
     680                 :          0 :             self->state = EAT_CRNL;
     681                 :          0 :             break;
     682                 :            :         }
     683                 :            :         /* normal character - handle as START_FIELD */
     684                 :          0 :         self->state = START_FIELD;
     685                 :            :         /* fallthru */
     686                 :          0 :     case START_FIELD:
     687                 :            :         /* expecting field */
     688   [ #  #  #  #  :          0 :         if (c == '\n' || c == '\r' || c == EOL) {
                   #  # ]
     689                 :            :             /* save empty field - return [fields] */
     690         [ #  # ]:          0 :             if (parse_save_field(self) < 0)
     691                 :          0 :                 return -1;
     692         [ #  # ]:          0 :             self->state = (c == EOL ? START_RECORD : EAT_CRNL);
     693                 :            :         }
     694         [ #  # ]:          0 :         else if (c == dialect->quotechar &&
     695         [ #  # ]:          0 :                  dialect->quoting != QUOTE_NONE) {
     696                 :            :             /* start quoted field */
     697                 :          0 :             self->state = IN_QUOTED_FIELD;
     698                 :            :         }
     699         [ #  # ]:          0 :         else if (c == dialect->escapechar) {
     700                 :            :             /* possible escaped character */
     701                 :          0 :             self->state = ESCAPED_CHAR;
     702                 :            :         }
     703   [ #  #  #  # ]:          0 :         else if (c == ' ' && dialect->skipinitialspace)
     704                 :            :             /* ignore spaces at start of field */
     705                 :            :             ;
     706         [ #  # ]:          0 :         else if (c == dialect->delimiter) {
     707                 :            :             /* save empty field */
     708         [ #  # ]:          0 :             if (parse_save_field(self) < 0)
     709                 :          0 :                 return -1;
     710                 :            :         }
     711                 :            :         else {
     712                 :            :             /* begin new unquoted field */
     713         [ #  # ]:          0 :             if (dialect->quoting == QUOTE_NONNUMERIC)
     714                 :          0 :                 self->numeric_field = 1;
     715         [ #  # ]:          0 :             if (parse_add_char(self, module_state, c) < 0)
     716                 :          0 :                 return -1;
     717                 :          0 :             self->state = IN_FIELD;
     718                 :            :         }
     719                 :          0 :         break;
     720                 :            : 
     721                 :          0 :     case ESCAPED_CHAR:
     722   [ #  #  #  # ]:          0 :         if (c == '\n' || c=='\r') {
     723         [ #  # ]:          0 :             if (parse_add_char(self, module_state, c) < 0)
     724                 :          0 :                 return -1;
     725                 :          0 :             self->state = AFTER_ESCAPED_CRNL;
     726                 :          0 :             break;
     727                 :            :         }
     728         [ #  # ]:          0 :         if (c == EOL)
     729                 :          0 :             c = '\n';
     730         [ #  # ]:          0 :         if (parse_add_char(self, module_state, c) < 0)
     731                 :          0 :             return -1;
     732                 :          0 :         self->state = IN_FIELD;
     733                 :          0 :         break;
     734                 :            : 
     735                 :          0 :     case AFTER_ESCAPED_CRNL:
     736         [ #  # ]:          0 :         if (c == EOL)
     737                 :          0 :             break;
     738                 :            :         /*fallthru*/
     739                 :            : 
     740                 :            :     case IN_FIELD:
     741                 :            :         /* in unquoted field */
     742   [ #  #  #  #  :          0 :         if (c == '\n' || c == '\r' || c == EOL) {
                   #  # ]
     743                 :            :             /* end of line - return [fields] */
     744         [ #  # ]:          0 :             if (parse_save_field(self) < 0)
     745                 :          0 :                 return -1;
     746         [ #  # ]:          0 :             self->state = (c == EOL ? START_RECORD : EAT_CRNL);
     747                 :            :         }
     748         [ #  # ]:          0 :         else if (c == dialect->escapechar) {
     749                 :            :             /* possible escaped character */
     750                 :          0 :             self->state = ESCAPED_CHAR;
     751                 :            :         }
     752         [ #  # ]:          0 :         else if (c == dialect->delimiter) {
     753                 :            :             /* save field - wait for new field */
     754         [ #  # ]:          0 :             if (parse_save_field(self) < 0)
     755                 :          0 :                 return -1;
     756                 :          0 :             self->state = START_FIELD;
     757                 :            :         }
     758                 :            :         else {
     759                 :            :             /* normal character - save in field */
     760         [ #  # ]:          0 :             if (parse_add_char(self, module_state, c) < 0)
     761                 :          0 :                 return -1;
     762                 :            :         }
     763                 :          0 :         break;
     764                 :            : 
     765                 :          0 :     case IN_QUOTED_FIELD:
     766                 :            :         /* in quoted field */
     767         [ #  # ]:          0 :         if (c == EOL)
     768                 :            :             ;
     769         [ #  # ]:          0 :         else if (c == dialect->escapechar) {
     770                 :            :             /* Possible escape character */
     771                 :          0 :             self->state = ESCAPE_IN_QUOTED_FIELD;
     772                 :            :         }
     773         [ #  # ]:          0 :         else if (c == dialect->quotechar &&
     774         [ #  # ]:          0 :                  dialect->quoting != QUOTE_NONE) {
     775         [ #  # ]:          0 :             if (dialect->doublequote) {
     776                 :            :                 /* doublequote; " represented by "" */
     777                 :          0 :                 self->state = QUOTE_IN_QUOTED_FIELD;
     778                 :            :             }
     779                 :            :             else {
     780                 :            :                 /* end of quote part of field */
     781                 :          0 :                 self->state = IN_FIELD;
     782                 :            :             }
     783                 :            :         }
     784                 :            :         else {
     785                 :            :             /* normal character - save in field */
     786         [ #  # ]:          0 :             if (parse_add_char(self, module_state, c) < 0)
     787                 :          0 :                 return -1;
     788                 :            :         }
     789                 :          0 :         break;
     790                 :            : 
     791                 :          0 :     case ESCAPE_IN_QUOTED_FIELD:
     792         [ #  # ]:          0 :         if (c == EOL)
     793                 :          0 :             c = '\n';
     794         [ #  # ]:          0 :         if (parse_add_char(self, module_state, c) < 0)
     795                 :          0 :             return -1;
     796                 :          0 :         self->state = IN_QUOTED_FIELD;
     797                 :          0 :         break;
     798                 :            : 
     799                 :          0 :     case QUOTE_IN_QUOTED_FIELD:
     800                 :            :         /* doublequote - seen a quote in a quoted field */
     801         [ #  # ]:          0 :         if (dialect->quoting != QUOTE_NONE &&
     802         [ #  # ]:          0 :             c == dialect->quotechar) {
     803                 :            :             /* save "" as " */
     804         [ #  # ]:          0 :             if (parse_add_char(self, module_state, c) < 0)
     805                 :          0 :                 return -1;
     806                 :          0 :             self->state = IN_QUOTED_FIELD;
     807                 :            :         }
     808         [ #  # ]:          0 :         else if (c == dialect->delimiter) {
     809                 :            :             /* save field - wait for new field */
     810         [ #  # ]:          0 :             if (parse_save_field(self) < 0)
     811                 :          0 :                 return -1;
     812                 :          0 :             self->state = START_FIELD;
     813                 :            :         }
     814   [ #  #  #  #  :          0 :         else if (c == '\n' || c == '\r' || c == EOL) {
                   #  # ]
     815                 :            :             /* end of line - return [fields] */
     816         [ #  # ]:          0 :             if (parse_save_field(self) < 0)
     817                 :          0 :                 return -1;
     818         [ #  # ]:          0 :             self->state = (c == EOL ? START_RECORD : EAT_CRNL);
     819                 :            :         }
     820         [ #  # ]:          0 :         else if (!dialect->strict) {
     821         [ #  # ]:          0 :             if (parse_add_char(self, module_state, c) < 0)
     822                 :          0 :                 return -1;
     823                 :          0 :             self->state = IN_FIELD;
     824                 :            :         }
     825                 :            :         else {
     826                 :            :             /* illegal */
     827                 :          0 :             PyErr_Format(module_state->error_obj, "'%c' expected after '%c'",
     828                 :            :                             dialect->delimiter,
     829                 :            :                             dialect->quotechar);
     830                 :          0 :             return -1;
     831                 :            :         }
     832                 :          0 :         break;
     833                 :            : 
     834                 :          0 :     case EAT_CRNL:
     835   [ #  #  #  # ]:          0 :         if (c == '\n' || c == '\r')
     836                 :            :             ;
     837         [ #  # ]:          0 :         else if (c == EOL)
     838                 :          0 :             self->state = START_RECORD;
     839                 :            :         else {
     840                 :          0 :             PyErr_Format(module_state->error_obj,
     841                 :            :                          "new-line character seen in unquoted field - do you need to open the file in universal-newline mode?");
     842                 :          0 :             return -1;
     843                 :            :         }
     844                 :          0 :         break;
     845                 :            : 
     846                 :            :     }
     847                 :          0 :     return 0;
     848                 :            : }
     849                 :            : 
     850                 :            : static int
     851                 :          0 : parse_reset(ReaderObj *self)
     852                 :            : {
     853                 :          0 :     Py_XSETREF(self->fields, PyList_New(0));
     854         [ #  # ]:          0 :     if (self->fields == NULL)
     855                 :          0 :         return -1;
     856                 :          0 :     self->field_len = 0;
     857                 :          0 :     self->state = START_RECORD;
     858                 :          0 :     self->numeric_field = 0;
     859                 :          0 :     return 0;
     860                 :            : }
     861                 :            : 
     862                 :            : static PyObject *
     863                 :          0 : Reader_iternext(ReaderObj *self)
     864                 :            : {
     865                 :          0 :     PyObject *fields = NULL;
     866                 :            :     Py_UCS4 c;
     867                 :            :     Py_ssize_t pos, linelen;
     868                 :            :     int kind;
     869                 :            :     const void *data;
     870                 :            :     PyObject *lineobj;
     871                 :            : 
     872                 :          0 :     _csvstate *module_state = _csv_state_from_type(Py_TYPE(self),
     873                 :            :                                                    "Reader.__next__");
     874         [ #  # ]:          0 :     if (module_state == NULL) {
     875                 :          0 :         return NULL;
     876                 :            :     }
     877                 :            : 
     878         [ #  # ]:          0 :     if (parse_reset(self) < 0)
     879                 :          0 :         return NULL;
     880                 :            :     do {
     881                 :          0 :         lineobj = PyIter_Next(self->input_iter);
     882         [ #  # ]:          0 :         if (lineobj == NULL) {
     883                 :            :             /* End of input OR exception */
     884   [ #  #  #  # ]:          0 :             if (!PyErr_Occurred() && (self->field_len != 0 ||
     885         [ #  # ]:          0 :                                       self->state == IN_QUOTED_FIELD)) {
     886         [ #  # ]:          0 :                 if (self->dialect->strict)
     887                 :          0 :                     PyErr_SetString(module_state->error_obj,
     888                 :            :                                     "unexpected end of data");
     889         [ #  # ]:          0 :                 else if (parse_save_field(self) >= 0)
     890                 :          0 :                     break;
     891                 :            :             }
     892                 :          0 :             return NULL;
     893                 :            :         }
     894         [ #  # ]:          0 :         if (!PyUnicode_Check(lineobj)) {
     895                 :          0 :             PyErr_Format(module_state->error_obj,
     896                 :            :                          "iterator should return strings, "
     897                 :            :                          "not %.200s "
     898                 :            :                          "(the file should be opened in text mode)",
     899                 :          0 :                          Py_TYPE(lineobj)->tp_name
     900                 :            :                 );
     901                 :          0 :             Py_DECREF(lineobj);
     902                 :          0 :             return NULL;
     903                 :            :         }
     904         [ #  # ]:          0 :         if (PyUnicode_READY(lineobj) == -1) {
     905                 :          0 :             Py_DECREF(lineobj);
     906                 :          0 :             return NULL;
     907                 :            :         }
     908                 :          0 :         ++self->line_num;
     909                 :          0 :         kind = PyUnicode_KIND(lineobj);
     910                 :          0 :         data = PyUnicode_DATA(lineobj);
     911                 :          0 :         pos = 0;
     912                 :          0 :         linelen = PyUnicode_GET_LENGTH(lineobj);
     913         [ #  # ]:          0 :         while (linelen--) {
     914                 :          0 :             c = PyUnicode_READ(kind, data, pos);
     915         [ #  # ]:          0 :             if (parse_process_char(self, module_state, c) < 0) {
     916                 :          0 :                 Py_DECREF(lineobj);
     917                 :          0 :                 goto err;
     918                 :            :             }
     919                 :          0 :             pos++;
     920                 :            :         }
     921                 :          0 :         Py_DECREF(lineobj);
     922         [ #  # ]:          0 :         if (parse_process_char(self, module_state, EOL) < 0)
     923                 :          0 :             goto err;
     924         [ #  # ]:          0 :     } while (self->state != START_RECORD);
     925                 :            : 
     926                 :          0 :     fields = self->fields;
     927                 :          0 :     self->fields = NULL;
     928                 :          0 : err:
     929                 :          0 :     return fields;
     930                 :            : }
     931                 :            : 
     932                 :            : static void
     933                 :          0 : Reader_dealloc(ReaderObj *self)
     934                 :            : {
     935                 :          0 :     PyTypeObject *tp = Py_TYPE(self);
     936                 :          0 :     PyObject_GC_UnTrack(self);
     937                 :          0 :     tp->tp_clear((PyObject *)self);
     938         [ #  # ]:          0 :     if (self->field != NULL) {
     939                 :          0 :         PyMem_Free(self->field);
     940                 :          0 :         self->field = NULL;
     941                 :            :     }
     942                 :          0 :     PyObject_GC_Del(self);
     943                 :          0 :     Py_DECREF(tp);
     944                 :          0 : }
     945                 :            : 
     946                 :            : static int
     947                 :          0 : Reader_traverse(ReaderObj *self, visitproc visit, void *arg)
     948                 :            : {
     949   [ #  #  #  # ]:          0 :     Py_VISIT(self->dialect);
     950   [ #  #  #  # ]:          0 :     Py_VISIT(self->input_iter);
     951   [ #  #  #  # ]:          0 :     Py_VISIT(self->fields);
     952   [ #  #  #  # ]:          0 :     Py_VISIT(Py_TYPE(self));
     953                 :          0 :     return 0;
     954                 :            : }
     955                 :            : 
     956                 :            : static int
     957                 :          0 : Reader_clear(ReaderObj *self)
     958                 :            : {
     959         [ #  # ]:          0 :     Py_CLEAR(self->dialect);
     960         [ #  # ]:          0 :     Py_CLEAR(self->input_iter);
     961         [ #  # ]:          0 :     Py_CLEAR(self->fields);
     962                 :          0 :     return 0;
     963                 :            : }
     964                 :            : 
     965                 :            : PyDoc_STRVAR(Reader_Type_doc,
     966                 :            : "CSV reader\n"
     967                 :            : "\n"
     968                 :            : "Reader objects are responsible for reading and parsing tabular data\n"
     969                 :            : "in CSV format.\n"
     970                 :            : );
     971                 :            : 
     972                 :            : static struct PyMethodDef Reader_methods[] = {
     973                 :            :     { NULL, NULL }
     974                 :            : };
     975                 :            : #define R_OFF(x) offsetof(ReaderObj, x)
     976                 :            : 
     977                 :            : static struct PyMemberDef Reader_memberlist[] = {
     978                 :            :     { "dialect", T_OBJECT, R_OFF(dialect), READONLY },
     979                 :            :     { "line_num", T_ULONG, R_OFF(line_num), READONLY },
     980                 :            :     { NULL }
     981                 :            : };
     982                 :            : 
     983                 :            : 
     984                 :            : static PyType_Slot Reader_Type_slots[] = {
     985                 :            :     {Py_tp_doc, (char*)Reader_Type_doc},
     986                 :            :     {Py_tp_traverse, Reader_traverse},
     987                 :            :     {Py_tp_iter, PyObject_SelfIter},
     988                 :            :     {Py_tp_iternext, Reader_iternext},
     989                 :            :     {Py_tp_methods, Reader_methods},
     990                 :            :     {Py_tp_members, Reader_memberlist},
     991                 :            :     {Py_tp_clear, Reader_clear},
     992                 :            :     {Py_tp_dealloc, Reader_dealloc},
     993                 :            :     {0, NULL}
     994                 :            : };
     995                 :            : 
     996                 :            : PyType_Spec Reader_Type_spec = {
     997                 :            :     .name = "_csv.reader",
     998                 :            :     .basicsize = sizeof(ReaderObj),
     999                 :            :     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
    1000                 :            :               Py_TPFLAGS_IMMUTABLETYPE),
    1001                 :            :     .slots = Reader_Type_slots
    1002                 :            : };
    1003                 :            : 
    1004                 :            : 
    1005                 :            : static PyObject *
    1006                 :          0 : csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args)
    1007                 :            : {
    1008                 :          0 :     PyObject * iterator, * dialect = NULL;
    1009                 :          0 :     _csvstate *module_state = get_csv_state(module);
    1010                 :          0 :     ReaderObj * self = PyObject_GC_New(
    1011                 :            :         ReaderObj,
    1012                 :            :         module_state->reader_type);
    1013                 :            : 
    1014         [ #  # ]:          0 :     if (!self)
    1015                 :          0 :         return NULL;
    1016                 :            : 
    1017                 :          0 :     self->dialect = NULL;
    1018                 :          0 :     self->fields = NULL;
    1019                 :          0 :     self->input_iter = NULL;
    1020                 :          0 :     self->field = NULL;
    1021                 :          0 :     self->field_size = 0;
    1022                 :          0 :     self->line_num = 0;
    1023                 :            : 
    1024         [ #  # ]:          0 :     if (parse_reset(self) < 0) {
    1025                 :          0 :         Py_DECREF(self);
    1026                 :          0 :         return NULL;
    1027                 :            :     }
    1028                 :            : 
    1029         [ #  # ]:          0 :     if (!PyArg_UnpackTuple(args, "", 1, 2, &iterator, &dialect)) {
    1030                 :          0 :         Py_DECREF(self);
    1031                 :          0 :         return NULL;
    1032                 :            :     }
    1033                 :          0 :     self->input_iter = PyObject_GetIter(iterator);
    1034         [ #  # ]:          0 :     if (self->input_iter == NULL) {
    1035                 :          0 :         Py_DECREF(self);
    1036                 :          0 :         return NULL;
    1037                 :            :     }
    1038                 :          0 :     self->dialect = (DialectObj *)_call_dialect(module_state, dialect,
    1039                 :            :                                                 keyword_args);
    1040         [ #  # ]:          0 :     if (self->dialect == NULL) {
    1041                 :          0 :         Py_DECREF(self);
    1042                 :          0 :         return NULL;
    1043                 :            :     }
    1044                 :            : 
    1045                 :          0 :     PyObject_GC_Track(self);
    1046                 :          0 :     return (PyObject *)self;
    1047                 :            : }
    1048                 :            : 
    1049                 :            : /*
    1050                 :            :  * WRITER
    1051                 :            :  */
    1052                 :            : /* ---------------------------------------------------------------- */
    1053                 :            : static void
    1054                 :          0 : join_reset(WriterObj *self)
    1055                 :            : {
    1056                 :          0 :     self->rec_len = 0;
    1057                 :          0 :     self->num_fields = 0;
    1058                 :          0 : }
    1059                 :            : 
    1060                 :            : #define MEM_INCR 32768
    1061                 :            : 
    1062                 :            : /* Calculate new record length or append field to record.  Return new
    1063                 :            :  * record length.
    1064                 :            :  */
    1065                 :            : static Py_ssize_t
    1066                 :          0 : join_append_data(WriterObj *self, int field_kind, const void *field_data,
    1067                 :            :                  Py_ssize_t field_len, int *quoted,
    1068                 :            :                  int copy_phase)
    1069                 :            : {
    1070                 :          0 :     DialectObj *dialect = self->dialect;
    1071                 :            :     int i;
    1072                 :            :     Py_ssize_t rec_len;
    1073                 :            : 
    1074                 :            : #define INCLEN \
    1075                 :            :     do {\
    1076                 :            :         if (!copy_phase && rec_len == PY_SSIZE_T_MAX) {    \
    1077                 :            :             goto overflow; \
    1078                 :            :         } \
    1079                 :            :         rec_len++; \
    1080                 :            :     } while(0)
    1081                 :            : 
    1082                 :            : #define ADDCH(c)                                \
    1083                 :            :     do {\
    1084                 :            :         if (copy_phase) \
    1085                 :            :             self->rec[rec_len] = c;\
    1086                 :            :         INCLEN;\
    1087                 :            :     } while(0)
    1088                 :            : 
    1089                 :          0 :     rec_len = self->rec_len;
    1090                 :            : 
    1091                 :            :     /* If this is not the first field we need a field separator */
    1092         [ #  # ]:          0 :     if (self->num_fields > 0)
    1093   [ #  #  #  #  :          0 :         ADDCH(dialect->delimiter);
                   #  # ]
    1094                 :            : 
    1095                 :            :     /* Handle preceding quote */
    1096   [ #  #  #  # ]:          0 :     if (copy_phase && *quoted)
    1097   [ #  #  #  #  :          0 :         ADDCH(dialect->quotechar);
                   #  # ]
    1098                 :            : 
    1099                 :            :     /* Copy/count field data */
    1100                 :            :     /* If field is null just pass over */
    1101   [ #  #  #  # ]:          0 :     for (i = 0; field_data && (i < field_len); i++) {
    1102                 :          0 :         Py_UCS4 c = PyUnicode_READ(field_kind, field_data, i);
    1103                 :          0 :         int want_escape = 0;
    1104                 :            : 
    1105         [ #  # ]:          0 :         if (c == dialect->delimiter ||
    1106         [ #  # ]:          0 :             c == dialect->escapechar ||
    1107   [ #  #  #  # ]:          0 :             c == dialect->quotechar  ||
    1108                 :          0 :             PyUnicode_FindChar(
    1109                 :            :                 dialect->lineterminator, c, 0,
    1110                 :            :                 PyUnicode_GET_LENGTH(dialect->lineterminator), 1) >= 0) {
    1111         [ #  # ]:          0 :             if (dialect->quoting == QUOTE_NONE)
    1112                 :          0 :                 want_escape = 1;
    1113                 :            :             else {
    1114         [ #  # ]:          0 :                 if (c == dialect->quotechar) {
    1115         [ #  # ]:          0 :                     if (dialect->doublequote)
    1116   [ #  #  #  #  :          0 :                         ADDCH(dialect->quotechar);
                   #  # ]
    1117                 :            :                     else
    1118                 :          0 :                         want_escape = 1;
    1119                 :            :                 }
    1120         [ #  # ]:          0 :                 else if (c == dialect->escapechar) {
    1121                 :          0 :                     want_escape = 1;
    1122                 :            :                 }
    1123         [ #  # ]:          0 :                 if (!want_escape)
    1124                 :          0 :                     *quoted = 1;
    1125                 :            :             }
    1126         [ #  # ]:          0 :             if (want_escape) {
    1127         [ #  # ]:          0 :                 if (dialect->escapechar == NOT_SET) {
    1128                 :          0 :                     PyErr_Format(self->error_obj,
    1129                 :            :                                  "need to escape, but no escapechar set");
    1130                 :          0 :                     return -1;
    1131                 :            :                 }
    1132   [ #  #  #  #  :          0 :                 ADDCH(dialect->escapechar);
                   #  # ]
    1133                 :            :             }
    1134                 :            :         }
    1135                 :            :         /* Copy field character into record buffer.
    1136                 :            :          */
    1137   [ #  #  #  #  :          0 :         ADDCH(c);
                   #  # ]
    1138                 :            :     }
    1139                 :            : 
    1140         [ #  # ]:          0 :     if (*quoted) {
    1141         [ #  # ]:          0 :         if (copy_phase)
    1142   [ #  #  #  #  :          0 :             ADDCH(dialect->quotechar);
                   #  # ]
    1143                 :            :         else {
    1144   [ #  #  #  # ]:          0 :             INCLEN; /* starting quote */
    1145   [ #  #  #  # ]:          0 :             INCLEN; /* ending quote */
    1146                 :            :         }
    1147                 :            :     }
    1148                 :          0 :     return rec_len;
    1149                 :            : 
    1150                 :          0 :   overflow:
    1151                 :          0 :     PyErr_NoMemory();
    1152                 :          0 :     return -1;
    1153                 :            : #undef ADDCH
    1154                 :            : #undef INCLEN
    1155                 :            : }
    1156                 :            : 
    1157                 :            : static int
    1158                 :          0 : join_check_rec_size(WriterObj *self, Py_ssize_t rec_len)
    1159                 :            : {
    1160                 :            :     assert(rec_len >= 0);
    1161                 :            : 
    1162         [ #  # ]:          0 :     if (rec_len > self->rec_size) {
    1163                 :          0 :         size_t rec_size_new = (size_t)(rec_len / MEM_INCR + 1) * MEM_INCR;
    1164                 :          0 :         Py_UCS4 *rec_new = self->rec;
    1165         [ #  # ]:          0 :         PyMem_Resize(rec_new, Py_UCS4, rec_size_new);
    1166         [ #  # ]:          0 :         if (rec_new == NULL) {
    1167                 :          0 :             PyErr_NoMemory();
    1168                 :          0 :             return 0;
    1169                 :            :         }
    1170                 :          0 :         self->rec = rec_new;
    1171                 :          0 :         self->rec_size = (Py_ssize_t)rec_size_new;
    1172                 :            :     }
    1173                 :          0 :     return 1;
    1174                 :            : }
    1175                 :            : 
    1176                 :            : static int
    1177                 :          0 : join_append(WriterObj *self, PyObject *field, int quoted)
    1178                 :            : {
    1179                 :          0 :     int field_kind = -1;
    1180                 :          0 :     const void *field_data = NULL;
    1181                 :          0 :     Py_ssize_t field_len = 0;
    1182                 :            :     Py_ssize_t rec_len;
    1183                 :            : 
    1184         [ #  # ]:          0 :     if (field != NULL) {
    1185         [ #  # ]:          0 :         if (PyUnicode_READY(field) == -1)
    1186                 :          0 :             return 0;
    1187                 :          0 :         field_kind = PyUnicode_KIND(field);
    1188                 :          0 :         field_data = PyUnicode_DATA(field);
    1189                 :          0 :         field_len = PyUnicode_GET_LENGTH(field);
    1190                 :            :     }
    1191                 :          0 :     rec_len = join_append_data(self, field_kind, field_data, field_len,
    1192                 :            :                                &quoted, 0);
    1193         [ #  # ]:          0 :     if (rec_len < 0)
    1194                 :          0 :         return 0;
    1195                 :            : 
    1196                 :            :     /* grow record buffer if necessary */
    1197         [ #  # ]:          0 :     if (!join_check_rec_size(self, rec_len))
    1198                 :          0 :         return 0;
    1199                 :            : 
    1200                 :          0 :     self->rec_len = join_append_data(self, field_kind, field_data, field_len,
    1201                 :            :                                      &quoted, 1);
    1202                 :          0 :     self->num_fields++;
    1203                 :            : 
    1204                 :          0 :     return 1;
    1205                 :            : }
    1206                 :            : 
    1207                 :            : static int
    1208                 :          0 : join_append_lineterminator(WriterObj *self)
    1209                 :            : {
    1210                 :            :     Py_ssize_t terminator_len, i;
    1211                 :            :     int term_kind;
    1212                 :            :     const void *term_data;
    1213                 :            : 
    1214                 :          0 :     terminator_len = PyUnicode_GET_LENGTH(self->dialect->lineterminator);
    1215         [ #  # ]:          0 :     if (terminator_len == -1)
    1216                 :          0 :         return 0;
    1217                 :            : 
    1218                 :            :     /* grow record buffer if necessary */
    1219         [ #  # ]:          0 :     if (!join_check_rec_size(self, self->rec_len + terminator_len))
    1220                 :          0 :         return 0;
    1221                 :            : 
    1222                 :          0 :     term_kind = PyUnicode_KIND(self->dialect->lineterminator);
    1223                 :          0 :     term_data = PyUnicode_DATA(self->dialect->lineterminator);
    1224         [ #  # ]:          0 :     for (i = 0; i < terminator_len; i++)
    1225                 :          0 :         self->rec[self->rec_len + i] = PyUnicode_READ(term_kind, term_data, i);
    1226                 :          0 :     self->rec_len += terminator_len;
    1227                 :            : 
    1228                 :          0 :     return 1;
    1229                 :            : }
    1230                 :            : 
    1231                 :            : PyDoc_STRVAR(csv_writerow_doc,
    1232                 :            : "writerow(iterable)\n"
    1233                 :            : "\n"
    1234                 :            : "Construct and write a CSV record from an iterable of fields.  Non-string\n"
    1235                 :            : "elements will be converted to string.");
    1236                 :            : 
    1237                 :            : static PyObject *
    1238                 :          0 : csv_writerow(WriterObj *self, PyObject *seq)
    1239                 :            : {
    1240                 :          0 :     DialectObj *dialect = self->dialect;
    1241                 :            :     PyObject *iter, *field, *line, *result;
    1242                 :            : 
    1243                 :          0 :     iter = PyObject_GetIter(seq);
    1244         [ #  # ]:          0 :     if (iter == NULL) {
    1245         [ #  # ]:          0 :         if (PyErr_ExceptionMatches(PyExc_TypeError)) {
    1246                 :          0 :             PyErr_Format(self->error_obj,
    1247                 :            :                          "iterable expected, not %.200s",
    1248                 :          0 :                          Py_TYPE(seq)->tp_name);
    1249                 :            :         }
    1250                 :          0 :         return NULL;
    1251                 :            :     }
    1252                 :            : 
    1253                 :            :     /* Join all fields in internal buffer.
    1254                 :            :      */
    1255                 :          0 :     join_reset(self);
    1256         [ #  # ]:          0 :     while ((field = PyIter_Next(iter))) {
    1257                 :            :         int append_ok;
    1258                 :            :         int quoted;
    1259                 :            : 
    1260      [ #  #  # ]:          0 :         switch (dialect->quoting) {
    1261                 :          0 :         case QUOTE_NONNUMERIC:
    1262                 :          0 :             quoted = !PyNumber_Check(field);
    1263                 :          0 :             break;
    1264                 :          0 :         case QUOTE_ALL:
    1265                 :          0 :             quoted = 1;
    1266                 :          0 :             break;
    1267                 :          0 :         default:
    1268                 :          0 :             quoted = 0;
    1269                 :          0 :             break;
    1270                 :            :         }
    1271                 :            : 
    1272         [ #  # ]:          0 :         if (PyUnicode_Check(field)) {
    1273                 :          0 :             append_ok = join_append(self, field, quoted);
    1274                 :          0 :             Py_DECREF(field);
    1275                 :            :         }
    1276         [ #  # ]:          0 :         else if (field == Py_None) {
    1277                 :          0 :             append_ok = join_append(self, NULL, quoted);
    1278                 :          0 :             Py_DECREF(field);
    1279                 :            :         }
    1280                 :            :         else {
    1281                 :            :             PyObject *str;
    1282                 :            : 
    1283                 :          0 :             str = PyObject_Str(field);
    1284                 :          0 :             Py_DECREF(field);
    1285         [ #  # ]:          0 :             if (str == NULL) {
    1286                 :          0 :                 Py_DECREF(iter);
    1287                 :          0 :                 return NULL;
    1288                 :            :             }
    1289                 :          0 :             append_ok = join_append(self, str, quoted);
    1290                 :          0 :             Py_DECREF(str);
    1291                 :            :         }
    1292         [ #  # ]:          0 :         if (!append_ok) {
    1293                 :          0 :             Py_DECREF(iter);
    1294                 :          0 :             return NULL;
    1295                 :            :         }
    1296                 :            :     }
    1297                 :          0 :     Py_DECREF(iter);
    1298         [ #  # ]:          0 :     if (PyErr_Occurred())
    1299                 :          0 :         return NULL;
    1300                 :            : 
    1301   [ #  #  #  # ]:          0 :     if (self->num_fields > 0 && self->rec_len == 0) {
    1302         [ #  # ]:          0 :         if (dialect->quoting == QUOTE_NONE) {
    1303                 :          0 :             PyErr_Format(self->error_obj,
    1304                 :            :                 "single empty field record must be quoted");
    1305                 :          0 :             return NULL;
    1306                 :            :         }
    1307                 :          0 :         self->num_fields--;
    1308         [ #  # ]:          0 :         if (!join_append(self, NULL, 1))
    1309                 :          0 :             return NULL;
    1310                 :            :     }
    1311                 :            : 
    1312                 :            :     /* Add line terminator.
    1313                 :            :      */
    1314         [ #  # ]:          0 :     if (!join_append_lineterminator(self)) {
    1315                 :          0 :         return NULL;
    1316                 :            :     }
    1317                 :            : 
    1318                 :          0 :     line = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
    1319                 :          0 :                                      (void *) self->rec, self->rec_len);
    1320         [ #  # ]:          0 :     if (line == NULL) {
    1321                 :          0 :         return NULL;
    1322                 :            :     }
    1323                 :          0 :     result = PyObject_CallOneArg(self->write, line);
    1324                 :          0 :     Py_DECREF(line);
    1325                 :          0 :     return result;
    1326                 :            : }
    1327                 :            : 
    1328                 :            : PyDoc_STRVAR(csv_writerows_doc,
    1329                 :            : "writerows(iterable of iterables)\n"
    1330                 :            : "\n"
    1331                 :            : "Construct and write a series of iterables to a csv file.  Non-string\n"
    1332                 :            : "elements will be converted to string.");
    1333                 :            : 
    1334                 :            : static PyObject *
    1335                 :          0 : csv_writerows(WriterObj *self, PyObject *seqseq)
    1336                 :            : {
    1337                 :            :     PyObject *row_iter, *row_obj, *result;
    1338                 :            : 
    1339                 :          0 :     row_iter = PyObject_GetIter(seqseq);
    1340         [ #  # ]:          0 :     if (row_iter == NULL) {
    1341                 :          0 :         return NULL;
    1342                 :            :     }
    1343         [ #  # ]:          0 :     while ((row_obj = PyIter_Next(row_iter))) {
    1344                 :          0 :         result = csv_writerow(self, row_obj);
    1345                 :          0 :         Py_DECREF(row_obj);
    1346         [ #  # ]:          0 :         if (!result) {
    1347                 :          0 :             Py_DECREF(row_iter);
    1348                 :          0 :             return NULL;
    1349                 :            :         }
    1350                 :            :         else
    1351                 :          0 :              Py_DECREF(result);
    1352                 :            :     }
    1353                 :          0 :     Py_DECREF(row_iter);
    1354         [ #  # ]:          0 :     if (PyErr_Occurred())
    1355                 :          0 :         return NULL;
    1356                 :          0 :     Py_RETURN_NONE;
    1357                 :            : }
    1358                 :            : 
    1359                 :            : static struct PyMethodDef Writer_methods[] = {
    1360                 :            :     { "writerow", (PyCFunction)csv_writerow, METH_O, csv_writerow_doc},
    1361                 :            :     { "writerows", (PyCFunction)csv_writerows, METH_O, csv_writerows_doc},
    1362                 :            :     { NULL, NULL }
    1363                 :            : };
    1364                 :            : 
    1365                 :            : #define W_OFF(x) offsetof(WriterObj, x)
    1366                 :            : 
    1367                 :            : static struct PyMemberDef Writer_memberlist[] = {
    1368                 :            :     { "dialect", T_OBJECT, W_OFF(dialect), READONLY },
    1369                 :            :     { NULL }
    1370                 :            : };
    1371                 :            : 
    1372                 :            : static int
    1373                 :          0 : Writer_traverse(WriterObj *self, visitproc visit, void *arg)
    1374                 :            : {
    1375   [ #  #  #  # ]:          0 :     Py_VISIT(self->dialect);
    1376   [ #  #  #  # ]:          0 :     Py_VISIT(self->write);
    1377   [ #  #  #  # ]:          0 :     Py_VISIT(self->error_obj);
    1378   [ #  #  #  # ]:          0 :     Py_VISIT(Py_TYPE(self));
    1379                 :          0 :     return 0;
    1380                 :            : }
    1381                 :            : 
    1382                 :            : static int
    1383                 :          0 : Writer_clear(WriterObj *self)
    1384                 :            : {
    1385         [ #  # ]:          0 :     Py_CLEAR(self->dialect);
    1386         [ #  # ]:          0 :     Py_CLEAR(self->write);
    1387         [ #  # ]:          0 :     Py_CLEAR(self->error_obj);
    1388                 :          0 :     return 0;
    1389                 :            : }
    1390                 :            : 
    1391                 :            : static void
    1392                 :          0 : Writer_dealloc(WriterObj *self)
    1393                 :            : {
    1394                 :          0 :     PyTypeObject *tp = Py_TYPE(self);
    1395                 :          0 :     PyObject_GC_UnTrack(self);
    1396                 :          0 :     tp->tp_clear((PyObject *)self);
    1397         [ #  # ]:          0 :     if (self->rec != NULL) {
    1398                 :          0 :         PyMem_Free(self->rec);
    1399                 :            :     }
    1400                 :          0 :     PyObject_GC_Del(self);
    1401                 :          0 :     Py_DECREF(tp);
    1402                 :          0 : }
    1403                 :            : 
    1404                 :            : PyDoc_STRVAR(Writer_Type_doc,
    1405                 :            : "CSV writer\n"
    1406                 :            : "\n"
    1407                 :            : "Writer objects are responsible for generating tabular data\n"
    1408                 :            : "in CSV format from sequence input.\n"
    1409                 :            : );
    1410                 :            : 
    1411                 :            : static PyType_Slot Writer_Type_slots[] = {
    1412                 :            :     {Py_tp_doc, (char*)Writer_Type_doc},
    1413                 :            :     {Py_tp_traverse, Writer_traverse},
    1414                 :            :     {Py_tp_clear, Writer_clear},
    1415                 :            :     {Py_tp_dealloc, Writer_dealloc},
    1416                 :            :     {Py_tp_methods, Writer_methods},
    1417                 :            :     {Py_tp_members, Writer_memberlist},
    1418                 :            :     {0, NULL}
    1419                 :            : };
    1420                 :            : 
    1421                 :            : PyType_Spec Writer_Type_spec = {
    1422                 :            :     .name = "_csv.writer",
    1423                 :            :     .basicsize = sizeof(WriterObj),
    1424                 :            :     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
    1425                 :            :               Py_TPFLAGS_IMMUTABLETYPE),
    1426                 :            :     .slots = Writer_Type_slots,
    1427                 :            : };
    1428                 :            : 
    1429                 :            : 
    1430                 :            : static PyObject *
    1431                 :          0 : csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args)
    1432                 :            : {
    1433                 :          0 :     PyObject * output_file, * dialect = NULL;
    1434                 :          0 :     _csvstate *module_state = get_csv_state(module);
    1435                 :          0 :     WriterObj * self = PyObject_GC_New(WriterObj, module_state->writer_type);
    1436                 :            : 
    1437         [ #  # ]:          0 :     if (!self)
    1438                 :          0 :         return NULL;
    1439                 :            : 
    1440                 :          0 :     self->dialect = NULL;
    1441                 :          0 :     self->write = NULL;
    1442                 :            : 
    1443                 :          0 :     self->rec = NULL;
    1444                 :          0 :     self->rec_size = 0;
    1445                 :          0 :     self->rec_len = 0;
    1446                 :          0 :     self->num_fields = 0;
    1447                 :            : 
    1448                 :          0 :     self->error_obj = Py_NewRef(module_state->error_obj);
    1449                 :            : 
    1450         [ #  # ]:          0 :     if (!PyArg_UnpackTuple(args, "", 1, 2, &output_file, &dialect)) {
    1451                 :          0 :         Py_DECREF(self);
    1452                 :          0 :         return NULL;
    1453                 :            :     }
    1454         [ #  # ]:          0 :     if (_PyObject_LookupAttr(output_file,
    1455                 :            :                              module_state->str_write,
    1456                 :            :                              &self->write) < 0) {
    1457                 :          0 :         Py_DECREF(self);
    1458                 :          0 :         return NULL;
    1459                 :            :     }
    1460   [ #  #  #  # ]:          0 :     if (self->write == NULL || !PyCallable_Check(self->write)) {
    1461                 :          0 :         PyErr_SetString(PyExc_TypeError,
    1462                 :            :                         "argument 1 must have a \"write\" method");
    1463                 :          0 :         Py_DECREF(self);
    1464                 :          0 :         return NULL;
    1465                 :            :     }
    1466                 :          0 :     self->dialect = (DialectObj *)_call_dialect(module_state, dialect,
    1467                 :            :                                                 keyword_args);
    1468         [ #  # ]:          0 :     if (self->dialect == NULL) {
    1469                 :          0 :         Py_DECREF(self);
    1470                 :          0 :         return NULL;
    1471                 :            :     }
    1472                 :          0 :     PyObject_GC_Track(self);
    1473                 :          0 :     return (PyObject *)self;
    1474                 :            : }
    1475                 :            : 
    1476                 :            : /*
    1477                 :            :  * DIALECT REGISTRY
    1478                 :            :  */
    1479                 :            : 
    1480                 :            : /*[clinic input]
    1481                 :            : _csv.list_dialects
    1482                 :            : 
    1483                 :            : Return a list of all known dialect names.
    1484                 :            : 
    1485                 :            :     names = csv.list_dialects()
    1486                 :            : [clinic start generated code]*/
    1487                 :            : 
    1488                 :            : static PyObject *
    1489                 :          0 : _csv_list_dialects_impl(PyObject *module)
    1490                 :            : /*[clinic end generated code: output=a5b92b215b006a6d input=8953943eb17d98ab]*/
    1491                 :            : {
    1492                 :          0 :     return PyDict_Keys(get_csv_state(module)->dialects);
    1493                 :            : }
    1494                 :            : 
    1495                 :            : static PyObject *
    1496                 :          0 : csv_register_dialect(PyObject *module, PyObject *args, PyObject *kwargs)
    1497                 :            : {
    1498                 :          0 :     PyObject *name_obj, *dialect_obj = NULL;
    1499                 :          0 :     _csvstate *module_state = get_csv_state(module);
    1500                 :            :     PyObject *dialect;
    1501                 :            : 
    1502         [ #  # ]:          0 :     if (!PyArg_UnpackTuple(args, "", 1, 2, &name_obj, &dialect_obj))
    1503                 :          0 :         return NULL;
    1504         [ #  # ]:          0 :     if (!PyUnicode_Check(name_obj)) {
    1505                 :          0 :         PyErr_SetString(PyExc_TypeError,
    1506                 :            :                         "dialect name must be a string");
    1507                 :          0 :         return NULL;
    1508                 :            :     }
    1509         [ #  # ]:          0 :     if (PyUnicode_READY(name_obj) == -1)
    1510                 :          0 :         return NULL;
    1511                 :          0 :     dialect = _call_dialect(module_state, dialect_obj, kwargs);
    1512         [ #  # ]:          0 :     if (dialect == NULL)
    1513                 :          0 :         return NULL;
    1514         [ #  # ]:          0 :     if (PyDict_SetItem(module_state->dialects, name_obj, dialect) < 0) {
    1515                 :          0 :         Py_DECREF(dialect);
    1516                 :          0 :         return NULL;
    1517                 :            :     }
    1518                 :          0 :     Py_DECREF(dialect);
    1519                 :          0 :     Py_RETURN_NONE;
    1520                 :            : }
    1521                 :            : 
    1522                 :            : 
    1523                 :            : /*[clinic input]
    1524                 :            : _csv.unregister_dialect
    1525                 :            : 
    1526                 :            :     name: object
    1527                 :            : 
    1528                 :            : Delete the name/dialect mapping associated with a string name.
    1529                 :            : 
    1530                 :            :     csv.unregister_dialect(name)
    1531                 :            : [clinic start generated code]*/
    1532                 :            : 
    1533                 :            : static PyObject *
    1534                 :          0 : _csv_unregister_dialect_impl(PyObject *module, PyObject *name)
    1535                 :            : /*[clinic end generated code: output=0813ebca6c058df4 input=6b5c1557bf60c7e7]*/
    1536                 :            : {
    1537                 :          0 :     _csvstate *module_state = get_csv_state(module);
    1538         [ #  # ]:          0 :     if (PyDict_DelItem(module_state->dialects, name) < 0) {
    1539         [ #  # ]:          0 :         if (PyErr_ExceptionMatches(PyExc_KeyError)) {
    1540                 :          0 :             PyErr_Format(module_state->error_obj, "unknown dialect");
    1541                 :            :         }
    1542                 :          0 :         return NULL;
    1543                 :            :     }
    1544                 :          0 :     Py_RETURN_NONE;
    1545                 :            : }
    1546                 :            : 
    1547                 :            : /*[clinic input]
    1548                 :            : _csv.get_dialect
    1549                 :            : 
    1550                 :            :     name: object
    1551                 :            : 
    1552                 :            : Return the dialect instance associated with name.
    1553                 :            : 
    1554                 :            :     dialect = csv.get_dialect(name)
    1555                 :            : [clinic start generated code]*/
    1556                 :            : 
    1557                 :            : static PyObject *
    1558                 :          0 : _csv_get_dialect_impl(PyObject *module, PyObject *name)
    1559                 :            : /*[clinic end generated code: output=aa988cd573bebebb input=edf9ddab32e448fb]*/
    1560                 :            : {
    1561                 :          0 :     return get_dialect_from_registry(name, get_csv_state(module));
    1562                 :            : }
    1563                 :            : 
    1564                 :            : /*[clinic input]
    1565                 :            : _csv.field_size_limit
    1566                 :            : 
    1567                 :            :     new_limit: object = NULL
    1568                 :            : 
    1569                 :            : Sets an upper limit on parsed fields.
    1570                 :            : 
    1571                 :            :     csv.field_size_limit([limit])
    1572                 :            : 
    1573                 :            : Returns old limit. If limit is not given, no new limit is set and
    1574                 :            : the old limit is returned
    1575                 :            : [clinic start generated code]*/
    1576                 :            : 
    1577                 :            : static PyObject *
    1578                 :          0 : _csv_field_size_limit_impl(PyObject *module, PyObject *new_limit)
    1579                 :            : /*[clinic end generated code: output=f2799ecd908e250b input=cec70e9226406435]*/
    1580                 :            : {
    1581                 :          0 :     _csvstate *module_state = get_csv_state(module);
    1582                 :          0 :     long old_limit = module_state->field_limit;
    1583         [ #  # ]:          0 :     if (new_limit != NULL) {
    1584         [ #  # ]:          0 :         if (!PyLong_CheckExact(new_limit)) {
    1585                 :          0 :             PyErr_Format(PyExc_TypeError,
    1586                 :            :                          "limit must be an integer");
    1587                 :          0 :             return NULL;
    1588                 :            :         }
    1589                 :          0 :         module_state->field_limit = PyLong_AsLong(new_limit);
    1590   [ #  #  #  # ]:          0 :         if (module_state->field_limit == -1 && PyErr_Occurred()) {
    1591                 :          0 :             module_state->field_limit = old_limit;
    1592                 :          0 :             return NULL;
    1593                 :            :         }
    1594                 :            :     }
    1595                 :          0 :     return PyLong_FromLong(old_limit);
    1596                 :            : }
    1597                 :            : 
    1598                 :            : static PyType_Slot error_slots[] = {
    1599                 :            :     {0, NULL},
    1600                 :            : };
    1601                 :            : 
    1602                 :            : PyType_Spec error_spec = {
    1603                 :            :     .name = "_csv.Error",
    1604                 :            :     .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    1605                 :            :     .slots = error_slots,
    1606                 :            : };
    1607                 :            : 
    1608                 :            : /*
    1609                 :            :  * MODULE
    1610                 :            :  */
    1611                 :            : 
    1612                 :            : PyDoc_STRVAR(csv_module_doc,
    1613                 :            : "CSV parsing and writing.\n"
    1614                 :            : "\n"
    1615                 :            : "This module provides classes that assist in the reading and writing\n"
    1616                 :            : "of Comma Separated Value (CSV) files, and implements the interface\n"
    1617                 :            : "described by PEP 305.  Although many CSV files are simple to parse,\n"
    1618                 :            : "the format is not formally defined by a stable specification and\n"
    1619                 :            : "is subtle enough that parsing lines of a CSV file with something\n"
    1620                 :            : "like line.split(\",\") is bound to fail.  The module supports three\n"
    1621                 :            : "basic APIs: reading, writing, and registration of dialects.\n"
    1622                 :            : "\n"
    1623                 :            : "\n"
    1624                 :            : "DIALECT REGISTRATION:\n"
    1625                 :            : "\n"
    1626                 :            : "Readers and writers support a dialect argument, which is a convenient\n"
    1627                 :            : "handle on a group of settings.  When the dialect argument is a string,\n"
    1628                 :            : "it identifies one of the dialects previously registered with the module.\n"
    1629                 :            : "If it is a class or instance, the attributes of the argument are used as\n"
    1630                 :            : "the settings for the reader or writer:\n"
    1631                 :            : "\n"
    1632                 :            : "    class excel:\n"
    1633                 :            : "        delimiter = ','\n"
    1634                 :            : "        quotechar = '\"'\n"
    1635                 :            : "        escapechar = None\n"
    1636                 :            : "        doublequote = True\n"
    1637                 :            : "        skipinitialspace = False\n"
    1638                 :            : "        lineterminator = '\\r\\n'\n"
    1639                 :            : "        quoting = QUOTE_MINIMAL\n"
    1640                 :            : "\n"
    1641                 :            : "SETTINGS:\n"
    1642                 :            : "\n"
    1643                 :            : "    * quotechar - specifies a one-character string to use as the\n"
    1644                 :            : "        quoting character.  It defaults to '\"'.\n"
    1645                 :            : "    * delimiter - specifies a one-character string to use as the\n"
    1646                 :            : "        field separator.  It defaults to ','.\n"
    1647                 :            : "    * skipinitialspace - specifies how to interpret spaces which\n"
    1648                 :            : "        immediately follow a delimiter.  It defaults to False, which\n"
    1649                 :            : "        means that spaces immediately following a delimiter is part\n"
    1650                 :            : "        of the following field.\n"
    1651                 :            : "    * lineterminator -  specifies the character sequence which should\n"
    1652                 :            : "        terminate rows.\n"
    1653                 :            : "    * quoting - controls when quotes should be generated by the writer.\n"
    1654                 :            : "        It can take on any of the following module constants:\n"
    1655                 :            : "\n"
    1656                 :            : "        csv.QUOTE_MINIMAL means only when required, for example, when a\n"
    1657                 :            : "            field contains either the quotechar or the delimiter\n"
    1658                 :            : "        csv.QUOTE_ALL means that quotes are always placed around fields.\n"
    1659                 :            : "        csv.QUOTE_NONNUMERIC means that quotes are always placed around\n"
    1660                 :            : "            fields which do not parse as integers or floating point\n"
    1661                 :            : "            numbers.\n"
    1662                 :            : "        csv.QUOTE_NONE means that quotes are never placed around fields.\n"
    1663                 :            : "    * escapechar - specifies a one-character string used to escape\n"
    1664                 :            : "        the delimiter when quoting is set to QUOTE_NONE.\n"
    1665                 :            : "    * doublequote - controls the handling of quotes inside fields.  When\n"
    1666                 :            : "        True, two consecutive quotes are interpreted as one during read,\n"
    1667                 :            : "        and when writing, each quote character embedded in the data is\n"
    1668                 :            : "        written as two quotes\n");
    1669                 :            : 
    1670                 :            : PyDoc_STRVAR(csv_reader_doc,
    1671                 :            : "    csv_reader = reader(iterable [, dialect='excel']\n"
    1672                 :            : "                        [optional keyword args])\n"
    1673                 :            : "    for row in csv_reader:\n"
    1674                 :            : "        process(row)\n"
    1675                 :            : "\n"
    1676                 :            : "The \"iterable\" argument can be any object that returns a line\n"
    1677                 :            : "of input for each iteration, such as a file object or a list.  The\n"
    1678                 :            : "optional \"dialect\" parameter is discussed below.  The function\n"
    1679                 :            : "also accepts optional keyword arguments which override settings\n"
    1680                 :            : "provided by the dialect.\n"
    1681                 :            : "\n"
    1682                 :            : "The returned object is an iterator.  Each iteration returns a row\n"
    1683                 :            : "of the CSV file (which can span multiple input lines).\n");
    1684                 :            : 
    1685                 :            : PyDoc_STRVAR(csv_writer_doc,
    1686                 :            : "    csv_writer = csv.writer(fileobj [, dialect='excel']\n"
    1687                 :            : "                            [optional keyword args])\n"
    1688                 :            : "    for row in sequence:\n"
    1689                 :            : "        csv_writer.writerow(row)\n"
    1690                 :            : "\n"
    1691                 :            : "    [or]\n"
    1692                 :            : "\n"
    1693                 :            : "    csv_writer = csv.writer(fileobj [, dialect='excel']\n"
    1694                 :            : "                            [optional keyword args])\n"
    1695                 :            : "    csv_writer.writerows(rows)\n"
    1696                 :            : "\n"
    1697                 :            : "The \"fileobj\" argument can be any object that supports the file API.\n");
    1698                 :            : 
    1699                 :            : PyDoc_STRVAR(csv_register_dialect_doc,
    1700                 :            : "Create a mapping from a string name to a dialect class.\n"
    1701                 :            : "    dialect = csv.register_dialect(name[, dialect[, **fmtparams]])");
    1702                 :            : 
    1703                 :            : static struct PyMethodDef csv_methods[] = {
    1704                 :            :     { "reader", _PyCFunction_CAST(csv_reader),
    1705                 :            :         METH_VARARGS | METH_KEYWORDS, csv_reader_doc},
    1706                 :            :     { "writer", _PyCFunction_CAST(csv_writer),
    1707                 :            :         METH_VARARGS | METH_KEYWORDS, csv_writer_doc},
    1708                 :            :     { "register_dialect", _PyCFunction_CAST(csv_register_dialect),
    1709                 :            :         METH_VARARGS | METH_KEYWORDS, csv_register_dialect_doc},
    1710                 :            :     _CSV_LIST_DIALECTS_METHODDEF
    1711                 :            :     _CSV_UNREGISTER_DIALECT_METHODDEF
    1712                 :            :     _CSV_GET_DIALECT_METHODDEF
    1713                 :            :     _CSV_FIELD_SIZE_LIMIT_METHODDEF
    1714                 :            :     { NULL, NULL }
    1715                 :            : };
    1716                 :            : 
    1717                 :            : static int
    1718                 :          1 : csv_exec(PyObject *module) {
    1719                 :            :     const StyleDesc *style;
    1720                 :            :     PyObject *temp;
    1721                 :          1 :     _csvstate *module_state = get_csv_state(module);
    1722                 :            : 
    1723                 :          1 :     temp = PyType_FromModuleAndSpec(module, &Dialect_Type_spec, NULL);
    1724                 :          1 :     module_state->dialect_type = (PyTypeObject *)temp;
    1725         [ -  + ]:          1 :     if (PyModule_AddObjectRef(module, "Dialect", temp) < 0) {
    1726                 :          0 :         return -1;
    1727                 :            :     }
    1728                 :            : 
    1729                 :          1 :     temp = PyType_FromModuleAndSpec(module, &Reader_Type_spec, NULL);
    1730                 :          1 :     module_state->reader_type = (PyTypeObject *)temp;
    1731         [ -  + ]:          1 :     if (PyModule_AddObjectRef(module, "Reader", temp) < 0) {
    1732                 :          0 :         return -1;
    1733                 :            :     }
    1734                 :            : 
    1735                 :          1 :     temp = PyType_FromModuleAndSpec(module, &Writer_Type_spec, NULL);
    1736                 :          1 :     module_state->writer_type = (PyTypeObject *)temp;
    1737         [ -  + ]:          1 :     if (PyModule_AddObjectRef(module, "Writer", temp) < 0) {
    1738                 :          0 :         return -1;
    1739                 :            :     }
    1740                 :            : 
    1741                 :            :     /* Add version to the module. */
    1742         [ -  + ]:          1 :     if (PyModule_AddStringConstant(module, "__version__",
    1743                 :            :                                    MODULE_VERSION) == -1) {
    1744                 :          0 :         return -1;
    1745                 :            :     }
    1746                 :            : 
    1747                 :            :     /* Set the field limit */
    1748                 :          1 :     module_state->field_limit = 128 * 1024;
    1749                 :            : 
    1750                 :            :     /* Add _dialects dictionary */
    1751                 :          1 :     module_state->dialects = PyDict_New();
    1752         [ -  + ]:          1 :     if (PyModule_AddObjectRef(module, "_dialects", module_state->dialects) < 0) {
    1753                 :          0 :         return -1;
    1754                 :            :     }
    1755                 :            : 
    1756                 :            :     /* Add quote styles into dictionary */
    1757         [ +  + ]:          5 :     for (style = quote_styles; style->name; style++) {
    1758         [ -  + ]:          4 :         if (PyModule_AddIntConstant(module, style->name,
    1759                 :          4 :                                     style->style) == -1)
    1760                 :          0 :             return -1;
    1761                 :            :     }
    1762                 :            : 
    1763                 :            :     /* Add the CSV exception object to the module. */
    1764                 :          1 :     PyObject *bases = PyTuple_Pack(1, PyExc_Exception);
    1765         [ -  + ]:          1 :     if (bases == NULL) {
    1766                 :          0 :         return -1;
    1767                 :            :     }
    1768                 :          1 :     module_state->error_obj = PyType_FromModuleAndSpec(module, &error_spec,
    1769                 :            :                                                        bases);
    1770                 :          1 :     Py_DECREF(bases);
    1771         [ -  + ]:          1 :     if (module_state->error_obj == NULL) {
    1772                 :          0 :         return -1;
    1773                 :            :     }
    1774         [ -  + ]:          1 :     if (PyModule_AddType(module, (PyTypeObject *)module_state->error_obj) != 0) {
    1775                 :          0 :         return -1;
    1776                 :            :     }
    1777                 :            : 
    1778                 :          1 :     module_state->str_write = PyUnicode_InternFromString("write");
    1779         [ -  + ]:          1 :     if (module_state->str_write == NULL) {
    1780                 :          0 :         return -1;
    1781                 :            :     }
    1782                 :          1 :     return 0;
    1783                 :            : }
    1784                 :            : 
    1785                 :            : static PyModuleDef_Slot csv_slots[] = {
    1786                 :            :     {Py_mod_exec, csv_exec},
    1787                 :            :     {0, NULL}
    1788                 :            : };
    1789                 :            : 
    1790                 :            : static struct PyModuleDef _csvmodule = {
    1791                 :            :     PyModuleDef_HEAD_INIT,
    1792                 :            :     "_csv",
    1793                 :            :     csv_module_doc,
    1794                 :            :     sizeof(_csvstate),
    1795                 :            :     csv_methods,
    1796                 :            :     csv_slots,
    1797                 :            :     _csv_traverse,
    1798                 :            :     _csv_clear,
    1799                 :            :     _csv_free
    1800                 :            : };
    1801                 :            : 
    1802                 :            : PyMODINIT_FUNC
    1803                 :          1 : PyInit__csv(void)
    1804                 :            : {
    1805                 :          1 :     return PyModuleDef_Init(&_csvmodule);
    1806                 :            : }

Generated by: LCOV version 1.14