LCOV - code coverage report
Current view: top level - Modules - _elementtree.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 1538 1880 81.8 %
Date: 2022-07-20 13:12:14 Functions: 118 118 100.0 %
Branches: 936 1368 68.4 %

           Branch data     Line data    Source code
       1                 :            : /*--------------------------------------------------------------------
       2                 :            :  * Licensed to PSF under a Contributor Agreement.
       3                 :            :  * See https://www.python.org/psf/license for licensing details.
       4                 :            :  *
       5                 :            :  * _elementtree - C accelerator for xml.etree.ElementTree
       6                 :            :  * Copyright (c) 1999-2009 by Secret Labs AB.  All rights reserved.
       7                 :            :  * Copyright (c) 1999-2009 by Fredrik Lundh.
       8                 :            :  *
       9                 :            :  * info@pythonware.com
      10                 :            :  * http://www.pythonware.com
      11                 :            :  *--------------------------------------------------------------------
      12                 :            :  */
      13                 :            : 
      14                 :            : #define PY_SSIZE_T_CLEAN
      15                 :            : #define NEEDS_PY_IDENTIFIER
      16                 :            : 
      17                 :            : #include "Python.h"
      18                 :            : #include "structmember.h"         // PyMemberDef
      19                 :            : 
      20                 :            : /* -------------------------------------------------------------------- */
      21                 :            : /* configuration */
      22                 :            : 
      23                 :            : /* An element can hold this many children without extra memory
      24                 :            :    allocations. */
      25                 :            : #define STATIC_CHILDREN 4
      26                 :            : 
      27                 :            : /* For best performance, chose a value so that 80-90% of all nodes
      28                 :            :    have no more than the given number of children.  Set this to zero
      29                 :            :    to minimize the size of the element structure itself (this only
      30                 :            :    helps if you have lots of leaf nodes with attributes). */
      31                 :            : 
      32                 :            : /* Also note that pymalloc always allocates blocks in multiples of
      33                 :            :    eight bytes.  For the current C version of ElementTree, this means
      34                 :            :    that the number of children should be an even number, at least on
      35                 :            :    32-bit platforms. */
      36                 :            : 
      37                 :            : /* -------------------------------------------------------------------- */
      38                 :            : 
      39                 :            : /* compiler tweaks */
      40                 :            : #if defined(_MSC_VER)
      41                 :            : #define LOCAL(type) static __inline type __fastcall
      42                 :            : #else
      43                 :            : #define LOCAL(type) static type
      44                 :            : #endif
      45                 :            : 
      46                 :            : /* macros used to store 'join' flags in string object pointers.  note
      47                 :            :    that all use of text and tail as object pointers must be wrapped in
      48                 :            :    JOIN_OBJ.  see comments in the ElementObject definition for more
      49                 :            :    info. */
      50                 :            : #define JOIN_GET(p) ((uintptr_t) (p) & 1)
      51                 :            : #define JOIN_SET(p, flag) ((void*) ((uintptr_t) (JOIN_OBJ(p)) | (flag)))
      52                 :            : #define JOIN_OBJ(p) ((PyObject*) ((uintptr_t) (p) & ~(uintptr_t)1))
      53                 :            : 
      54                 :            : /* Py_SETREF for a PyObject* that uses a join flag. */
      55                 :            : Py_LOCAL_INLINE(void)
      56                 :     405827 : _set_joined_ptr(PyObject **p, PyObject *new_joined_ptr)
      57                 :            : {
      58                 :     405827 :     PyObject *tmp = JOIN_OBJ(*p);
      59                 :     405827 :     *p = new_joined_ptr;
      60                 :     405827 :     Py_DECREF(tmp);
      61                 :     405827 : }
      62                 :            : 
      63                 :            : /* Py_CLEAR for a PyObject* that uses a join flag. Pass the pointer by
      64                 :            :  * reference since this function sets it to NULL.
      65                 :            : */
      66                 :     404516 : static void _clear_joined_ptr(PyObject **p)
      67                 :            : {
      68         [ +  + ]:     404516 :     if (*p) {
      69                 :     404500 :         _set_joined_ptr(p, NULL);
      70                 :            :     }
      71                 :     404516 : }
      72                 :            : 
      73                 :            : /* Types defined by this extension */
      74                 :            : static PyTypeObject Element_Type;
      75                 :            : static PyTypeObject ElementIter_Type;
      76                 :            : static PyTypeObject TreeBuilder_Type;
      77                 :            : static PyTypeObject XMLParser_Type;
      78                 :            : 
      79                 :            : 
      80                 :            : /* Per-module state; PEP 3121 */
      81                 :            : typedef struct {
      82                 :            :     PyObject *parseerror_obj;
      83                 :            :     PyObject *deepcopy_obj;
      84                 :            :     PyObject *elementpath_obj;
      85                 :            :     PyObject *comment_factory;
      86                 :            :     PyObject *pi_factory;
      87                 :            : } elementtreestate;
      88                 :            : 
      89                 :            : static struct PyModuleDef elementtreemodule;
      90                 :            : 
      91                 :            : /* Given a module object (assumed to be _elementtree), get its per-module
      92                 :            :  * state.
      93                 :            :  */
      94                 :            : static inline elementtreestate*
      95                 :        370 : get_elementtree_state(PyObject *module)
      96                 :            : {
      97                 :        370 :     void *state = PyModule_GetState(module);
      98                 :            :     assert(state != NULL);
      99                 :        370 :     return (elementtreestate *)state;
     100                 :            : }
     101                 :            : 
     102                 :            : /* Find the module instance imported in the currently running sub-interpreter
     103                 :            :  * and get its state.
     104                 :            :  */
     105                 :            : #define ET_STATE_GLOBAL \
     106                 :            :     ((elementtreestate *) PyModule_GetState(PyState_FindModule(&elementtreemodule)))
     107                 :            : 
     108                 :            : static int
     109                 :         25 : elementtree_clear(PyObject *m)
     110                 :            : {
     111                 :         25 :     elementtreestate *st = get_elementtree_state(m);
     112         [ +  + ]:         25 :     Py_CLEAR(st->parseerror_obj);
     113         [ +  + ]:         25 :     Py_CLEAR(st->deepcopy_obj);
     114         [ +  + ]:         25 :     Py_CLEAR(st->elementpath_obj);
     115         [ +  + ]:         25 :     Py_CLEAR(st->comment_factory);
     116         [ +  + ]:         25 :     Py_CLEAR(st->pi_factory);
     117                 :         25 :     return 0;
     118                 :            : }
     119                 :            : 
     120                 :            : static int
     121                 :        332 : elementtree_traverse(PyObject *m, visitproc visit, void *arg)
     122                 :            : {
     123                 :        332 :     elementtreestate *st = get_elementtree_state(m);
     124   [ +  +  -  + ]:        332 :     Py_VISIT(st->parseerror_obj);
     125   [ +  -  -  + ]:        332 :     Py_VISIT(st->deepcopy_obj);
     126   [ +  +  -  + ]:        332 :     Py_VISIT(st->elementpath_obj);
     127   [ +  +  -  + ]:        332 :     Py_VISIT(st->comment_factory);
     128   [ +  +  -  + ]:        332 :     Py_VISIT(st->pi_factory);
     129                 :        332 :     return 0;
     130                 :            : }
     131                 :            : 
     132                 :            : static void
     133                 :         13 : elementtree_free(void *m)
     134                 :            : {
     135                 :         13 :     elementtree_clear((PyObject *)m);
     136                 :         13 : }
     137                 :            : 
     138                 :            : /* helpers */
     139                 :            : 
     140                 :            : LOCAL(PyObject*)
     141                 :         72 : list_join(PyObject* list)
     142                 :            : {
     143                 :            :     /* join list elements */
     144                 :            :     PyObject* joiner;
     145                 :            :     PyObject* result;
     146                 :            : 
     147                 :         72 :     joiner = PyUnicode_FromStringAndSize("", 0);
     148         [ -  + ]:         72 :     if (!joiner)
     149                 :          0 :         return NULL;
     150                 :         72 :     result = PyUnicode_Join(joiner, list);
     151                 :         72 :     Py_DECREF(joiner);
     152                 :         72 :     return result;
     153                 :            : }
     154                 :            : 
     155                 :            : /* Is the given object an empty dictionary?
     156                 :            : */
     157                 :            : static int
     158                 :       1174 : is_empty_dict(PyObject *obj)
     159                 :            : {
     160   [ +  -  +  + ]:       1174 :     return PyDict_CheckExact(obj) && PyDict_GET_SIZE(obj) == 0;
     161                 :            : }
     162                 :            : 
     163                 :            : 
     164                 :            : /* -------------------------------------------------------------------- */
     165                 :            : /* the Element type */
     166                 :            : 
     167                 :            : typedef struct {
     168                 :            : 
     169                 :            :     /* attributes (a dictionary object), or NULL if no attributes */
     170                 :            :     PyObject* attrib;
     171                 :            : 
     172                 :            :     /* child elements */
     173                 :            :     Py_ssize_t length; /* actual number of items */
     174                 :            :     Py_ssize_t allocated; /* allocated items */
     175                 :            : 
     176                 :            :     /* this either points to _children or to a malloced buffer */
     177                 :            :     PyObject* *children;
     178                 :            : 
     179                 :            :     PyObject* _children[STATIC_CHILDREN];
     180                 :            : 
     181                 :            : } ElementObjectExtra;
     182                 :            : 
     183                 :            : typedef struct {
     184                 :            :     PyObject_HEAD
     185                 :            : 
     186                 :            :     /* element tag (a string). */
     187                 :            :     PyObject* tag;
     188                 :            : 
     189                 :            :     /* text before first child.  note that this is a tagged pointer;
     190                 :            :        use JOIN_OBJ to get the object pointer.  the join flag is used
     191                 :            :        to distinguish lists created by the tree builder from lists
     192                 :            :        assigned to the attribute by application code; the former
     193                 :            :        should be joined before being returned to the user, the latter
     194                 :            :        should be left intact. */
     195                 :            :     PyObject* text;
     196                 :            : 
     197                 :            :     /* text after this element, in parent.  note that this is a tagged
     198                 :            :        pointer; use JOIN_OBJ to get the object pointer. */
     199                 :            :     PyObject* tail;
     200                 :            : 
     201                 :            :     ElementObjectExtra* extra;
     202                 :            : 
     203                 :            :     PyObject *weakreflist; /* For tp_weaklistoffset */
     204                 :            : 
     205                 :            : } ElementObject;
     206                 :            : 
     207                 :            : 
     208                 :            : #define Element_CheckExact(op) Py_IS_TYPE(op, &Element_Type)
     209                 :            : #define Element_Check(op) PyObject_TypeCheck(op, &Element_Type)
     210                 :            : 
     211                 :            : 
     212                 :            : /* -------------------------------------------------------------------- */
     213                 :            : /* Element constructors and destructor */
     214                 :            : 
     215                 :            : LOCAL(int)
     216                 :     200623 : create_extra(ElementObject* self, PyObject* attrib)
     217                 :            : {
     218                 :     200623 :     self->extra = PyObject_Malloc(sizeof(ElementObjectExtra));
     219         [ -  + ]:     200623 :     if (!self->extra) {
     220                 :            :         PyErr_NoMemory();
     221                 :          0 :         return -1;
     222                 :            :     }
     223                 :            : 
     224                 :     200623 :     Py_XINCREF(attrib);
     225                 :     200623 :     self->extra->attrib = attrib;
     226                 :            : 
     227                 :     200623 :     self->extra->length = 0;
     228                 :     200623 :     self->extra->allocated = STATIC_CHILDREN;
     229                 :     200623 :     self->extra->children = self->extra->_children;
     230                 :            : 
     231                 :     200623 :     return 0;
     232                 :            : }
     233                 :            : 
     234                 :            : LOCAL(void)
     235                 :     200672 : dealloc_extra(ElementObjectExtra *extra)
     236                 :            : {
     237                 :            :     Py_ssize_t i;
     238                 :            : 
     239         [ +  + ]:     200672 :     if (!extra)
     240                 :         49 :         return;
     241                 :            : 
     242                 :     200623 :     Py_XDECREF(extra->attrib);
     243                 :            : 
     244         [ +  + ]:     401278 :     for (i = 0; i < extra->length; i++)
     245                 :     200655 :         Py_DECREF(extra->children[i]);
     246                 :            : 
     247         [ +  + ]:     200623 :     if (extra->children != extra->_children)
     248                 :         10 :         PyObject_Free(extra->children);
     249                 :            : 
     250                 :     200623 :     PyObject_Free(extra);
     251                 :            : }
     252                 :            : 
     253                 :            : LOCAL(void)
     254                 :     202278 : clear_extra(ElementObject* self)
     255                 :            : {
     256                 :            :     ElementObjectExtra *myextra;
     257                 :            : 
     258         [ +  + ]:     202278 :     if (!self->extra)
     259                 :       1755 :         return;
     260                 :            : 
     261                 :            :     /* Avoid DECREFs calling into this code again (cycles, etc.)
     262                 :            :     */
     263                 :     200523 :     myextra = self->extra;
     264                 :     200523 :     self->extra = NULL;
     265                 :            : 
     266                 :     200523 :     dealloc_extra(myextra);
     267                 :            : }
     268                 :            : 
     269                 :            : /* Convenience internal function to create new Element objects with the given
     270                 :            :  * tag and attributes.
     271                 :            : */
     272                 :            : LOCAL(PyObject*)
     273                 :     201836 : create_new_element(PyObject* tag, PyObject* attrib)
     274                 :            : {
     275                 :            :     ElementObject* self;
     276                 :            : 
     277                 :     201836 :     self = PyObject_GC_New(ElementObject, &Element_Type);
     278         [ -  + ]:     201836 :     if (self == NULL)
     279                 :          0 :         return NULL;
     280                 :     201836 :     self->extra = NULL;
     281                 :            : 
     282                 :     201836 :     Py_INCREF(tag);
     283                 :     201836 :     self->tag = tag;
     284                 :            : 
     285                 :     201836 :     Py_INCREF(Py_None);
     286                 :     201836 :     self->text = Py_None;
     287                 :            : 
     288                 :     201836 :     Py_INCREF(Py_None);
     289                 :     201836 :     self->tail = Py_None;
     290                 :            : 
     291                 :     201836 :     self->weakreflist = NULL;
     292                 :            : 
     293                 :     201836 :     PyObject_GC_Track(self);
     294                 :            : 
     295   [ +  +  +  + ]:     201836 :     if (attrib != NULL && !is_empty_dict(attrib)) {
     296         [ -  + ]:        125 :         if (create_extra(self, attrib) < 0) {
     297                 :          0 :             Py_DECREF(self);
     298                 :          0 :             return NULL;
     299                 :            :         }
     300                 :            :     }
     301                 :            : 
     302                 :     201836 :     return (PyObject*) self;
     303                 :            : }
     304                 :            : 
     305                 :            : static PyObject *
     306                 :        414 : element_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     307                 :            : {
     308                 :        414 :     ElementObject *e = (ElementObject *)type->tp_alloc(type, 0);
     309         [ +  - ]:        414 :     if (e != NULL) {
     310                 :        414 :         Py_INCREF(Py_None);
     311                 :        414 :         e->tag = Py_None;
     312                 :            : 
     313                 :        414 :         Py_INCREF(Py_None);
     314                 :        414 :         e->text = Py_None;
     315                 :            : 
     316                 :        414 :         Py_INCREF(Py_None);
     317                 :        414 :         e->tail = Py_None;
     318                 :            : 
     319                 :        414 :         e->extra = NULL;
     320                 :        414 :         e->weakreflist = NULL;
     321                 :            :     }
     322                 :        414 :     return (PyObject *)e;
     323                 :            : }
     324                 :            : 
     325                 :            : /* Helper function for extracting the attrib dictionary from a keywords dict.
     326                 :            :  * This is required by some constructors/functions in this module that can
     327                 :            :  * either accept attrib as a keyword argument or all attributes splashed
     328                 :            :  * directly into *kwds.
     329                 :            :  *
     330                 :            :  * Return a dictionary with the content of kwds merged into the content of
     331                 :            :  * attrib. If there is no attrib keyword, return a copy of kwds.
     332                 :            :  */
     333                 :            : static PyObject*
     334                 :         24 : get_attrib_from_keywords(PyObject *kwds)
     335                 :            : {
     336                 :         24 :     PyObject *attrib_str = PyUnicode_FromString("attrib");
     337         [ -  + ]:         24 :     if (attrib_str == NULL) {
     338                 :          0 :         return NULL;
     339                 :            :     }
     340                 :         24 :     PyObject *attrib = PyDict_GetItemWithError(kwds, attrib_str);
     341                 :            : 
     342         [ +  + ]:         24 :     if (attrib) {
     343                 :            :         /* If attrib was found in kwds, copy its value and remove it from
     344                 :            :          * kwds
     345                 :            :          */
     346         [ +  + ]:          3 :         if (!PyDict_Check(attrib)) {
     347                 :          1 :             Py_DECREF(attrib_str);
     348                 :          1 :             PyErr_Format(PyExc_TypeError, "attrib must be dict, not %.100s",
     349                 :          1 :                          Py_TYPE(attrib)->tp_name);
     350                 :          1 :             return NULL;
     351                 :            :         }
     352                 :          2 :         attrib = PyDict_Copy(attrib);
     353   [ +  -  -  + ]:          2 :         if (attrib && PyDict_DelItem(kwds, attrib_str) < 0) {
     354                 :          0 :             Py_DECREF(attrib);
     355                 :          0 :             attrib = NULL;
     356                 :            :         }
     357                 :            :     }
     358         [ +  - ]:         21 :     else if (!PyErr_Occurred()) {
     359                 :         21 :         attrib = PyDict_New();
     360                 :            :     }
     361                 :            : 
     362                 :         23 :     Py_DECREF(attrib_str);
     363                 :            : 
     364   [ +  -  -  + ]:         23 :     if (attrib != NULL && PyDict_Update(attrib, kwds) < 0) {
     365                 :          0 :         Py_DECREF(attrib);
     366                 :          0 :         return NULL;
     367                 :            :     }
     368                 :         23 :     return attrib;
     369                 :            : }
     370                 :            : 
     371                 :            : /*[clinic input]
     372                 :            : module _elementtree
     373                 :            : class _elementtree.Element "ElementObject *" "&Element_Type"
     374                 :            : class _elementtree.TreeBuilder "TreeBuilderObject *" "&TreeBuilder_Type"
     375                 :            : class _elementtree.XMLParser "XMLParserObject *" "&XMLParser_Type"
     376                 :            : [clinic start generated code]*/
     377                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=159aa50a54061c22]*/
     378                 :            : 
     379                 :            : static int
     380                 :        365 : element_init(PyObject *self, PyObject *args, PyObject *kwds)
     381                 :            : {
     382                 :            :     PyObject *tag;
     383                 :        365 :     PyObject *attrib = NULL;
     384                 :            :     ElementObject *self_elem;
     385                 :            : 
     386         [ +  + ]:        365 :     if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, &PyDict_Type, &attrib))
     387                 :          1 :         return -1;
     388                 :            : 
     389         [ +  + ]:        364 :     if (attrib) {
     390                 :            :         /* attrib passed as positional arg */
     391                 :         15 :         attrib = PyDict_Copy(attrib);
     392         [ -  + ]:         15 :         if (!attrib)
     393                 :          0 :             return -1;
     394         [ +  + ]:         15 :         if (kwds) {
     395         [ -  + ]:          4 :             if (PyDict_Update(attrib, kwds) < 0) {
     396                 :          0 :                 Py_DECREF(attrib);
     397                 :          0 :                 return -1;
     398                 :            :             }
     399                 :            :         }
     400         [ +  + ]:        349 :     } else if (kwds) {
     401                 :            :         /* have keywords args */
     402                 :         22 :         attrib = get_attrib_from_keywords(kwds);
     403         [ +  + ]:         22 :         if (!attrib)
     404                 :          1 :             return -1;
     405                 :            :     }
     406                 :            : 
     407                 :        363 :     self_elem = (ElementObject *)self;
     408                 :            : 
     409   [ +  +  +  + ]:        363 :     if (attrib != NULL && !is_empty_dict(attrib)) {
     410         [ -  + ]:         33 :         if (create_extra(self_elem, attrib) < 0) {
     411                 :          0 :             Py_DECREF(attrib);
     412                 :          0 :             return -1;
     413                 :            :         }
     414                 :            :     }
     415                 :            : 
     416                 :            :     /* We own a reference to attrib here and it's no longer needed. */
     417                 :        363 :     Py_XDECREF(attrib);
     418                 :            : 
     419                 :            :     /* Replace the objects already pointed to by tag, text and tail. */
     420                 :        363 :     Py_INCREF(tag);
     421                 :        363 :     Py_XSETREF(self_elem->tag, tag);
     422                 :            : 
     423                 :        363 :     Py_INCREF(Py_None);
     424                 :        363 :     _set_joined_ptr(&self_elem->text, Py_None);
     425                 :            : 
     426                 :        363 :     Py_INCREF(Py_None);
     427                 :        363 :     _set_joined_ptr(&self_elem->tail, Py_None);
     428                 :            : 
     429                 :        363 :     return 0;
     430                 :            : }
     431                 :            : 
     432                 :            : LOCAL(int)
     433                 :     200701 : element_resize(ElementObject* self, Py_ssize_t extra)
     434                 :            : {
     435                 :            :     Py_ssize_t size;
     436                 :            :     PyObject* *children;
     437                 :            : 
     438                 :            :     assert(extra >= 0);
     439                 :            :     /* make sure self->children can hold the given number of extra
     440                 :            :        elements.  set an exception and return -1 if allocation failed */
     441                 :            : 
     442         [ +  + ]:     200701 :     if (!self->extra) {
     443         [ -  + ]:     200427 :         if (create_extra(self, NULL) < 0)
     444                 :          0 :             return -1;
     445                 :            :     }
     446                 :            : 
     447                 :     200701 :     size = self->extra->length + extra;  /* never overflows */
     448                 :            : 
     449         [ +  + ]:     200701 :     if (size > self->extra->allocated) {
     450                 :            :         /* use Python 2.4's list growth strategy */
     451         [ +  + ]:         13 :         size = (size >> 3) + (size < 9 ? 3 : 6) + size;
     452                 :            :         /* Coverity CID #182 size_error: Allocating 1 bytes to pointer "children"
     453                 :            :          * which needs at least 4 bytes.
     454                 :            :          * Although it's a false alarm always assume at least one child to
     455                 :            :          * be safe.
     456                 :            :          */
     457         [ +  - ]:         13 :         size = size ? size : 1;
     458         [ -  + ]:         13 :         if ((size_t)size > PY_SSIZE_T_MAX/sizeof(PyObject*))
     459                 :          0 :             goto nomemory;
     460         [ +  + ]:         13 :         if (self->extra->children != self->extra->_children) {
     461                 :            :             /* Coverity CID #182 size_error: Allocating 1 bytes to pointer
     462                 :            :              * "children", which needs at least 4 bytes. Although it's a
     463                 :            :              * false alarm always assume at least one child to be safe.
     464                 :            :              */
     465                 :          3 :             children = PyObject_Realloc(self->extra->children,
     466                 :            :                                         size * sizeof(PyObject*));
     467         [ -  + ]:          3 :             if (!children)
     468                 :          0 :                 goto nomemory;
     469                 :            :         } else {
     470                 :         10 :             children = PyObject_Malloc(size * sizeof(PyObject*));
     471         [ -  + ]:         10 :             if (!children)
     472                 :          0 :                 goto nomemory;
     473                 :            :             /* copy existing children from static area to malloc buffer */
     474                 :         10 :             memcpy(children, self->extra->children,
     475                 :         10 :                    self->extra->length * sizeof(PyObject*));
     476                 :            :         }
     477                 :         13 :         self->extra->children = children;
     478                 :         13 :         self->extra->allocated = size;
     479                 :            :     }
     480                 :            : 
     481                 :     200701 :     return 0;
     482                 :            : 
     483                 :          0 :   nomemory:
     484                 :            :     PyErr_NoMemory();
     485                 :          0 :     return -1;
     486                 :            : }
     487                 :            : 
     488                 :            : LOCAL(void)
     489                 :          7 : raise_type_error(PyObject *element)
     490                 :            : {
     491                 :          7 :     PyErr_Format(PyExc_TypeError,
     492                 :            :                  "expected an Element, not \"%.200s\"",
     493                 :          7 :                  Py_TYPE(element)->tp_name);
     494                 :          7 : }
     495                 :            : 
     496                 :            : LOCAL(int)
     497                 :     200507 : element_add_subelement(ElementObject* self, PyObject* element)
     498                 :            : {
     499                 :            :     /* add a child element to a parent */
     500                 :            : 
     501         [ +  + ]:     200507 :     if (!Element_Check(element)) {
     502                 :          3 :         raise_type_error(element);
     503                 :          3 :         return -1;
     504                 :            :     }
     505                 :            : 
     506         [ -  + ]:     200504 :     if (element_resize(self, 1) < 0)
     507                 :          0 :         return -1;
     508                 :            : 
     509                 :     200504 :     Py_INCREF(element);
     510                 :     200504 :     self->extra->children[self->extra->length] = element;
     511                 :            : 
     512                 :     200504 :     self->extra->length++;
     513                 :            : 
     514                 :     200504 :     return 0;
     515                 :            : }
     516                 :            : 
     517                 :            : LOCAL(PyObject*)
     518                 :        153 : element_get_attrib(ElementObject* self)
     519                 :            : {
     520                 :            :     /* return borrowed reference to attrib dictionary */
     521                 :            :     /* note: this function assumes that the extra section exists */
     522                 :            : 
     523                 :        153 :     PyObject* res = self->extra->attrib;
     524                 :            : 
     525         [ +  + ]:        153 :     if (!res) {
     526                 :            :         /* create missing dictionary */
     527                 :         49 :         res = self->extra->attrib = PyDict_New();
     528                 :            :     }
     529                 :            : 
     530                 :        153 :     return res;
     531                 :            : }
     532                 :            : 
     533                 :            : LOCAL(PyObject*)
     534                 :       1308 : element_get_text(ElementObject* self)
     535                 :            : {
     536                 :            :     /* return borrowed reference to text attribute */
     537                 :            : 
     538                 :       1308 :     PyObject *res = self->text;
     539                 :            : 
     540         [ +  + ]:       1308 :     if (JOIN_GET(res)) {
     541                 :         32 :         res = JOIN_OBJ(res);
     542         [ +  - ]:         32 :         if (PyList_CheckExact(res)) {
     543                 :         32 :             PyObject *tmp = list_join(res);
     544         [ -  + ]:         32 :             if (!tmp)
     545                 :          0 :                 return NULL;
     546                 :         32 :             self->text = tmp;
     547                 :         32 :             Py_DECREF(res);
     548                 :         32 :             res = tmp;
     549                 :            :         }
     550                 :            :     }
     551                 :            : 
     552                 :       1308 :     return res;
     553                 :            : }
     554                 :            : 
     555                 :            : LOCAL(PyObject*)
     556                 :        814 : element_get_tail(ElementObject* self)
     557                 :            : {
     558                 :            :     /* return borrowed reference to text attribute */
     559                 :            : 
     560                 :        814 :     PyObject *res = self->tail;
     561                 :            : 
     562         [ +  + ]:        814 :     if (JOIN_GET(res)) {
     563                 :         26 :         res = JOIN_OBJ(res);
     564         [ +  - ]:         26 :         if (PyList_CheckExact(res)) {
     565                 :         26 :             PyObject *tmp = list_join(res);
     566         [ -  + ]:         26 :             if (!tmp)
     567                 :          0 :                 return NULL;
     568                 :         26 :             self->tail = tmp;
     569                 :         26 :             Py_DECREF(res);
     570                 :         26 :             res = tmp;
     571                 :            :         }
     572                 :            :     }
     573                 :            : 
     574                 :        814 :     return res;
     575                 :            : }
     576                 :            : 
     577                 :            : static PyObject*
     578                 :     200125 : subelement(PyObject *self, PyObject *args, PyObject *kwds)
     579                 :            : {
     580                 :            :     PyObject* elem;
     581                 :            : 
     582                 :            :     ElementObject* parent;
     583                 :            :     PyObject* tag;
     584                 :     200125 :     PyObject* attrib = NULL;
     585         [ -  + ]:     200125 :     if (!PyArg_ParseTuple(args, "O!O|O!:SubElement",
     586                 :            :                           &Element_Type, &parent, &tag,
     587                 :            :                           &PyDict_Type, &attrib)) {
     588                 :          0 :         return NULL;
     589                 :            :     }
     590                 :            : 
     591         [ -  + ]:     200125 :     if (attrib) {
     592                 :            :         /* attrib passed as positional arg */
     593                 :          0 :         attrib = PyDict_Copy(attrib);
     594         [ #  # ]:          0 :         if (!attrib)
     595                 :          0 :             return NULL;
     596   [ #  #  #  # ]:          0 :         if (kwds != NULL && PyDict_Update(attrib, kwds) < 0) {
     597                 :          0 :             Py_DECREF(attrib);
     598                 :          0 :             return NULL;
     599                 :            :         }
     600         [ +  + ]:     200125 :     } else if (kwds) {
     601                 :            :         /* have keyword args */
     602                 :          2 :         attrib = get_attrib_from_keywords(kwds);
     603         [ -  + ]:          2 :         if (!attrib)
     604                 :          0 :             return NULL;
     605                 :            :     } else {
     606                 :            :         /* no attrib arg, no kwds, so no attribute */
     607                 :            :     }
     608                 :            : 
     609                 :     200125 :     elem = create_new_element(tag, attrib);
     610                 :     200125 :     Py_XDECREF(attrib);
     611         [ -  + ]:     200125 :     if (elem == NULL)
     612                 :          0 :         return NULL;
     613                 :            : 
     614         [ -  + ]:     200125 :     if (element_add_subelement(parent, elem) < 0) {
     615                 :          0 :         Py_DECREF(elem);
     616                 :          0 :         return NULL;
     617                 :            :     }
     618                 :            : 
     619                 :     200125 :     return elem;
     620                 :            : }
     621                 :            : 
     622                 :            : static int
     623                 :    1310939 : element_gc_traverse(ElementObject *self, visitproc visit, void *arg)
     624                 :            : {
     625   [ +  -  -  + ]:    1310939 :     Py_VISIT(self->tag);
     626   [ +  -  -  + ]:    1310939 :     Py_VISIT(JOIN_OBJ(self->text));
     627   [ +  -  -  + ]:    1310939 :     Py_VISIT(JOIN_OBJ(self->tail));
     628                 :            : 
     629         [ +  + ]:    1310939 :     if (self->extra) {
     630                 :            :         Py_ssize_t i;
     631   [ +  +  -  + ]:    1310302 :         Py_VISIT(self->extra->attrib);
     632                 :            : 
     633         [ +  + ]:    2620578 :         for (i = 0; i < self->extra->length; ++i)
     634   [ +  -  -  + ]:    1310276 :             Py_VISIT(self->extra->children[i]);
     635                 :            :     }
     636                 :    1310939 :     return 0;
     637                 :            : }
     638                 :            : 
     639                 :            : static int
     640                 :     202258 : element_gc_clear(ElementObject *self)
     641                 :            : {
     642         [ +  + ]:     202258 :     Py_CLEAR(self->tag);
     643                 :     202258 :     _clear_joined_ptr(&self->text);
     644                 :     202258 :     _clear_joined_ptr(&self->tail);
     645                 :            : 
     646                 :            :     /* After dropping all references from extra, it's no longer valid anyway,
     647                 :            :      * so fully deallocate it.
     648                 :            :     */
     649                 :     202258 :     clear_extra(self);
     650                 :     202258 :     return 0;
     651                 :            : }
     652                 :            : 
     653                 :            : static void
     654                 :     206331 : element_dealloc(ElementObject* self)
     655                 :            : {
     656                 :            :     /* bpo-31095: UnTrack is needed before calling any callbacks */
     657                 :     206331 :     PyObject_GC_UnTrack(self);
     658   [ +  +  +  + ]:     206331 :     Py_TRASHCAN_BEGIN(self, element_dealloc)
     659                 :            : 
     660         [ +  + ]:     202250 :     if (self->weakreflist != NULL)
     661                 :          1 :         PyObject_ClearWeakRefs((PyObject *) self);
     662                 :            : 
     663                 :            :     /* element_gc_clear clears all references and deallocates extra
     664                 :            :     */
     665                 :     202250 :     element_gc_clear(self);
     666                 :            : 
     667                 :     202250 :     Py_TYPE(self)->tp_free((PyObject *)self);
     668         [ +  + ]:     202250 :     Py_TRASHCAN_END
     669                 :     206331 : }
     670                 :            : 
     671                 :            : /* -------------------------------------------------------------------- */
     672                 :            : 
     673                 :            : /*[clinic input]
     674                 :            : _elementtree.Element.append
     675                 :            : 
     676                 :            :     subelement: object(subclass_of='&Element_Type')
     677                 :            :     /
     678                 :            : 
     679                 :            : [clinic start generated code]*/
     680                 :            : 
     681                 :            : static PyObject *
     682                 :         38 : _elementtree_Element_append_impl(ElementObject *self, PyObject *subelement)
     683                 :            : /*[clinic end generated code: output=54a884b7cf2295f4 input=3ed648beb5bfa22a]*/
     684                 :            : {
     685         [ -  + ]:         38 :     if (element_add_subelement(self, subelement) < 0)
     686                 :          0 :         return NULL;
     687                 :            : 
     688                 :         38 :     Py_RETURN_NONE;
     689                 :            : }
     690                 :            : 
     691                 :            : /*[clinic input]
     692                 :            : _elementtree.Element.clear
     693                 :            : 
     694                 :            : [clinic start generated code]*/
     695                 :            : 
     696                 :            : static PyObject *
     697                 :         20 : _elementtree_Element_clear_impl(ElementObject *self)
     698                 :            : /*[clinic end generated code: output=8bcd7a51f94cfff6 input=3c719ff94bf45dd6]*/
     699                 :            : {
     700                 :         20 :     clear_extra(self);
     701                 :            : 
     702                 :         20 :     Py_INCREF(Py_None);
     703                 :         20 :     _set_joined_ptr(&self->text, Py_None);
     704                 :            : 
     705                 :         20 :     Py_INCREF(Py_None);
     706                 :         20 :     _set_joined_ptr(&self->tail, Py_None);
     707                 :            : 
     708                 :         20 :     Py_RETURN_NONE;
     709                 :            : }
     710                 :            : 
     711                 :            : /*[clinic input]
     712                 :            : _elementtree.Element.__copy__
     713                 :            : 
     714                 :            : [clinic start generated code]*/
     715                 :            : 
     716                 :            : static PyObject *
     717                 :         24 : _elementtree_Element___copy___impl(ElementObject *self)
     718                 :            : /*[clinic end generated code: output=2c701ebff7247781 input=ad87aaebe95675bf]*/
     719                 :            : {
     720                 :            :     Py_ssize_t i;
     721                 :            :     ElementObject* element;
     722                 :            : 
     723                 :         24 :     element = (ElementObject*) create_new_element(
     724         [ +  - ]:         24 :         self->tag, self->extra ? self->extra->attrib : NULL);
     725         [ -  + ]:         24 :     if (!element)
     726                 :          0 :         return NULL;
     727                 :            : 
     728                 :         24 :     Py_INCREF(JOIN_OBJ(self->text));
     729                 :         24 :     _set_joined_ptr(&element->text, self->text);
     730                 :            : 
     731                 :         24 :     Py_INCREF(JOIN_OBJ(self->tail));
     732                 :         24 :     _set_joined_ptr(&element->tail, self->tail);
     733                 :            : 
     734                 :            :     assert(!element->extra || !element->extra->length);
     735         [ +  - ]:         24 :     if (self->extra) {
     736         [ -  + ]:         24 :         if (element_resize(element, self->extra->length) < 0) {
     737                 :          0 :             Py_DECREF(element);
     738                 :          0 :             return NULL;
     739                 :            :         }
     740                 :            : 
     741         [ +  + ]:         66 :         for (i = 0; i < self->extra->length; i++) {
     742                 :         42 :             Py_INCREF(self->extra->children[i]);
     743                 :         42 :             element->extra->children[i] = self->extra->children[i];
     744                 :            :         }
     745                 :            : 
     746                 :            :         assert(!element->extra->length);
     747                 :         24 :         element->extra->length = self->extra->length;
     748                 :            :     }
     749                 :            : 
     750                 :         24 :     return (PyObject*) element;
     751                 :            : }
     752                 :            : 
     753                 :            : /* Helper for a deep copy. */
     754                 :            : LOCAL(PyObject *) deepcopy(PyObject *, PyObject *);
     755                 :            : 
     756                 :            : /*[clinic input]
     757                 :            : _elementtree.Element.__deepcopy__
     758                 :            : 
     759                 :            :     memo: object(subclass_of="&PyDict_Type")
     760                 :            :     /
     761                 :            : 
     762                 :            : [clinic start generated code]*/
     763                 :            : 
     764                 :            : static PyObject *
     765                 :          5 : _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
     766                 :            : /*[clinic end generated code: output=eefc3df50465b642 input=a2d40348c0aade10]*/
     767                 :            : {
     768                 :            :     Py_ssize_t i;
     769                 :            :     ElementObject* element;
     770                 :            :     PyObject* tag;
     771                 :            :     PyObject* attrib;
     772                 :            :     PyObject* text;
     773                 :            :     PyObject* tail;
     774                 :            :     PyObject* id;
     775                 :            : 
     776                 :          5 :     tag = deepcopy(self->tag, memo);
     777         [ -  + ]:          5 :     if (!tag)
     778                 :          0 :         return NULL;
     779                 :            : 
     780   [ +  +  +  + ]:          5 :     if (self->extra && self->extra->attrib) {
     781                 :          2 :         attrib = deepcopy(self->extra->attrib, memo);
     782         [ -  + ]:          2 :         if (!attrib) {
     783                 :          0 :             Py_DECREF(tag);
     784                 :          0 :             return NULL;
     785                 :            :         }
     786                 :            :     } else {
     787                 :          3 :         attrib = NULL;
     788                 :            :     }
     789                 :            : 
     790                 :          5 :     element = (ElementObject*) create_new_element(tag, attrib);
     791                 :            : 
     792                 :          5 :     Py_DECREF(tag);
     793                 :          5 :     Py_XDECREF(attrib);
     794                 :            : 
     795         [ -  + ]:          5 :     if (!element)
     796                 :          0 :         return NULL;
     797                 :            : 
     798                 :          5 :     text = deepcopy(JOIN_OBJ(self->text), memo);
     799         [ -  + ]:          5 :     if (!text)
     800                 :          0 :         goto error;
     801                 :          5 :     _set_joined_ptr(&element->text, JOIN_SET(text, JOIN_GET(self->text)));
     802                 :            : 
     803                 :          5 :     tail = deepcopy(JOIN_OBJ(self->tail), memo);
     804         [ -  + ]:          5 :     if (!tail)
     805                 :          0 :         goto error;
     806                 :          5 :     _set_joined_ptr(&element->tail, JOIN_SET(tail, JOIN_GET(self->tail)));
     807                 :            : 
     808                 :            :     assert(!element->extra || !element->extra->length);
     809         [ +  + ]:          5 :     if (self->extra) {
     810         [ -  + ]:          4 :         if (element_resize(element, self->extra->length) < 0)
     811                 :          0 :             goto error;
     812                 :            : 
     813         [ +  + ]:          6 :         for (i = 0; i < self->extra->length; i++) {
     814                 :          3 :             PyObject* child = deepcopy(self->extra->children[i], memo);
     815   [ +  -  +  + ]:          3 :             if (!child || !Element_Check(child)) {
     816         [ +  - ]:          1 :                 if (child) {
     817                 :          1 :                     raise_type_error(child);
     818                 :          1 :                     Py_DECREF(child);
     819                 :            :                 }
     820                 :          1 :                 element->extra->length = i;
     821                 :          1 :                 goto error;
     822                 :            :             }
     823                 :          2 :             element->extra->children[i] = child;
     824                 :            :         }
     825                 :            : 
     826                 :            :         assert(!element->extra->length);
     827                 :          3 :         element->extra->length = self->extra->length;
     828                 :            :     }
     829                 :            : 
     830                 :            :     /* add object to memo dictionary (so deepcopy won't visit it again) */
     831                 :          4 :     id = PyLong_FromSsize_t((uintptr_t) self);
     832         [ -  + ]:          4 :     if (!id)
     833                 :          0 :         goto error;
     834                 :            : 
     835                 :          4 :     i = PyDict_SetItem(memo, id, (PyObject*) element);
     836                 :            : 
     837                 :          4 :     Py_DECREF(id);
     838                 :            : 
     839         [ -  + ]:          4 :     if (i < 0)
     840                 :          0 :         goto error;
     841                 :            : 
     842                 :          4 :     return (PyObject*) element;
     843                 :            : 
     844                 :          1 :   error:
     845                 :          1 :     Py_DECREF(element);
     846                 :          1 :     return NULL;
     847                 :            : }
     848                 :            : 
     849                 :            : LOCAL(PyObject *)
     850                 :         20 : deepcopy(PyObject *object, PyObject *memo)
     851                 :            : {
     852                 :            :     /* do a deep copy of the given object */
     853                 :            :     elementtreestate *st;
     854                 :            :     PyObject *stack[2];
     855                 :            : 
     856                 :            :     /* Fast paths */
     857   [ +  +  +  + ]:         20 :     if (object == Py_None || PyUnicode_CheckExact(object)) {
     858                 :         15 :         Py_INCREF(object);
     859                 :         15 :         return object;
     860                 :            :     }
     861                 :            : 
     862         [ +  + ]:          5 :     if (Py_REFCNT(object) == 1) {
     863         [ +  + ]:          4 :         if (PyDict_CheckExact(object)) {
     864                 :            :             PyObject *key, *value;
     865                 :          2 :             Py_ssize_t pos = 0;
     866                 :          2 :             int simple = 1;
     867         [ +  + ]:          4 :             while (PyDict_Next(object, &pos, &key, &value)) {
     868   [ +  -  -  + ]:          2 :                 if (!PyUnicode_CheckExact(key) || !PyUnicode_CheckExact(value)) {
     869                 :          0 :                     simple = 0;
     870                 :          0 :                     break;
     871                 :            :                 }
     872                 :            :             }
     873         [ +  - ]:          2 :             if (simple)
     874                 :          2 :                 return PyDict_Copy(object);
     875                 :            :             /* Fall through to general case */
     876                 :            :         }
     877         [ +  + ]:          2 :         else if (Element_CheckExact(object)) {
     878                 :          1 :             return _elementtree_Element___deepcopy___impl(
     879                 :            :                 (ElementObject *)object, memo);
     880                 :            :         }
     881                 :            :     }
     882                 :            : 
     883                 :            :     /* General case */
     884                 :          2 :     st = ET_STATE_GLOBAL;
     885         [ -  + ]:          2 :     if (!st->deepcopy_obj) {
     886                 :          0 :         PyErr_SetString(PyExc_RuntimeError,
     887                 :            :                         "deepcopy helper not found");
     888                 :          0 :         return NULL;
     889                 :            :     }
     890                 :            : 
     891                 :          2 :     stack[0] = object;
     892                 :          2 :     stack[1] = memo;
     893                 :          2 :     return _PyObject_FastCall(st->deepcopy_obj, stack, 2);
     894                 :            : }
     895                 :            : 
     896                 :            : 
     897                 :            : /*[clinic input]
     898                 :            : _elementtree.Element.__sizeof__ -> Py_ssize_t
     899                 :            : 
     900                 :            : [clinic start generated code]*/
     901                 :            : 
     902                 :            : static Py_ssize_t
     903                 :          3 : _elementtree_Element___sizeof___impl(ElementObject *self)
     904                 :            : /*[clinic end generated code: output=bf73867721008000 input=70f4b323d55a17c1]*/
     905                 :            : {
     906                 :          3 :     Py_ssize_t result = _PyObject_SIZE(Py_TYPE(self));
     907         [ +  + ]:          3 :     if (self->extra) {
     908                 :          2 :         result += sizeof(ElementObjectExtra);
     909         [ +  + ]:          2 :         if (self->extra->children != self->extra->_children)
     910                 :          1 :             result += sizeof(PyObject*) * self->extra->allocated;
     911                 :            :     }
     912                 :          3 :     return result;
     913                 :            : }
     914                 :            : 
     915                 :            : /* dict keys for getstate/setstate. */
     916                 :            : #define PICKLED_TAG "tag"
     917                 :            : #define PICKLED_CHILDREN "_children"
     918                 :            : #define PICKLED_ATTRIB "attrib"
     919                 :            : #define PICKLED_TAIL "tail"
     920                 :            : #define PICKLED_TEXT "text"
     921                 :            : 
     922                 :            : /* __getstate__ returns a fabricated instance dict as in the pure-Python
     923                 :            :  * Element implementation, for interoperability/interchangeability.  This
     924                 :            :  * makes the pure-Python implementation details an API, but (a) there aren't
     925                 :            :  * any unnecessary structures there; and (b) it buys compatibility with 3.2
     926                 :            :  * pickles.  See issue #16076.
     927                 :            :  */
     928                 :            : /*[clinic input]
     929                 :            : _elementtree.Element.__getstate__
     930                 :            : 
     931                 :            : [clinic start generated code]*/
     932                 :            : 
     933                 :            : static PyObject *
     934                 :         56 : _elementtree_Element___getstate___impl(ElementObject *self)
     935                 :            : /*[clinic end generated code: output=37279aeeb6bb5b04 input=f0d16d7ec2f7adc1]*/
     936                 :            : {
     937                 :            :     Py_ssize_t i;
     938                 :            :     PyObject *children, *attrib;
     939                 :            : 
     940                 :            :     /* Build a list of children. */
     941         [ +  + ]:         56 :     children = PyList_New(self->extra ? self->extra->length : 0);
     942         [ -  + ]:         56 :     if (!children)
     943                 :          0 :         return NULL;
     944         [ +  + ]:         96 :     for (i = 0; i < PyList_GET_SIZE(children); i++) {
     945                 :         40 :         PyObject *child = self->extra->children[i];
     946                 :         40 :         Py_INCREF(child);
     947                 :         40 :         PyList_SET_ITEM(children, i, child);
     948                 :            :     }
     949                 :            : 
     950   [ +  +  +  + ]:         56 :     if (self->extra && self->extra->attrib) {
     951                 :         16 :         attrib = self->extra->attrib;
     952                 :         16 :         Py_INCREF(attrib);
     953                 :            :     }
     954                 :            :     else {
     955                 :         40 :         attrib = PyDict_New();
     956         [ -  + ]:         40 :         if (!attrib) {
     957                 :          0 :             Py_DECREF(children);
     958                 :          0 :             return NULL;
     959                 :            :         }
     960                 :            :     }
     961                 :            : 
     962                 :         56 :     return Py_BuildValue("{sOsNsNsOsO}",
     963                 :            :                          PICKLED_TAG, self->tag,
     964                 :            :                          PICKLED_CHILDREN, children,
     965                 :            :                          PICKLED_ATTRIB, attrib,
     966                 :         56 :                          PICKLED_TEXT, JOIN_OBJ(self->text),
     967                 :         56 :                          PICKLED_TAIL, JOIN_OBJ(self->tail));
     968                 :            : }
     969                 :            : 
     970                 :            : static PyObject *
     971                 :        151 : element_setstate_from_attributes(ElementObject *self,
     972                 :            :                                  PyObject *tag,
     973                 :            :                                  PyObject *attrib,
     974                 :            :                                  PyObject *text,
     975                 :            :                                  PyObject *tail,
     976                 :            :                                  PyObject *children)
     977                 :            : {
     978                 :            :     Py_ssize_t i, nchildren;
     979                 :        151 :     ElementObjectExtra *oldextra = NULL;
     980                 :            : 
     981         [ -  + ]:        151 :     if (!tag) {
     982                 :          0 :         PyErr_SetString(PyExc_TypeError, "tag may not be NULL");
     983                 :          0 :         return NULL;
     984                 :            :     }
     985                 :            : 
     986                 :        151 :     Py_INCREF(tag);
     987                 :        151 :     Py_XSETREF(self->tag, tag);
     988                 :            : 
     989         [ +  + ]:        151 :     text = text ? JOIN_SET(text, PyList_CheckExact(text)) : Py_None;
     990                 :        151 :     Py_INCREF(JOIN_OBJ(text));
     991                 :        151 :     _set_joined_ptr(&self->text, text);
     992                 :            : 
     993         [ +  + ]:        151 :     tail = tail ? JOIN_SET(tail, PyList_CheckExact(tail)) : Py_None;
     994                 :        151 :     Py_INCREF(JOIN_OBJ(tail));
     995                 :        151 :     _set_joined_ptr(&self->tail, tail);
     996                 :            : 
     997                 :            :     /* Handle ATTRIB and CHILDREN. */
     998   [ +  +  +  - ]:        151 :     if (!children && !attrib) {
     999                 :          2 :         Py_RETURN_NONE;
    1000                 :            :     }
    1001                 :            : 
    1002                 :            :     /* Compute 'nchildren'. */
    1003         [ +  - ]:        149 :     if (children) {
    1004         [ -  + ]:        149 :         if (!PyList_Check(children)) {
    1005                 :          0 :             PyErr_SetString(PyExc_TypeError, "'_children' is not a list");
    1006                 :          0 :             return NULL;
    1007                 :            :         }
    1008                 :        149 :         nchildren = PyList_GET_SIZE(children);
    1009                 :            : 
    1010                 :            :         /* (Re-)allocate 'extra'.
    1011                 :            :            Avoid DECREFs calling into this code again (cycles, etc.)
    1012                 :            :          */
    1013                 :        149 :         oldextra = self->extra;
    1014                 :        149 :         self->extra = NULL;
    1015         [ -  + ]:        149 :         if (element_resize(self, nchildren)) {
    1016                 :            :             assert(!self->extra || !self->extra->length);
    1017                 :          0 :             clear_extra(self);
    1018                 :          0 :             self->extra = oldextra;
    1019                 :          0 :             return NULL;
    1020                 :            :         }
    1021                 :            :         assert(self->extra);
    1022                 :            :         assert(self->extra->allocated >= nchildren);
    1023         [ +  + ]:        149 :         if (oldextra) {
    1024                 :            :             assert(self->extra->attrib == NULL);
    1025                 :        100 :             self->extra->attrib = oldextra->attrib;
    1026                 :        100 :             oldextra->attrib = NULL;
    1027                 :            :         }
    1028                 :            : 
    1029                 :            :         /* Copy children */
    1030         [ +  + ]:        281 :         for (i = 0; i < nchildren; i++) {
    1031                 :        133 :             PyObject *child = PyList_GET_ITEM(children, i);
    1032         [ +  + ]:        133 :             if (!Element_Check(child)) {
    1033                 :          1 :                 raise_type_error(child);
    1034                 :          1 :                 self->extra->length = i;
    1035                 :          1 :                 dealloc_extra(oldextra);
    1036                 :          1 :                 return NULL;
    1037                 :            :             }
    1038                 :        132 :             Py_INCREF(child);
    1039                 :        132 :             self->extra->children[i] = child;
    1040                 :            :         }
    1041                 :            : 
    1042                 :            :         assert(!self->extra->length);
    1043                 :        148 :         self->extra->length = nchildren;
    1044                 :            :     }
    1045                 :            :     else {
    1046         [ #  # ]:          0 :         if (element_resize(self, 0)) {
    1047                 :          0 :             return NULL;
    1048                 :            :         }
    1049                 :            :     }
    1050                 :            : 
    1051                 :            :     /* Stash attrib. */
    1052                 :        148 :     Py_XINCREF(attrib);
    1053                 :        148 :     Py_XSETREF(self->extra->attrib, attrib);
    1054                 :        148 :     dealloc_extra(oldextra);
    1055                 :            : 
    1056                 :        148 :     Py_RETURN_NONE;
    1057                 :            : }
    1058                 :            : 
    1059                 :            : /* __setstate__ for Element instance from the Python implementation.
    1060                 :            :  * 'state' should be the instance dict.
    1061                 :            :  */
    1062                 :            : 
    1063                 :            : static PyObject *
    1064                 :        151 : element_setstate_from_Python(ElementObject *self, PyObject *state)
    1065                 :            : {
    1066                 :            :     static char *kwlist[] = {PICKLED_TAG, PICKLED_ATTRIB, PICKLED_TEXT,
    1067                 :            :                              PICKLED_TAIL, PICKLED_CHILDREN, 0};
    1068                 :            :     PyObject *args;
    1069                 :            :     PyObject *tag, *attrib, *text, *tail, *children;
    1070                 :            :     PyObject *retval;
    1071                 :            : 
    1072                 :        151 :     tag = attrib = text = tail = children = NULL;
    1073                 :        151 :     args = PyTuple_New(0);
    1074         [ -  + ]:        151 :     if (!args)
    1075                 :          0 :         return NULL;
    1076                 :            : 
    1077         [ +  - ]:        151 :     if (PyArg_ParseTupleAndKeywords(args, state, "|$OOOOO", kwlist, &tag,
    1078                 :            :                                     &attrib, &text, &tail, &children))
    1079                 :        151 :         retval = element_setstate_from_attributes(self, tag, attrib, text,
    1080                 :            :                                                   tail, children);
    1081                 :            :     else
    1082                 :          0 :         retval = NULL;
    1083                 :            : 
    1084                 :        151 :     Py_DECREF(args);
    1085                 :        151 :     return retval;
    1086                 :            : }
    1087                 :            : 
    1088                 :            : /*[clinic input]
    1089                 :            : _elementtree.Element.__setstate__
    1090                 :            : 
    1091                 :            :     state: object
    1092                 :            :     /
    1093                 :            : 
    1094                 :            : [clinic start generated code]*/
    1095                 :            : 
    1096                 :            : static PyObject *
    1097                 :        151 : _elementtree_Element___setstate__(ElementObject *self, PyObject *state)
    1098                 :            : /*[clinic end generated code: output=ea28bf3491b1f75e input=aaf80abea7c1e3b9]*/
    1099                 :            : {
    1100         [ -  + ]:        151 :     if (!PyDict_CheckExact(state)) {
    1101                 :          0 :         PyErr_Format(PyExc_TypeError,
    1102                 :            :                      "Don't know how to unpickle \"%.200R\" as an Element",
    1103                 :            :                      state);
    1104                 :          0 :         return NULL;
    1105                 :            :     }
    1106                 :            :     else
    1107                 :        151 :         return element_setstate_from_Python(self, state);
    1108                 :            : }
    1109                 :            : 
    1110                 :            : LOCAL(int)
    1111                 :        820 : checkpath(PyObject* tag)
    1112                 :            : {
    1113                 :            :     Py_ssize_t i;
    1114                 :        820 :     int check = 1;
    1115                 :            : 
    1116                 :            :     /* check if a tag contains an xpath character */
    1117                 :            : 
    1118                 :            : #define PATHCHAR(ch) \
    1119                 :            :     (ch == '/' || ch == '*' || ch == '[' || ch == '@' || ch == '.')
    1120                 :            : 
    1121         [ +  - ]:        820 :     if (PyUnicode_Check(tag)) {
    1122                 :        820 :         const Py_ssize_t len = PyUnicode_GET_LENGTH(tag);
    1123                 :        820 :         const void *data = PyUnicode_DATA(tag);
    1124                 :        820 :         int kind = PyUnicode_KIND(tag);
    1125   [ +  +  +  +  :        845 :         if (len >= 3 && PyUnicode_READ(kind, data, 0) == '{' && (
                   +  + ]
    1126         [ +  + ]:         47 :                 PyUnicode_READ(kind, data, 1) == '}' || (
    1127         [ +  - ]:         26 :                 PyUnicode_READ(kind, data, 1) == '*' &&
    1128                 :          4 :                 PyUnicode_READ(kind, data, 2) == '}'))) {
    1129                 :            :             /* wildcard: '{}tag' or '{*}tag' */
    1130                 :          7 :             return 1;
    1131                 :            :         }
    1132         [ +  + ]:       1774 :         for (i = 0; i < len; i++) {
    1133                 :       1705 :             Py_UCS4 ch = PyUnicode_READ(kind, data, i);
    1134         [ +  + ]:       1705 :             if (ch == '{')
    1135                 :         18 :                 check = 0;
    1136         [ +  + ]:       1687 :             else if (ch == '}')
    1137                 :         18 :                 check = 1;
    1138   [ +  +  +  +  :       1669 :             else if (check && PATHCHAR(ch))
          +  +  +  -  +  
                -  +  + ]
    1139                 :        744 :                 return 1;
    1140                 :            :         }
    1141                 :         69 :         return 0;
    1142                 :            :     }
    1143         [ #  # ]:          0 :     if (PyBytes_Check(tag)) {
    1144                 :          0 :         const char *p = PyBytes_AS_STRING(tag);
    1145                 :          0 :         const Py_ssize_t len = PyBytes_GET_SIZE(tag);
    1146   [ #  #  #  # ]:          0 :         if (len >= 3 && p[0] == '{' && (
    1147   [ #  #  #  #  :          0 :                 p[1] == '}' || (p[1] == '*' && p[2] == '}'))) {
                   #  # ]
    1148                 :            :             /* wildcard: '{}tag' or '{*}tag' */
    1149                 :          0 :             return 1;
    1150                 :            :         }
    1151         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
    1152         [ #  # ]:          0 :             if (p[i] == '{')
    1153                 :          0 :                 check = 0;
    1154         [ #  # ]:          0 :             else if (p[i] == '}')
    1155                 :          0 :                 check = 1;
    1156   [ #  #  #  #  :          0 :             else if (check && PATHCHAR(p[i]))
          #  #  #  #  #  
                #  #  # ]
    1157                 :          0 :                 return 1;
    1158                 :            :         }
    1159                 :          0 :         return 0;
    1160                 :            :     }
    1161                 :            : 
    1162                 :          0 :     return 1; /* unknown type; might be path expression */
    1163                 :            : }
    1164                 :            : 
    1165                 :            : /*[clinic input]
    1166                 :            : _elementtree.Element.extend
    1167                 :            : 
    1168                 :            :     elements: object
    1169                 :            :     /
    1170                 :            : 
    1171                 :            : [clinic start generated code]*/
    1172                 :            : 
    1173                 :            : static PyObject *
    1174                 :         16 : _elementtree_Element_extend(ElementObject *self, PyObject *elements)
    1175                 :            : /*[clinic end generated code: output=f6e67fc2ff529191 input=807bc4f31c69f7c0]*/
    1176                 :            : {
    1177                 :            :     PyObject* seq;
    1178                 :            :     Py_ssize_t i;
    1179                 :            : 
    1180                 :         16 :     seq = PySequence_Fast(elements, "");
    1181         [ -  + ]:         16 :     if (!seq) {
    1182                 :          0 :         PyErr_Format(
    1183                 :            :             PyExc_TypeError,
    1184                 :          0 :             "expected sequence, not \"%.200s\"", Py_TYPE(elements)->tp_name
    1185                 :            :             );
    1186                 :          0 :         return NULL;
    1187                 :            :     }
    1188                 :            : 
    1189   [ +  -  +  + ]:         32 :     for (i = 0; i < PySequence_Fast_GET_SIZE(seq); i++) {
    1190         [ +  - ]:         19 :         PyObject* element = PySequence_Fast_GET_ITEM(seq, i);
    1191                 :         19 :         Py_INCREF(element);
    1192         [ +  + ]:         19 :         if (element_add_subelement(self, element) < 0) {
    1193                 :          3 :             Py_DECREF(seq);
    1194                 :          3 :             Py_DECREF(element);
    1195                 :          3 :             return NULL;
    1196                 :            :         }
    1197                 :         16 :         Py_DECREF(element);
    1198                 :            :     }
    1199                 :            : 
    1200                 :         13 :     Py_DECREF(seq);
    1201                 :            : 
    1202                 :         13 :     Py_RETURN_NONE;
    1203                 :            : }
    1204                 :            : 
    1205                 :            : /*[clinic input]
    1206                 :            : _elementtree.Element.find
    1207                 :            : 
    1208                 :            :     path: object
    1209                 :            :     namespaces: object = None
    1210                 :            : 
    1211                 :            : [clinic start generated code]*/
    1212                 :            : 
    1213                 :            : static PyObject *
    1214                 :        674 : _elementtree_Element_find_impl(ElementObject *self, PyObject *path,
    1215                 :            :                                PyObject *namespaces)
    1216                 :            : /*[clinic end generated code: output=41b43f0f0becafae input=359b6985f6489d2e]*/
    1217                 :            : {
    1218                 :            :     Py_ssize_t i;
    1219                 :        674 :     elementtreestate *st = ET_STATE_GLOBAL;
    1220                 :            : 
    1221   [ +  +  -  + ]:        674 :     if (checkpath(path) || namespaces != Py_None) {
    1222                 :            :         _Py_IDENTIFIER(find);
    1223                 :        655 :         return _PyObject_CallMethodIdObjArgs(
    1224                 :            :             st->elementpath_obj, &PyId_find, self, path, namespaces, NULL
    1225                 :            :             );
    1226                 :            :     }
    1227                 :            : 
    1228         [ +  + ]:         19 :     if (!self->extra)
    1229                 :          2 :         Py_RETURN_NONE;
    1230                 :            : 
    1231         [ +  + ]:         25 :     for (i = 0; i < self->extra->length; i++) {
    1232                 :         21 :         PyObject* item = self->extra->children[i];
    1233                 :            :         int rc;
    1234                 :            :         assert(Element_Check(item));
    1235                 :         21 :         Py_INCREF(item);
    1236                 :         21 :         rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ);
    1237         [ +  + ]:         21 :         if (rc > 0)
    1238                 :         12 :             return item;
    1239                 :          9 :         Py_DECREF(item);
    1240         [ +  + ]:          9 :         if (rc < 0)
    1241                 :          1 :             return NULL;
    1242                 :            :     }
    1243                 :            : 
    1244                 :          4 :     Py_RETURN_NONE;
    1245                 :            : }
    1246                 :            : 
    1247                 :            : /*[clinic input]
    1248                 :            : _elementtree.Element.findtext
    1249                 :            : 
    1250                 :            :     path: object
    1251                 :            :     default: object = None
    1252                 :            :     namespaces: object = None
    1253                 :            : 
    1254                 :            : [clinic start generated code]*/
    1255                 :            : 
    1256                 :            : static PyObject *
    1257                 :         15 : _elementtree_Element_findtext_impl(ElementObject *self, PyObject *path,
    1258                 :            :                                    PyObject *default_value,
    1259                 :            :                                    PyObject *namespaces)
    1260                 :            : /*[clinic end generated code: output=83b3ba4535d308d2 input=b53a85aa5aa2a916]*/
    1261                 :            : {
    1262                 :            :     Py_ssize_t i;
    1263                 :            :     _Py_IDENTIFIER(findtext);
    1264                 :         15 :     elementtreestate *st = ET_STATE_GLOBAL;
    1265                 :            : 
    1266   [ +  +  -  + ]:         15 :     if (checkpath(path) || namespaces != Py_None)
    1267                 :          5 :         return _PyObject_CallMethodIdObjArgs(
    1268                 :            :             st->elementpath_obj, &PyId_findtext,
    1269                 :            :             self, path, default_value, namespaces, NULL
    1270                 :            :             );
    1271                 :            : 
    1272         [ +  + ]:         10 :     if (!self->extra) {
    1273                 :          2 :         Py_INCREF(default_value);
    1274                 :          2 :         return default_value;
    1275                 :            :     }
    1276                 :            : 
    1277         [ +  + ]:         14 :     for (i = 0; i < self->extra->length; i++) {
    1278                 :         12 :         PyObject *item = self->extra->children[i];
    1279                 :            :         int rc;
    1280                 :            :         assert(Element_Check(item));
    1281                 :         12 :         Py_INCREF(item);
    1282                 :         12 :         rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ);
    1283         [ +  + ]:         12 :         if (rc > 0) {
    1284                 :          5 :             PyObject* text = element_get_text((ElementObject*)item);
    1285         [ +  + ]:          5 :             if (text == Py_None) {
    1286                 :          2 :                 Py_DECREF(item);
    1287                 :          2 :                 return PyUnicode_New(0, 0);
    1288                 :            :             }
    1289                 :          3 :             Py_XINCREF(text);
    1290                 :          3 :             Py_DECREF(item);
    1291                 :          3 :             return text;
    1292                 :            :         }
    1293                 :          7 :         Py_DECREF(item);
    1294         [ +  + ]:          7 :         if (rc < 0)
    1295                 :          1 :             return NULL;
    1296                 :            :     }
    1297                 :            : 
    1298                 :          2 :     Py_INCREF(default_value);
    1299                 :          2 :     return default_value;
    1300                 :            : }
    1301                 :            : 
    1302                 :            : /*[clinic input]
    1303                 :            : _elementtree.Element.findall
    1304                 :            : 
    1305                 :            :     path: object
    1306                 :            :     namespaces: object = None
    1307                 :            : 
    1308                 :            : [clinic start generated code]*/
    1309                 :            : 
    1310                 :            : static PyObject *
    1311                 :        131 : _elementtree_Element_findall_impl(ElementObject *self, PyObject *path,
    1312                 :            :                                   PyObject *namespaces)
    1313                 :            : /*[clinic end generated code: output=1a0bd9f5541b711d input=4d9e6505a638550c]*/
    1314                 :            : {
    1315                 :            :     Py_ssize_t i;
    1316                 :            :     PyObject* out;
    1317                 :        131 :     elementtreestate *st = ET_STATE_GLOBAL;
    1318                 :            : 
    1319   [ +  +  -  + ]:        131 :     if (checkpath(path) || namespaces != Py_None) {
    1320                 :            :         _Py_IDENTIFIER(findall);
    1321                 :         91 :         return _PyObject_CallMethodIdObjArgs(
    1322                 :            :             st->elementpath_obj, &PyId_findall, self, path, namespaces, NULL
    1323                 :            :             );
    1324                 :            :     }
    1325                 :            : 
    1326                 :         40 :     out = PyList_New(0);
    1327         [ -  + ]:         40 :     if (!out)
    1328                 :          0 :         return NULL;
    1329                 :            : 
    1330         [ +  + ]:         40 :     if (!self->extra)
    1331                 :          2 :         return out;
    1332                 :            : 
    1333         [ +  + ]:        143 :     for (i = 0; i < self->extra->length; i++) {
    1334                 :        106 :         PyObject* item = self->extra->children[i];
    1335                 :            :         int rc;
    1336                 :            :         assert(Element_Check(item));
    1337                 :        106 :         Py_INCREF(item);
    1338                 :        106 :         rc = PyObject_RichCompareBool(((ElementObject*)item)->tag, path, Py_EQ);
    1339   [ +  +  +  +  :        106 :         if (rc != 0 && (rc < 0 || PyList_Append(out, item) < 0)) {
                   -  + ]
    1340                 :          1 :             Py_DECREF(item);
    1341                 :          1 :             Py_DECREF(out);
    1342                 :          1 :             return NULL;
    1343                 :            :         }
    1344                 :        105 :         Py_DECREF(item);
    1345                 :            :     }
    1346                 :            : 
    1347                 :         37 :     return out;
    1348                 :            : }
    1349                 :            : 
    1350                 :            : /*[clinic input]
    1351                 :            : _elementtree.Element.iterfind
    1352                 :            : 
    1353                 :            :     path: object
    1354                 :            :     namespaces: object = None
    1355                 :            : 
    1356                 :            : [clinic start generated code]*/
    1357                 :            : 
    1358                 :            : static PyObject *
    1359                 :         11 : _elementtree_Element_iterfind_impl(ElementObject *self, PyObject *path,
    1360                 :            :                                    PyObject *namespaces)
    1361                 :            : /*[clinic end generated code: output=ecdd56d63b19d40f input=abb974e350fb65c7]*/
    1362                 :            : {
    1363                 :         11 :     PyObject* tag = path;
    1364                 :            :     _Py_IDENTIFIER(iterfind);
    1365                 :         11 :     elementtreestate *st = ET_STATE_GLOBAL;
    1366                 :            : 
    1367                 :         11 :     return _PyObject_CallMethodIdObjArgs(
    1368                 :            :         st->elementpath_obj, &PyId_iterfind, self, tag, namespaces, NULL);
    1369                 :            : }
    1370                 :            : 
    1371                 :            : /*[clinic input]
    1372                 :            : _elementtree.Element.get
    1373                 :            : 
    1374                 :            :     key: object
    1375                 :            :     default: object = None
    1376                 :            : 
    1377                 :            : [clinic start generated code]*/
    1378                 :            : 
    1379                 :            : static PyObject *
    1380                 :        128 : _elementtree_Element_get_impl(ElementObject *self, PyObject *key,
    1381                 :            :                               PyObject *default_value)
    1382                 :            : /*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/
    1383                 :            : {
    1384   [ +  +  +  + ]:        128 :     if (self->extra && self->extra->attrib) {
    1385                 :        117 :         PyObject *attrib = self->extra->attrib;
    1386                 :        117 :         Py_INCREF(attrib);
    1387                 :        117 :         PyObject *value = PyDict_GetItemWithError(attrib, key);
    1388                 :        117 :         Py_XINCREF(value);
    1389                 :        117 :         Py_DECREF(attrib);
    1390   [ +  +  -  + ]:        117 :         if (value != NULL || PyErr_Occurred()) {
    1391                 :         79 :             return value;
    1392                 :            :         }
    1393                 :            :     }
    1394                 :            : 
    1395                 :         49 :     Py_INCREF(default_value);
    1396                 :         49 :     return default_value;
    1397                 :            : }
    1398                 :            : 
    1399                 :            : static PyObject *
    1400                 :            : create_elementiter(ElementObject *self, PyObject *tag, int gettext);
    1401                 :            : 
    1402                 :            : 
    1403                 :            : /*[clinic input]
    1404                 :            : _elementtree.Element.iter
    1405                 :            : 
    1406                 :            :     tag: object = None
    1407                 :            : 
    1408                 :            : [clinic start generated code]*/
    1409                 :            : 
    1410                 :            : static PyObject *
    1411                 :        448 : _elementtree_Element_iter_impl(ElementObject *self, PyObject *tag)
    1412                 :            : /*[clinic end generated code: output=3f49f9a862941cc5 input=774d5b12e573aedd]*/
    1413                 :            : {
    1414         [ +  + ]:        448 :     if (PyUnicode_Check(tag)) {
    1415         [ -  + ]:         71 :         if (PyUnicode_READY(tag) < 0)
    1416                 :          0 :             return NULL;
    1417   [ +  +  +  + ]:         71 :         if (PyUnicode_GET_LENGTH(tag) == 1 && PyUnicode_READ_CHAR(tag, 0) == '*')
    1418                 :          8 :             tag = Py_None;
    1419                 :            :     }
    1420         [ -  + ]:        377 :     else if (PyBytes_Check(tag)) {
    1421   [ #  #  #  # ]:          0 :         if (PyBytes_GET_SIZE(tag) == 1 && *PyBytes_AS_STRING(tag) == '*')
    1422                 :          0 :             tag = Py_None;
    1423                 :            :     }
    1424                 :            : 
    1425                 :        448 :     return create_elementiter(self, tag, 0);
    1426                 :            : }
    1427                 :            : 
    1428                 :            : 
    1429                 :            : /*[clinic input]
    1430                 :            : _elementtree.Element.itertext
    1431                 :            : 
    1432                 :            : [clinic start generated code]*/
    1433                 :            : 
    1434                 :            : static PyObject *
    1435                 :         80 : _elementtree_Element_itertext_impl(ElementObject *self)
    1436                 :            : /*[clinic end generated code: output=5fa34b2fbcb65df6 input=af8f0e42cb239c89]*/
    1437                 :            : {
    1438                 :         80 :     return create_elementiter(self, Py_None, 1);
    1439                 :            : }
    1440                 :            : 
    1441                 :            : 
    1442                 :            : static PyObject*
    1443                 :       3902 : element_getitem(PyObject* self_, Py_ssize_t index)
    1444                 :            : {
    1445                 :       3902 :     ElementObject* self = (ElementObject*) self_;
    1446                 :            : 
    1447   [ +  +  +  +  :       3902 :     if (!self->extra || index < 0 || index >= self->extra->length) {
                   +  + ]
    1448                 :       1225 :         PyErr_SetString(
    1449                 :            :             PyExc_IndexError,
    1450                 :            :             "child index out of range"
    1451                 :            :             );
    1452                 :       1225 :         return NULL;
    1453                 :            :     }
    1454                 :            : 
    1455                 :       2677 :     Py_INCREF(self->extra->children[index]);
    1456                 :       2677 :     return self->extra->children[index];
    1457                 :            : }
    1458                 :            : 
    1459                 :            : /*[clinic input]
    1460                 :            : _elementtree.Element.insert
    1461                 :            : 
    1462                 :            :     index: Py_ssize_t
    1463                 :            :     subelement: object(subclass_of='&Element_Type')
    1464                 :            :     /
    1465                 :            : 
    1466                 :            : [clinic start generated code]*/
    1467                 :            : 
    1468                 :            : static PyObject *
    1469                 :         15 : _elementtree_Element_insert_impl(ElementObject *self, Py_ssize_t index,
    1470                 :            :                                  PyObject *subelement)
    1471                 :            : /*[clinic end generated code: output=990adfef4d424c0b input=cd6fbfcdab52d7a8]*/
    1472                 :            : {
    1473                 :            :     Py_ssize_t i;
    1474                 :            : 
    1475         [ +  + ]:         15 :     if (!self->extra) {
    1476         [ -  + ]:          1 :         if (create_extra(self, NULL) < 0)
    1477                 :          0 :             return NULL;
    1478                 :            :     }
    1479                 :            : 
    1480         [ +  + ]:         15 :     if (index < 0) {
    1481                 :          1 :         index += self->extra->length;
    1482         [ -  + ]:          1 :         if (index < 0)
    1483                 :          0 :             index = 0;
    1484                 :            :     }
    1485         [ -  + ]:         15 :     if (index > self->extra->length)
    1486                 :          0 :         index = self->extra->length;
    1487                 :            : 
    1488         [ -  + ]:         15 :     if (element_resize(self, 1) < 0)
    1489                 :          0 :         return NULL;
    1490                 :            : 
    1491         [ +  + ]:         66 :     for (i = self->extra->length; i > index; i--)
    1492                 :         51 :         self->extra->children[i] = self->extra->children[i-1];
    1493                 :            : 
    1494                 :         15 :     Py_INCREF(subelement);
    1495                 :         15 :     self->extra->children[index] = subelement;
    1496                 :            : 
    1497                 :         15 :     self->extra->length++;
    1498                 :            : 
    1499                 :         15 :     Py_RETURN_NONE;
    1500                 :            : }
    1501                 :            : 
    1502                 :            : /*[clinic input]
    1503                 :            : _elementtree.Element.items
    1504                 :            : 
    1505                 :            : [clinic start generated code]*/
    1506                 :            : 
    1507                 :            : static PyObject *
    1508                 :        994 : _elementtree_Element_items_impl(ElementObject *self)
    1509                 :            : /*[clinic end generated code: output=6db2c778ce3f5a4d input=adbe09aaea474447]*/
    1510                 :            : {
    1511   [ +  +  +  + ]:        994 :     if (!self->extra || !self->extra->attrib)
    1512                 :        875 :         return PyList_New(0);
    1513                 :            : 
    1514                 :        119 :     return PyDict_Items(self->extra->attrib);
    1515                 :            : }
    1516                 :            : 
    1517                 :            : /*[clinic input]
    1518                 :            : _elementtree.Element.keys
    1519                 :            : 
    1520                 :            : [clinic start generated code]*/
    1521                 :            : 
    1522                 :            : static PyObject *
    1523                 :          1 : _elementtree_Element_keys_impl(ElementObject *self)
    1524                 :            : /*[clinic end generated code: output=bc5bfabbf20eeb3c input=f02caf5b496b5b0b]*/
    1525                 :            : {
    1526   [ +  -  -  + ]:          1 :     if (!self->extra || !self->extra->attrib)
    1527                 :          0 :         return PyList_New(0);
    1528                 :            : 
    1529                 :          1 :     return PyDict_Keys(self->extra->attrib);
    1530                 :            : }
    1531                 :            : 
    1532                 :            : static Py_ssize_t
    1533                 :        530 : element_length(ElementObject* self)
    1534                 :            : {
    1535         [ +  + ]:        530 :     if (!self->extra)
    1536                 :        208 :         return 0;
    1537                 :            : 
    1538                 :        322 :     return self->extra->length;
    1539                 :            : }
    1540                 :            : 
    1541                 :            : /*[clinic input]
    1542                 :            : _elementtree.Element.makeelement
    1543                 :            : 
    1544                 :            :     tag: object
    1545                 :            :     attrib: object(subclass_of='&PyDict_Type')
    1546                 :            :     /
    1547                 :            : 
    1548                 :            : [clinic start generated code]*/
    1549                 :            : 
    1550                 :            : static PyObject *
    1551                 :          1 : _elementtree_Element_makeelement_impl(ElementObject *self, PyObject *tag,
    1552                 :            :                                       PyObject *attrib)
    1553                 :            : /*[clinic end generated code: output=4109832d5bb789ef input=2279d974529c3861]*/
    1554                 :            : {
    1555                 :            :     PyObject* elem;
    1556                 :            : 
    1557                 :          1 :     attrib = PyDict_Copy(attrib);
    1558         [ -  + ]:          1 :     if (!attrib)
    1559                 :          0 :         return NULL;
    1560                 :            : 
    1561                 :          1 :     elem = create_new_element(tag, attrib);
    1562                 :            : 
    1563                 :          1 :     Py_DECREF(attrib);
    1564                 :            : 
    1565                 :          1 :     return elem;
    1566                 :            : }
    1567                 :            : 
    1568                 :            : /*[clinic input]
    1569                 :            : _elementtree.Element.remove
    1570                 :            : 
    1571                 :            :     subelement: object(subclass_of='&Element_Type')
    1572                 :            :     /
    1573                 :            : 
    1574                 :            : [clinic start generated code]*/
    1575                 :            : 
    1576                 :            : static PyObject *
    1577                 :          9 : _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement)
    1578                 :            : /*[clinic end generated code: output=38fe6c07d6d87d1f input=d52fc28ededc0bd8]*/
    1579                 :            : {
    1580                 :            :     Py_ssize_t i;
    1581                 :            :     int rc;
    1582                 :            :     PyObject *found;
    1583                 :            : 
    1584         [ -  + ]:          9 :     if (!self->extra) {
    1585                 :            :         /* element has no children, so raise exception */
    1586                 :          0 :         PyErr_SetString(
    1587                 :            :             PyExc_ValueError,
    1588                 :            :             "list.remove(x): x not in list"
    1589                 :            :             );
    1590                 :          0 :         return NULL;
    1591                 :            :     }
    1592                 :            : 
    1593         [ +  + ]:         14 :     for (i = 0; i < self->extra->length; i++) {
    1594         [ +  + ]:         11 :         if (self->extra->children[i] == subelement)
    1595                 :          6 :             break;
    1596                 :          5 :         rc = PyObject_RichCompareBool(self->extra->children[i], subelement, Py_EQ);
    1597         [ -  + ]:          5 :         if (rc > 0)
    1598                 :          0 :             break;
    1599         [ -  + ]:          5 :         if (rc < 0)
    1600                 :          0 :             return NULL;
    1601                 :            :     }
    1602                 :            : 
    1603         [ +  + ]:          9 :     if (i >= self->extra->length) {
    1604                 :            :         /* subelement is not in children, so raise exception */
    1605                 :          3 :         PyErr_SetString(
    1606                 :            :             PyExc_ValueError,
    1607                 :            :             "list.remove(x): x not in list"
    1608                 :            :             );
    1609                 :          3 :         return NULL;
    1610                 :            :     }
    1611                 :            : 
    1612                 :          6 :     found = self->extra->children[i];
    1613                 :            : 
    1614                 :          6 :     self->extra->length--;
    1615         [ +  + ]:          8 :     for (; i < self->extra->length; i++)
    1616                 :          2 :         self->extra->children[i] = self->extra->children[i+1];
    1617                 :            : 
    1618                 :          6 :     Py_DECREF(found);
    1619                 :          6 :     Py_RETURN_NONE;
    1620                 :            : }
    1621                 :            : 
    1622                 :            : static PyObject*
    1623                 :          3 : element_repr(ElementObject* self)
    1624                 :            : {
    1625                 :            :     int status;
    1626                 :            : 
    1627         [ -  + ]:          3 :     if (self->tag == NULL)
    1628                 :          0 :         return PyUnicode_FromFormat("<Element at %p>", self);
    1629                 :            : 
    1630                 :          3 :     status = Py_ReprEnter((PyObject *)self);
    1631         [ +  + ]:          3 :     if (status == 0) {
    1632                 :            :         PyObject *res;
    1633                 :          2 :         res = PyUnicode_FromFormat("<Element %R at %p>", self->tag, self);
    1634                 :          2 :         Py_ReprLeave((PyObject *)self);
    1635                 :          2 :         return res;
    1636                 :            :     }
    1637         [ +  - ]:          1 :     if (status > 0)
    1638                 :          1 :         PyErr_Format(PyExc_RuntimeError,
    1639                 :            :                      "reentrant call inside %s.__repr__",
    1640                 :          1 :                      Py_TYPE(self)->tp_name);
    1641                 :          1 :     return NULL;
    1642                 :            : }
    1643                 :            : 
    1644                 :            : /*[clinic input]
    1645                 :            : _elementtree.Element.set
    1646                 :            : 
    1647                 :            :     key: object
    1648                 :            :     value: object
    1649                 :            :     /
    1650                 :            : 
    1651                 :            : [clinic start generated code]*/
    1652                 :            : 
    1653                 :            : static PyObject *
    1654                 :         18 : _elementtree_Element_set_impl(ElementObject *self, PyObject *key,
    1655                 :            :                               PyObject *value)
    1656                 :            : /*[clinic end generated code: output=fb938806be3c5656 input=1efe90f7d82b3fe9]*/
    1657                 :            : {
    1658                 :            :     PyObject* attrib;
    1659                 :            : 
    1660         [ +  + ]:         18 :     if (!self->extra) {
    1661         [ -  + ]:         14 :         if (create_extra(self, NULL) < 0)
    1662                 :          0 :             return NULL;
    1663                 :            :     }
    1664                 :            : 
    1665                 :         18 :     attrib = element_get_attrib(self);
    1666         [ -  + ]:         18 :     if (!attrib)
    1667                 :          0 :         return NULL;
    1668                 :            : 
    1669         [ -  + ]:         18 :     if (PyDict_SetItem(attrib, key, value) < 0)
    1670                 :          0 :         return NULL;
    1671                 :            : 
    1672                 :         18 :     Py_RETURN_NONE;
    1673                 :            : }
    1674                 :            : 
    1675                 :            : static int
    1676                 :         25 : element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item)
    1677                 :            : {
    1678                 :         25 :     ElementObject* self = (ElementObject*) self_;
    1679                 :            :     Py_ssize_t i;
    1680                 :            :     PyObject* old;
    1681                 :            : 
    1682   [ +  -  +  +  :         25 :     if (!self->extra || index < 0 || index >= self->extra->length) {
                   +  + ]
    1683                 :          2 :         PyErr_SetString(
    1684                 :            :             PyExc_IndexError,
    1685                 :            :             "child assignment index out of range");
    1686                 :          2 :         return -1;
    1687                 :            :     }
    1688                 :            : 
    1689                 :         23 :     old = self->extra->children[index];
    1690                 :            : 
    1691         [ +  + ]:         23 :     if (item) {
    1692         [ +  + ]:         19 :         if (!Element_Check(item)) {
    1693                 :          1 :             raise_type_error(item);
    1694                 :          1 :             return -1;
    1695                 :            :         }
    1696                 :         18 :         Py_INCREF(item);
    1697                 :         18 :         self->extra->children[index] = item;
    1698                 :            :     } else {
    1699                 :          4 :         self->extra->length--;
    1700         [ -  + ]:          4 :         for (i = index; i < self->extra->length; i++)
    1701                 :          0 :             self->extra->children[i] = self->extra->children[i+1];
    1702                 :            :     }
    1703                 :            : 
    1704                 :         22 :     Py_DECREF(old);
    1705                 :            : 
    1706                 :         22 :     return 0;
    1707                 :            : }
    1708                 :            : 
    1709                 :            : static PyObject*
    1710                 :        155 : element_subscr(PyObject* self_, PyObject* item)
    1711                 :            : {
    1712                 :        155 :     ElementObject* self = (ElementObject*) self_;
    1713                 :            : 
    1714         [ +  + ]:        155 :     if (PyIndex_Check(item)) {
    1715                 :        132 :         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
    1716                 :            : 
    1717   [ +  +  -  + ]:        132 :         if (i == -1 && PyErr_Occurred()) {
    1718                 :          0 :             return NULL;
    1719                 :            :         }
    1720   [ +  +  +  - ]:        132 :         if (i < 0 && self->extra)
    1721                 :          3 :             i += self->extra->length;
    1722                 :        132 :         return element_getitem(self_, i);
    1723                 :            :     }
    1724         [ +  - ]:         23 :     else if (PySlice_Check(item)) {
    1725                 :            :         Py_ssize_t start, stop, step, slicelen, i;
    1726                 :            :         size_t cur;
    1727                 :            :         PyObject* list;
    1728                 :            : 
    1729         [ -  + ]:         23 :         if (!self->extra)
    1730                 :          0 :             return PyList_New(0);
    1731                 :            : 
    1732         [ -  + ]:         23 :         if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
    1733                 :          0 :             return NULL;
    1734                 :            :         }
    1735                 :         23 :         slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
    1736                 :            :                                          step);
    1737                 :            : 
    1738         [ +  + ]:         23 :         if (slicelen <= 0)
    1739                 :          2 :             return PyList_New(0);
    1740                 :            :         else {
    1741                 :         21 :             list = PyList_New(slicelen);
    1742         [ -  + ]:         21 :             if (!list)
    1743                 :          0 :                 return NULL;
    1744                 :            : 
    1745         [ +  + ]:         67 :             for (cur = start, i = 0; i < slicelen;
    1746                 :         46 :                  cur += step, i++) {
    1747                 :         46 :                 PyObject* item = self->extra->children[cur];
    1748                 :         46 :                 Py_INCREF(item);
    1749                 :         46 :                 PyList_SET_ITEM(list, i, item);
    1750                 :            :             }
    1751                 :            : 
    1752                 :         21 :             return list;
    1753                 :            :         }
    1754                 :            :     }
    1755                 :            :     else {
    1756                 :          0 :         PyErr_SetString(PyExc_TypeError,
    1757                 :            :                 "element indices must be integers");
    1758                 :          0 :         return NULL;
    1759                 :            :     }
    1760                 :            : }
    1761                 :            : 
    1762                 :            : static int
    1763                 :         66 : element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
    1764                 :            : {
    1765                 :         66 :     ElementObject* self = (ElementObject*) self_;
    1766                 :            : 
    1767         [ +  + ]:         66 :     if (PyIndex_Check(item)) {
    1768                 :         25 :         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
    1769                 :            : 
    1770   [ -  +  -  - ]:         25 :         if (i == -1 && PyErr_Occurred()) {
    1771                 :          0 :             return -1;
    1772                 :            :         }
    1773   [ +  +  +  - ]:         25 :         if (i < 0 && self->extra)
    1774                 :          2 :             i += self->extra->length;
    1775                 :         25 :         return element_setitem(self_, i, value);
    1776                 :            :     }
    1777         [ +  - ]:         41 :     else if (PySlice_Check(item)) {
    1778                 :            :         Py_ssize_t start, stop, step, slicelen, newlen, i;
    1779                 :            :         size_t cur;
    1780                 :            : 
    1781                 :         41 :         PyObject* recycle = NULL;
    1782                 :            :         PyObject* seq;
    1783                 :            : 
    1784         [ -  + ]:         41 :         if (!self->extra) {
    1785         [ #  # ]:          0 :             if (create_extra(self, NULL) < 0)
    1786                 :          0 :                 return -1;
    1787                 :            :         }
    1788                 :            : 
    1789         [ -  + ]:         41 :         if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
    1790                 :          0 :             return -1;
    1791                 :            :         }
    1792                 :         41 :         slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
    1793                 :            :                                          step);
    1794                 :            : 
    1795         [ +  + ]:         41 :         if (value == NULL) {
    1796                 :            :             /* Delete slice */
    1797                 :            :             size_t cur;
    1798                 :            :             Py_ssize_t i;
    1799                 :            : 
    1800         [ -  + ]:         15 :             if (slicelen <= 0)
    1801                 :          0 :                 return 0;
    1802                 :            : 
    1803                 :            :             /* Since we're deleting, the direction of the range doesn't matter,
    1804                 :            :              * so for simplicity make it always ascending.
    1805                 :            :             */
    1806         [ +  + ]:         15 :             if (step < 0) {
    1807                 :          2 :                 stop = start + 1;
    1808                 :          2 :                 start = stop + step * (slicelen - 1) - 1;
    1809                 :          2 :                 step = -step;
    1810                 :            :             }
    1811                 :            : 
    1812                 :            :             assert((size_t)slicelen <= SIZE_MAX / sizeof(PyObject *));
    1813                 :            : 
    1814                 :            :             /* recycle is a list that will contain all the children
    1815                 :            :              * scheduled for removal.
    1816                 :            :             */
    1817         [ -  + ]:         15 :             if (!(recycle = PyList_New(slicelen))) {
    1818                 :          0 :                 return -1;
    1819                 :            :             }
    1820                 :            : 
    1821                 :            :             /* This loop walks over all the children that have to be deleted,
    1822                 :            :              * with cur pointing at them. num_moved is the amount of children
    1823                 :            :              * until the next deleted child that have to be "shifted down" to
    1824                 :            :              * occupy the deleted's places.
    1825                 :            :              * Note that in the ith iteration, shifting is done i+i places down
    1826                 :            :              * because i children were already removed.
    1827                 :            :             */
    1828         [ +  + ]:         39 :             for (cur = start, i = 0; cur < (size_t)stop; cur += step, ++i) {
    1829                 :            :                 /* Compute how many children have to be moved, clipping at the
    1830                 :            :                  * list end.
    1831                 :            :                 */
    1832                 :         24 :                 Py_ssize_t num_moved = step - 1;
    1833         [ +  + ]:         24 :                 if (cur + step >= (size_t)self->extra->length) {
    1834                 :         12 :                     num_moved = self->extra->length - cur - 1;
    1835                 :            :                 }
    1836                 :            : 
    1837                 :         24 :                 PyList_SET_ITEM(recycle, i, self->extra->children[cur]);
    1838                 :            : 
    1839                 :         24 :                 memmove(
    1840                 :         24 :                     self->extra->children + cur - i,
    1841                 :         24 :                     self->extra->children + cur + 1,
    1842                 :            :                     num_moved * sizeof(PyObject *));
    1843                 :            :             }
    1844                 :            : 
    1845                 :            :             /* Leftover "tail" after the last removed child */
    1846                 :         15 :             cur = start + (size_t)slicelen * step;
    1847         [ +  + ]:         15 :             if (cur < (size_t)self->extra->length) {
    1848                 :          3 :                 memmove(
    1849                 :          3 :                     self->extra->children + cur - slicelen,
    1850                 :          3 :                     self->extra->children + cur,
    1851                 :          3 :                     (self->extra->length - cur) * sizeof(PyObject *));
    1852                 :            :             }
    1853                 :            : 
    1854                 :         15 :             self->extra->length -= slicelen;
    1855                 :            : 
    1856                 :            :             /* Discard the recycle list with all the deleted sub-elements */
    1857                 :         15 :             Py_DECREF(recycle);
    1858                 :         15 :             return 0;
    1859                 :            :         }
    1860                 :            : 
    1861                 :            :         /* A new slice is actually being assigned */
    1862                 :         26 :         seq = PySequence_Fast(value, "");
    1863         [ -  + ]:         26 :         if (!seq) {
    1864                 :          0 :             PyErr_Format(
    1865                 :            :                 PyExc_TypeError,
    1866                 :          0 :                 "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name
    1867                 :            :                 );
    1868                 :          0 :             return -1;
    1869                 :            :         }
    1870         [ +  + ]:         26 :         newlen = PySequence_Fast_GET_SIZE(seq);
    1871                 :            : 
    1872   [ +  +  +  + ]:         26 :         if (step !=  1 && newlen != slicelen)
    1873                 :            :         {
    1874                 :          6 :             Py_DECREF(seq);
    1875                 :          6 :             PyErr_Format(PyExc_ValueError,
    1876                 :            :                 "attempt to assign sequence of size %zd "
    1877                 :            :                 "to extended slice of size %zd",
    1878                 :            :                 newlen, slicelen
    1879                 :            :                 );
    1880                 :          6 :             return -1;
    1881                 :            :         }
    1882                 :            : 
    1883                 :            :         /* Resize before creating the recycle bin, to prevent refleaks. */
    1884         [ +  + ]:         20 :         if (newlen > slicelen) {
    1885         [ -  + ]:          5 :             if (element_resize(self, newlen - slicelen) < 0) {
    1886                 :          0 :                 Py_DECREF(seq);
    1887                 :          0 :                 return -1;
    1888                 :            :             }
    1889                 :            :         }
    1890                 :            : 
    1891         [ +  + ]:         48 :         for (i = 0; i < newlen; i++) {
    1892         [ +  + ]:         29 :             PyObject *element = PySequence_Fast_GET_ITEM(seq, i);
    1893         [ +  + ]:         29 :             if (!Element_Check(element)) {
    1894                 :          1 :                 raise_type_error(element);
    1895                 :          1 :                 Py_DECREF(seq);
    1896                 :          1 :                 return -1;
    1897                 :            :             }
    1898                 :            :         }
    1899                 :            : 
    1900         [ +  + ]:         19 :         if (slicelen > 0) {
    1901                 :            :             /* to avoid recursive calls to this method (via decref), move
    1902                 :            :                old items to the recycle bin here, and get rid of them when
    1903                 :            :                we're done modifying the element */
    1904                 :         16 :             recycle = PyList_New(slicelen);
    1905         [ -  + ]:         16 :             if (!recycle) {
    1906                 :          0 :                 Py_DECREF(seq);
    1907                 :          0 :                 return -1;
    1908                 :            :             }
    1909         [ +  + ]:         49 :             for (cur = start, i = 0; i < slicelen;
    1910                 :         33 :                  cur += step, i++)
    1911                 :         33 :                 PyList_SET_ITEM(recycle, i, self->extra->children[cur]);
    1912                 :            :         }
    1913                 :            : 
    1914         [ +  + ]:         19 :         if (newlen < slicelen) {
    1915                 :            :             /* delete slice */
    1916         [ +  + ]:          4 :             for (i = stop; i < self->extra->length; i++)
    1917                 :          1 :                 self->extra->children[i + newlen - slicelen] = self->extra->children[i];
    1918         [ +  + ]:         16 :         } else if (newlen > slicelen) {
    1919                 :            :             /* insert slice */
    1920         [ +  + ]:          5 :             for (i = self->extra->length-1; i >= stop; i--)
    1921                 :          1 :                 self->extra->children[i + newlen - slicelen] = self->extra->children[i];
    1922                 :            :         }
    1923                 :            : 
    1924                 :            :         /* replace the slice */
    1925         [ +  + ]:         46 :         for (cur = start, i = 0; i < newlen;
    1926                 :         27 :              cur += step, i++) {
    1927         [ +  + ]:         27 :             PyObject* element = PySequence_Fast_GET_ITEM(seq, i);
    1928                 :         27 :             Py_INCREF(element);
    1929                 :         27 :             self->extra->children[cur] = element;
    1930                 :            :         }
    1931                 :            : 
    1932                 :         19 :         self->extra->length += newlen - slicelen;
    1933                 :            : 
    1934                 :         19 :         Py_DECREF(seq);
    1935                 :            : 
    1936                 :            :         /* discard the recycle bin, and everything in it */
    1937                 :         19 :         Py_XDECREF(recycle);
    1938                 :            : 
    1939                 :         19 :         return 0;
    1940                 :            :     }
    1941                 :            :     else {
    1942                 :          0 :         PyErr_SetString(PyExc_TypeError,
    1943                 :            :                 "element indices must be integers");
    1944                 :          0 :         return -1;
    1945                 :            :     }
    1946                 :            : }
    1947                 :            : 
    1948                 :            : static PyObject*
    1949                 :       3820 : element_tag_getter(ElementObject *self, void *closure)
    1950                 :            : {
    1951                 :       3820 :     PyObject *res = self->tag;
    1952                 :       3820 :     Py_INCREF(res);
    1953                 :       3820 :     return res;
    1954                 :            : }
    1955                 :            : 
    1956                 :            : static PyObject*
    1957                 :       1215 : element_text_getter(ElementObject *self, void *closure)
    1958                 :            : {
    1959                 :       1215 :     PyObject *res = element_get_text(self);
    1960                 :       1215 :     Py_XINCREF(res);
    1961                 :       1215 :     return res;
    1962                 :            : }
    1963                 :            : 
    1964                 :            : static PyObject*
    1965                 :        807 : element_tail_getter(ElementObject *self, void *closure)
    1966                 :            : {
    1967                 :        807 :     PyObject *res = element_get_tail(self);
    1968                 :        807 :     Py_XINCREF(res);
    1969                 :        807 :     return res;
    1970                 :            : }
    1971                 :            : 
    1972                 :            : static PyObject*
    1973                 :        135 : element_attrib_getter(ElementObject *self, void *closure)
    1974                 :            : {
    1975                 :            :     PyObject *res;
    1976         [ +  + ]:        135 :     if (!self->extra) {
    1977         [ -  + ]:         23 :         if (create_extra(self, NULL) < 0)
    1978                 :          0 :             return NULL;
    1979                 :            :     }
    1980                 :        135 :     res = element_get_attrib(self);
    1981                 :        135 :     Py_XINCREF(res);
    1982                 :        135 :     return res;
    1983                 :            : }
    1984                 :            : 
    1985                 :            : /* macro for setter validation */
    1986                 :            : #define _VALIDATE_ATTR_VALUE(V)                     \
    1987                 :            :     if ((V) == NULL) {                              \
    1988                 :            :         PyErr_SetString(                            \
    1989                 :            :             PyExc_AttributeError,                   \
    1990                 :            :             "can't delete element attribute");      \
    1991                 :            :         return -1;                                  \
    1992                 :            :     }
    1993                 :            : 
    1994                 :            : static int
    1995                 :          8 : element_tag_setter(ElementObject *self, PyObject *value, void *closure)
    1996                 :            : {
    1997         [ +  + ]:          8 :     _VALIDATE_ATTR_VALUE(value);
    1998                 :          7 :     Py_INCREF(value);
    1999                 :          7 :     Py_SETREF(self->tag, value);
    2000                 :          7 :     return 0;
    2001                 :            : }
    2002                 :            : 
    2003                 :            : static int
    2004                 :        125 : element_text_setter(ElementObject *self, PyObject *value, void *closure)
    2005                 :            : {
    2006         [ +  + ]:        125 :     _VALIDATE_ATTR_VALUE(value);
    2007                 :        123 :     Py_INCREF(value);
    2008                 :        123 :     _set_joined_ptr(&self->text, value);
    2009                 :        123 :     return 0;
    2010                 :            : }
    2011                 :            : 
    2012                 :            : static int
    2013                 :         80 : element_tail_setter(ElementObject *self, PyObject *value, void *closure)
    2014                 :            : {
    2015         [ +  + ]:         80 :     _VALIDATE_ATTR_VALUE(value);
    2016                 :         78 :     Py_INCREF(value);
    2017                 :         78 :     _set_joined_ptr(&self->tail, value);
    2018                 :         78 :     return 0;
    2019                 :            : }
    2020                 :            : 
    2021                 :            : static int
    2022                 :          6 : element_attrib_setter(ElementObject *self, PyObject *value, void *closure)
    2023                 :            : {
    2024         [ +  + ]:          6 :     _VALIDATE_ATTR_VALUE(value);
    2025         [ -  + ]:          4 :     if (!PyDict_Check(value)) {
    2026                 :          0 :         PyErr_Format(PyExc_TypeError,
    2027                 :            :                      "attrib must be dict, not %.200s",
    2028                 :          0 :                      Py_TYPE(value)->tp_name);
    2029                 :          0 :         return -1;
    2030                 :            :     }
    2031         [ -  + ]:          4 :     if (!self->extra) {
    2032         [ #  # ]:          0 :         if (create_extra(self, NULL) < 0)
    2033                 :          0 :             return -1;
    2034                 :            :     }
    2035                 :          4 :     Py_INCREF(value);
    2036                 :          4 :     Py_XSETREF(self->extra->attrib, value);
    2037                 :          4 :     return 0;
    2038                 :            : }
    2039                 :            : 
    2040                 :            : static PySequenceMethods element_as_sequence = {
    2041                 :            :     (lenfunc) element_length,
    2042                 :            :     0, /* sq_concat */
    2043                 :            :     0, /* sq_repeat */
    2044                 :            :     element_getitem,
    2045                 :            :     0,
    2046                 :            :     element_setitem,
    2047                 :            :     0,
    2048                 :            : };
    2049                 :            : 
    2050                 :            : /******************************* Element iterator ****************************/
    2051                 :            : 
    2052                 :            : /* ElementIterObject represents the iteration state over an XML element in
    2053                 :            :  * pre-order traversal. To keep track of which sub-element should be returned
    2054                 :            :  * next, a stack of parents is maintained. This is a standard stack-based
    2055                 :            :  * iterative pre-order traversal of a tree.
    2056                 :            :  * The stack is managed using a continuous array.
    2057                 :            :  * Each stack item contains the saved parent to which we should return after
    2058                 :            :  * the current one is exhausted, and the next child to examine in that parent.
    2059                 :            :  */
    2060                 :            : typedef struct ParentLocator_t {
    2061                 :            :     ElementObject *parent;
    2062                 :            :     Py_ssize_t child_index;
    2063                 :            : } ParentLocator;
    2064                 :            : 
    2065                 :            : typedef struct {
    2066                 :            :     PyObject_HEAD
    2067                 :            :     ParentLocator *parent_stack;
    2068                 :            :     Py_ssize_t parent_stack_used;
    2069                 :            :     Py_ssize_t parent_stack_size;
    2070                 :            :     ElementObject *root_element;
    2071                 :            :     PyObject *sought_tag;
    2072                 :            :     int gettext;
    2073                 :            : } ElementIterObject;
    2074                 :            : 
    2075                 :            : 
    2076                 :            : static void
    2077                 :        528 : elementiter_dealloc(ElementIterObject *it)
    2078                 :            : {
    2079                 :        528 :     Py_ssize_t i = it->parent_stack_used;
    2080                 :        528 :     it->parent_stack_used = 0;
    2081                 :            :     /* bpo-31095: UnTrack is needed before calling any callbacks */
    2082                 :        528 :     PyObject_GC_UnTrack(it);
    2083         [ +  + ]:        543 :     while (i--)
    2084                 :         15 :         Py_XDECREF(it->parent_stack[i].parent);
    2085                 :        528 :     PyMem_Free(it->parent_stack);
    2086                 :            : 
    2087                 :        528 :     Py_XDECREF(it->sought_tag);
    2088                 :        528 :     Py_XDECREF(it->root_element);
    2089                 :            : 
    2090                 :        528 :     PyObject_GC_Del(it);
    2091                 :        528 : }
    2092                 :            : 
    2093                 :            : static int
    2094                 :          2 : elementiter_traverse(ElementIterObject *it, visitproc visit, void *arg)
    2095                 :            : {
    2096                 :          2 :     Py_ssize_t i = it->parent_stack_used;
    2097         [ +  + ]:          6 :     while (i--)
    2098   [ +  -  -  + ]:          4 :         Py_VISIT(it->parent_stack[i].parent);
    2099                 :            : 
    2100   [ -  +  -  - ]:          2 :     Py_VISIT(it->root_element);
    2101   [ +  -  -  + ]:          2 :     Py_VISIT(it->sought_tag);
    2102                 :          2 :     return 0;
    2103                 :            : }
    2104                 :            : 
    2105                 :            : /* Helper function for elementiter_next. Add a new parent to the parent stack.
    2106                 :            :  */
    2107                 :            : static int
    2108                 :       1253 : parent_stack_push_new(ElementIterObject *it, ElementObject *parent)
    2109                 :            : {
    2110                 :            :     ParentLocator *item;
    2111                 :            : 
    2112         [ -  + ]:       1253 :     if (it->parent_stack_used >= it->parent_stack_size) {
    2113                 :          0 :         Py_ssize_t new_size = it->parent_stack_size * 2;  /* never overflow */
    2114                 :          0 :         ParentLocator *parent_stack = it->parent_stack;
    2115         [ #  # ]:          0 :         PyMem_Resize(parent_stack, ParentLocator, new_size);
    2116         [ #  # ]:          0 :         if (parent_stack == NULL)
    2117                 :          0 :             return -1;
    2118                 :          0 :         it->parent_stack = parent_stack;
    2119                 :          0 :         it->parent_stack_size = new_size;
    2120                 :            :     }
    2121                 :       1253 :     item = it->parent_stack + it->parent_stack_used++;
    2122                 :       1253 :     Py_INCREF(parent);
    2123                 :       1253 :     item->parent = parent;
    2124                 :       1253 :     item->child_index = 0;
    2125                 :       1253 :     return 0;
    2126                 :            : }
    2127                 :            : 
    2128                 :            : static PyObject *
    2129                 :       1431 : elementiter_next(ElementIterObject *it)
    2130                 :        307 : {
    2131                 :            :     /* Sub-element iterator.
    2132                 :            :      *
    2133                 :            :      * A short note on gettext: this function serves both the iter() and
    2134                 :            :      * itertext() methods to avoid code duplication. However, there are a few
    2135                 :            :      * small differences in the way these iterations work. Namely:
    2136                 :            :      *   - itertext() only yields text from nodes that have it, and continues
    2137                 :            :      *     iterating when a node doesn't have text (so it doesn't return any
    2138                 :            :      *     node like iter())
    2139                 :            :      *   - itertext() also has to handle tail, after finishing with all the
    2140                 :            :      *     children of a node.
    2141                 :            :      */
    2142                 :            :     int rc;
    2143                 :            :     ElementObject *elem;
    2144                 :            :     PyObject *text;
    2145                 :            : 
    2146                 :            :     while (1) {
    2147                 :            :         /* Handle the case reached in the beginning and end of iteration, where
    2148                 :            :          * the parent stack is empty. If root_element is NULL and we're here, the
    2149                 :            :          * iterator is exhausted.
    2150                 :            :          */
    2151         [ +  + ]:       3007 :         if (!it->parent_stack_used) {
    2152         [ +  + ]:       1042 :             if (!it->root_element) {
    2153                 :        516 :                 PyErr_SetNone(PyExc_StopIteration);
    2154                 :        516 :                 return NULL;
    2155                 :            :             }
    2156                 :            : 
    2157                 :        526 :             elem = it->root_element;  /* steals a reference */
    2158                 :        526 :             it->root_element = NULL;
    2159                 :            :         }
    2160                 :            :         else {
    2161                 :            :             /* See if there are children left to traverse in the current parent. If
    2162                 :            :              * yes, visit the next child. If not, pop the stack and try again.
    2163                 :            :              */
    2164                 :       1965 :             ParentLocator *item = &it->parent_stack[it->parent_stack_used - 1];
    2165                 :       1965 :             Py_ssize_t child_index = item->child_index;
    2166                 :            :             ElementObjectExtra *extra;
    2167                 :       1965 :             elem = item->parent;
    2168                 :       1965 :             extra = elem->extra;
    2169   [ +  +  +  + ]:       1965 :             if (!extra || child_index >= extra->length) {
    2170                 :       1238 :                 it->parent_stack_used--;
    2171                 :            :                 /* Note that extra condition on it->parent_stack_used here;
    2172                 :            :                  * this is because itertext() is supposed to only return *inner*
    2173                 :            :                  * text, not text following the element it began iteration with.
    2174                 :            :                  */
    2175   [ +  +  +  + ]:       1238 :                 if (it->gettext && it->parent_stack_used) {
    2176                 :          7 :                     text = element_get_tail(elem);
    2177                 :          7 :                     goto gettext;
    2178                 :            :                 }
    2179                 :       1231 :                 Py_DECREF(elem);
    2180                 :       1231 :                 continue;
    2181                 :            :             }
    2182                 :            : 
    2183                 :            :             assert(Element_Check(extra->children[child_index]));
    2184                 :        727 :             elem = (ElementObject *)extra->children[child_index];
    2185                 :        727 :             item->child_index++;
    2186                 :        727 :             Py_INCREF(elem);
    2187                 :            :         }
    2188                 :            : 
    2189         [ -  + ]:       1253 :         if (parent_stack_push_new(it, elem) < 0) {
    2190                 :          0 :             Py_DECREF(elem);
    2191                 :            :             PyErr_NoMemory();
    2192                 :          0 :             return NULL;
    2193                 :            :         }
    2194         [ +  + ]:       1253 :         if (it->gettext) {
    2195                 :         88 :             text = element_get_text(elem);
    2196                 :         88 :             goto gettext;
    2197                 :            :         }
    2198                 :            : 
    2199         [ +  + ]:       1165 :         if (it->sought_tag == Py_None)
    2200                 :        701 :             return (PyObject *)elem;
    2201                 :            : 
    2202                 :        464 :         rc = PyObject_RichCompareBool(elem->tag, it->sought_tag, Py_EQ);
    2203         [ +  + ]:        464 :         if (rc > 0)
    2204                 :        157 :             return (PyObject *)elem;
    2205                 :            : 
    2206                 :        307 :         Py_DECREF(elem);
    2207         [ -  + ]:        307 :         if (rc < 0)
    2208                 :          0 :             return NULL;
    2209                 :        307 :         continue;
    2210                 :            : 
    2211                 :         95 : gettext:
    2212         [ -  + ]:         95 :         if (!text) {
    2213                 :          0 :             Py_DECREF(elem);
    2214                 :          0 :             return NULL;
    2215                 :            :         }
    2216         [ +  + ]:         95 :         if (text == Py_None) {
    2217                 :         38 :             Py_DECREF(elem);
    2218                 :            :         }
    2219                 :            :         else {
    2220                 :         57 :             Py_INCREF(text);
    2221                 :         57 :             Py_DECREF(elem);
    2222                 :         57 :             rc = PyObject_IsTrue(text);
    2223         [ +  - ]:         57 :             if (rc > 0)
    2224                 :         57 :                 return text;
    2225                 :          0 :             Py_DECREF(text);
    2226         [ #  # ]:          0 :             if (rc < 0)
    2227                 :          0 :                 return NULL;
    2228                 :            :         }
    2229                 :            :     }
    2230                 :            : 
    2231                 :            :     return NULL;
    2232                 :            : }
    2233                 :            : 
    2234                 :            : 
    2235                 :            : static PyTypeObject ElementIter_Type = {
    2236                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
    2237                 :            :     /* Using the module's name since the pure-Python implementation does not
    2238                 :            :        have such a type. */
    2239                 :            :     "_elementtree._element_iterator",           /* tp_name */
    2240                 :            :     sizeof(ElementIterObject),                  /* tp_basicsize */
    2241                 :            :     0,                                          /* tp_itemsize */
    2242                 :            :     /* methods */
    2243                 :            :     (destructor)elementiter_dealloc,            /* tp_dealloc */
    2244                 :            :     0,                                          /* tp_vectorcall_offset */
    2245                 :            :     0,                                          /* tp_getattr */
    2246                 :            :     0,                                          /* tp_setattr */
    2247                 :            :     0,                                          /* tp_as_async */
    2248                 :            :     0,                                          /* tp_repr */
    2249                 :            :     0,                                          /* tp_as_number */
    2250                 :            :     0,                                          /* tp_as_sequence */
    2251                 :            :     0,                                          /* tp_as_mapping */
    2252                 :            :     0,                                          /* tp_hash */
    2253                 :            :     0,                                          /* tp_call */
    2254                 :            :     0,                                          /* tp_str */
    2255                 :            :     0,                                          /* tp_getattro */
    2256                 :            :     0,                                          /* tp_setattro */
    2257                 :            :     0,                                          /* tp_as_buffer */
    2258                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
    2259                 :            :     0,                                          /* tp_doc */
    2260                 :            :     (traverseproc)elementiter_traverse,         /* tp_traverse */
    2261                 :            :     0,                                          /* tp_clear */
    2262                 :            :     0,                                          /* tp_richcompare */
    2263                 :            :     0,                                          /* tp_weaklistoffset */
    2264                 :            :     PyObject_SelfIter,                          /* tp_iter */
    2265                 :            :     (iternextfunc)elementiter_next,             /* tp_iternext */
    2266                 :            :     0,                                          /* tp_methods */
    2267                 :            :     0,                                          /* tp_members */
    2268                 :            :     0,                                          /* tp_getset */
    2269                 :            :     0,                                          /* tp_base */
    2270                 :            :     0,                                          /* tp_dict */
    2271                 :            :     0,                                          /* tp_descr_get */
    2272                 :            :     0,                                          /* tp_descr_set */
    2273                 :            :     0,                                          /* tp_dictoffset */
    2274                 :            :     0,                                          /* tp_init */
    2275                 :            :     0,                                          /* tp_alloc */
    2276                 :            :     0,                                          /* tp_new */
    2277                 :            : };
    2278                 :            : 
    2279                 :            : #define INIT_PARENT_STACK_SIZE 8
    2280                 :            : 
    2281                 :            : static PyObject *
    2282                 :        528 : create_elementiter(ElementObject *self, PyObject *tag, int gettext)
    2283                 :            : {
    2284                 :            :     ElementIterObject *it;
    2285                 :            : 
    2286                 :        528 :     it = PyObject_GC_New(ElementIterObject, &ElementIter_Type);
    2287         [ -  + ]:        528 :     if (!it)
    2288                 :          0 :         return NULL;
    2289                 :            : 
    2290                 :        528 :     Py_INCREF(tag);
    2291                 :        528 :     it->sought_tag = tag;
    2292                 :        528 :     it->gettext = gettext;
    2293                 :        528 :     Py_INCREF(self);
    2294                 :        528 :     it->root_element = self;
    2295                 :            : 
    2296                 :        528 :     it->parent_stack = PyMem_New(ParentLocator, INIT_PARENT_STACK_SIZE);
    2297         [ -  + ]:        528 :     if (it->parent_stack == NULL) {
    2298                 :          0 :         Py_DECREF(it);
    2299                 :            :         PyErr_NoMemory();
    2300                 :          0 :         return NULL;
    2301                 :            :     }
    2302                 :        528 :     it->parent_stack_used = 0;
    2303                 :        528 :     it->parent_stack_size = INIT_PARENT_STACK_SIZE;
    2304                 :            : 
    2305                 :        528 :     PyObject_GC_Track(it);
    2306                 :            : 
    2307                 :        528 :     return (PyObject *)it;
    2308                 :            : }
    2309                 :            : 
    2310                 :            : 
    2311                 :            : /* ==================================================================== */
    2312                 :            : /* the tree builder type */
    2313                 :            : 
    2314                 :            : typedef struct {
    2315                 :            :     PyObject_HEAD
    2316                 :            : 
    2317                 :            :     PyObject *root; /* root node (first created node) */
    2318                 :            : 
    2319                 :            :     PyObject *this; /* current node */
    2320                 :            :     PyObject *last; /* most recently created node */
    2321                 :            :     PyObject *last_for_tail; /* most recently created node that takes a tail */
    2322                 :            : 
    2323                 :            :     PyObject *data; /* data collector (string or list), or NULL */
    2324                 :            : 
    2325                 :            :     PyObject *stack; /* element stack */
    2326                 :            :     Py_ssize_t index; /* current stack size (0 means empty) */
    2327                 :            : 
    2328                 :            :     PyObject *element_factory;
    2329                 :            :     PyObject *comment_factory;
    2330                 :            :     PyObject *pi_factory;
    2331                 :            : 
    2332                 :            :     /* element tracing */
    2333                 :            :     PyObject *events_append; /* the append method of the list of events, or NULL */
    2334                 :            :     PyObject *start_event_obj; /* event objects (NULL to ignore) */
    2335                 :            :     PyObject *end_event_obj;
    2336                 :            :     PyObject *start_ns_event_obj;
    2337                 :            :     PyObject *end_ns_event_obj;
    2338                 :            :     PyObject *comment_event_obj;
    2339                 :            :     PyObject *pi_event_obj;
    2340                 :            : 
    2341                 :            :     char insert_comments;
    2342                 :            :     char insert_pis;
    2343                 :            : } TreeBuilderObject;
    2344                 :            : 
    2345                 :            : #define TreeBuilder_CheckExact(op) Py_IS_TYPE((op), &TreeBuilder_Type)
    2346                 :            : 
    2347                 :            : /* -------------------------------------------------------------------- */
    2348                 :            : /* constructor and destructor */
    2349                 :            : 
    2350                 :            : static PyObject *
    2351                 :       1419 : treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    2352                 :            : {
    2353                 :       1419 :     TreeBuilderObject *t = (TreeBuilderObject *)type->tp_alloc(type, 0);
    2354         [ +  - ]:       1419 :     if (t != NULL) {
    2355                 :       1419 :         t->root = NULL;
    2356                 :            : 
    2357                 :       1419 :         Py_INCREF(Py_None);
    2358                 :       1419 :         t->this = Py_None;
    2359                 :       1419 :         Py_INCREF(Py_None);
    2360                 :       1419 :         t->last = Py_None;
    2361                 :            : 
    2362                 :       1419 :         t->data = NULL;
    2363                 :       1419 :         t->element_factory = NULL;
    2364                 :       1419 :         t->comment_factory = NULL;
    2365                 :       1419 :         t->pi_factory = NULL;
    2366                 :       1419 :         t->stack = PyList_New(20);
    2367         [ -  + ]:       1419 :         if (!t->stack) {
    2368                 :          0 :             Py_DECREF(t->this);
    2369                 :          0 :             Py_DECREF(t->last);
    2370                 :          0 :             Py_DECREF((PyObject *) t);
    2371                 :          0 :             return NULL;
    2372                 :            :         }
    2373                 :       1419 :         t->index = 0;
    2374                 :            : 
    2375                 :       1419 :         t->events_append = NULL;
    2376                 :       1419 :         t->start_event_obj = t->end_event_obj = NULL;
    2377                 :       1419 :         t->start_ns_event_obj = t->end_ns_event_obj = NULL;
    2378                 :       1419 :         t->comment_event_obj = t->pi_event_obj = NULL;
    2379                 :       1419 :         t->insert_comments = t->insert_pis = 0;
    2380                 :            :     }
    2381                 :       1419 :     return (PyObject *)t;
    2382                 :            : }
    2383                 :            : 
    2384                 :            : /*[clinic input]
    2385                 :            : _elementtree.TreeBuilder.__init__
    2386                 :            : 
    2387                 :            :     element_factory: object = None
    2388                 :            :     *
    2389                 :            :     comment_factory: object = None
    2390                 :            :     pi_factory: object = None
    2391                 :            :     insert_comments: bool = False
    2392                 :            :     insert_pis: bool = False
    2393                 :            : 
    2394                 :            : [clinic start generated code]*/
    2395                 :            : 
    2396                 :            : static int
    2397                 :       1388 : _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self,
    2398                 :            :                                        PyObject *element_factory,
    2399                 :            :                                        PyObject *comment_factory,
    2400                 :            :                                        PyObject *pi_factory,
    2401                 :            :                                        int insert_comments, int insert_pis)
    2402                 :            : /*[clinic end generated code: output=8571d4dcadfdf952 input=ae98a94df20b5cc3]*/
    2403                 :            : {
    2404         [ +  + ]:       1388 :     if (element_factory != Py_None) {
    2405                 :          5 :         Py_INCREF(element_factory);
    2406                 :          5 :         Py_XSETREF(self->element_factory, element_factory);
    2407                 :            :     } else {
    2408         [ -  + ]:       1383 :         Py_CLEAR(self->element_factory);
    2409                 :            :     }
    2410                 :            : 
    2411         [ +  + ]:       1388 :     if (comment_factory == Py_None) {
    2412                 :       1385 :         elementtreestate *st = ET_STATE_GLOBAL;
    2413                 :       1385 :         comment_factory = st->comment_factory;
    2414                 :            :     }
    2415         [ +  - ]:       1388 :     if (comment_factory) {
    2416                 :       1388 :         Py_INCREF(comment_factory);
    2417                 :       1388 :         Py_XSETREF(self->comment_factory, comment_factory);
    2418                 :       1388 :         self->insert_comments = insert_comments;
    2419                 :            :     } else {
    2420         [ #  # ]:          0 :         Py_CLEAR(self->comment_factory);
    2421                 :          0 :         self->insert_comments = 0;
    2422                 :            :     }
    2423                 :            : 
    2424         [ +  + ]:       1388 :     if (pi_factory == Py_None) {
    2425                 :       1385 :         elementtreestate *st = ET_STATE_GLOBAL;
    2426                 :       1385 :         pi_factory = st->pi_factory;
    2427                 :            :     }
    2428         [ +  - ]:       1388 :     if (pi_factory) {
    2429                 :       1388 :         Py_INCREF(pi_factory);
    2430                 :       1388 :         Py_XSETREF(self->pi_factory, pi_factory);
    2431                 :       1388 :         self->insert_pis = insert_pis;
    2432                 :            :     } else {
    2433         [ #  # ]:          0 :         Py_CLEAR(self->pi_factory);
    2434                 :          0 :         self->insert_pis = 0;
    2435                 :            :     }
    2436                 :            : 
    2437                 :       1388 :     return 0;
    2438                 :            : }
    2439                 :            : 
    2440                 :            : static int
    2441                 :         12 : treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg)
    2442                 :            : {
    2443   [ -  +  -  - ]:         12 :     Py_VISIT(self->pi_event_obj);
    2444   [ -  +  -  - ]:         12 :     Py_VISIT(self->comment_event_obj);
    2445   [ -  +  -  - ]:         12 :     Py_VISIT(self->end_ns_event_obj);
    2446   [ -  +  -  - ]:         12 :     Py_VISIT(self->start_ns_event_obj);
    2447   [ +  +  -  + ]:         12 :     Py_VISIT(self->end_event_obj);
    2448   [ -  +  -  - ]:         12 :     Py_VISIT(self->start_event_obj);
    2449   [ +  +  -  + ]:         12 :     Py_VISIT(self->events_append);
    2450   [ +  +  -  + ]:         12 :     Py_VISIT(self->root);
    2451   [ +  -  -  + ]:         12 :     Py_VISIT(self->this);
    2452   [ +  -  -  + ]:         12 :     Py_VISIT(self->last);
    2453   [ +  +  -  + ]:         12 :     Py_VISIT(self->last_for_tail);
    2454   [ -  +  -  - ]:         12 :     Py_VISIT(self->data);
    2455   [ +  -  -  + ]:         12 :     Py_VISIT(self->stack);
    2456   [ +  +  -  + ]:         12 :     Py_VISIT(self->pi_factory);
    2457   [ +  +  -  + ]:         12 :     Py_VISIT(self->comment_factory);
    2458   [ -  +  -  - ]:         12 :     Py_VISIT(self->element_factory);
    2459                 :         12 :     return 0;
    2460                 :            : }
    2461                 :            : 
    2462                 :            : static int
    2463                 :       1419 : treebuilder_gc_clear(TreeBuilderObject *self)
    2464                 :            : {
    2465         [ +  + ]:       1419 :     Py_CLEAR(self->pi_event_obj);
    2466         [ +  + ]:       1419 :     Py_CLEAR(self->comment_event_obj);
    2467         [ +  + ]:       1419 :     Py_CLEAR(self->end_ns_event_obj);
    2468         [ +  + ]:       1419 :     Py_CLEAR(self->start_ns_event_obj);
    2469         [ +  + ]:       1419 :     Py_CLEAR(self->end_event_obj);
    2470         [ +  + ]:       1419 :     Py_CLEAR(self->start_event_obj);
    2471         [ +  + ]:       1419 :     Py_CLEAR(self->events_append);
    2472         [ +  - ]:       1419 :     Py_CLEAR(self->stack);
    2473         [ +  + ]:       1419 :     Py_CLEAR(self->data);
    2474         [ +  - ]:       1419 :     Py_CLEAR(self->last);
    2475         [ +  + ]:       1419 :     Py_CLEAR(self->last_for_tail);
    2476         [ +  - ]:       1419 :     Py_CLEAR(self->this);
    2477         [ +  + ]:       1419 :     Py_CLEAR(self->pi_factory);
    2478         [ +  + ]:       1419 :     Py_CLEAR(self->comment_factory);
    2479         [ +  + ]:       1419 :     Py_CLEAR(self->element_factory);
    2480         [ +  + ]:       1419 :     Py_CLEAR(self->root);
    2481                 :       1419 :     return 0;
    2482                 :            : }
    2483                 :            : 
    2484                 :            : static void
    2485                 :       1419 : treebuilder_dealloc(TreeBuilderObject *self)
    2486                 :            : {
    2487                 :       1419 :     PyObject_GC_UnTrack(self);
    2488                 :       1419 :     treebuilder_gc_clear(self);
    2489                 :       1419 :     Py_TYPE(self)->tp_free((PyObject *)self);
    2490                 :       1419 : }
    2491                 :            : 
    2492                 :            : /* -------------------------------------------------------------------- */
    2493                 :            : /* helpers for handling of arbitrary element-like objects */
    2494                 :            : 
    2495                 :            : /*[clinic input]
    2496                 :            : _elementtree._set_factories
    2497                 :            : 
    2498                 :            :     comment_factory: object
    2499                 :            :     pi_factory: object
    2500                 :            :     /
    2501                 :            : 
    2502                 :            : Change the factories used to create comments and processing instructions.
    2503                 :            : 
    2504                 :            : For internal use only.
    2505                 :            : [clinic start generated code]*/
    2506                 :            : 
    2507                 :            : static PyObject *
    2508                 :         15 : _elementtree__set_factories_impl(PyObject *module, PyObject *comment_factory,
    2509                 :            :                                  PyObject *pi_factory)
    2510                 :            : /*[clinic end generated code: output=813b408adee26535 input=99d17627aea7fb3b]*/
    2511                 :            : {
    2512                 :         15 :     elementtreestate *st = ET_STATE_GLOBAL;
    2513                 :            :     PyObject *old;
    2514                 :            : 
    2515   [ -  +  -  - ]:         15 :     if (!PyCallable_Check(comment_factory) && comment_factory != Py_None) {
    2516                 :          0 :         PyErr_Format(PyExc_TypeError, "Comment factory must be callable, not %.100s",
    2517                 :          0 :                      Py_TYPE(comment_factory)->tp_name);
    2518                 :          0 :         return NULL;
    2519                 :            :     }
    2520   [ -  +  -  - ]:         15 :     if (!PyCallable_Check(pi_factory) && pi_factory != Py_None) {
    2521                 :          0 :         PyErr_Format(PyExc_TypeError, "PI factory must be callable, not %.100s",
    2522                 :          0 :                      Py_TYPE(pi_factory)->tp_name);
    2523                 :          0 :         return NULL;
    2524                 :            :     }
    2525                 :            : 
    2526                 :         30 :     old = PyTuple_Pack(2,
    2527         [ +  + ]:         15 :         st->comment_factory ? st->comment_factory : Py_None,
    2528         [ +  + ]:         15 :         st->pi_factory ? st->pi_factory : Py_None);
    2529                 :            : 
    2530         [ -  + ]:         15 :     if (comment_factory == Py_None) {
    2531         [ #  # ]:          0 :         Py_CLEAR(st->comment_factory);
    2532                 :            :     } else {
    2533                 :         15 :         Py_INCREF(comment_factory);
    2534                 :         15 :         Py_XSETREF(st->comment_factory, comment_factory);
    2535                 :            :     }
    2536         [ -  + ]:         15 :     if (pi_factory == Py_None) {
    2537         [ #  # ]:          0 :         Py_CLEAR(st->pi_factory);
    2538                 :            :     } else {
    2539                 :         15 :         Py_INCREF(pi_factory);
    2540                 :         15 :         Py_XSETREF(st->pi_factory, pi_factory);
    2541                 :            :     }
    2542                 :            : 
    2543                 :         15 :     return old;
    2544                 :            : }
    2545                 :            : 
    2546                 :            : static int
    2547                 :       1611 : treebuilder_extend_element_text_or_tail(PyObject *element, PyObject **data,
    2548                 :            :                                         PyObject **dest, _Py_Identifier *name)
    2549                 :            : {
    2550                 :            :     /* Fast paths for the "almost always" cases. */
    2551         [ +  + ]:       1611 :     if (Element_CheckExact(element)) {
    2552                 :       1603 :         PyObject *dest_obj = JOIN_OBJ(*dest);
    2553         [ +  + ]:       1603 :         if (dest_obj == Py_None) {
    2554                 :       1595 :             *dest = JOIN_SET(*data, PyList_CheckExact(*data));
    2555                 :       1595 :             *data = NULL;
    2556                 :       1595 :             Py_DECREF(dest_obj);
    2557                 :       1595 :             return 0;
    2558                 :            :         }
    2559         [ -  + ]:          8 :         else if (JOIN_GET(*dest)) {
    2560         [ #  # ]:          0 :             if (PyList_SetSlice(dest_obj, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, *data) < 0) {
    2561                 :          0 :                 return -1;
    2562                 :            :             }
    2563         [ #  # ]:          0 :             Py_CLEAR(*data);
    2564                 :          0 :             return 0;
    2565                 :            :         }
    2566                 :            :     }
    2567                 :            : 
    2568                 :            :     /*  Fallback for the non-Element / non-trivial cases. */
    2569                 :            :     {
    2570                 :            :         int r;
    2571                 :            :         PyObject* joined;
    2572                 :         16 :         PyObject* previous = _PyObject_GetAttrId(element, name);
    2573         [ +  + ]:         16 :         if (!previous)
    2574                 :          2 :             return -1;
    2575                 :         14 :         joined = list_join(*data);
    2576         [ -  + ]:         14 :         if (!joined) {
    2577                 :          0 :             Py_DECREF(previous);
    2578                 :          0 :             return -1;
    2579                 :            :         }
    2580         [ +  + ]:         14 :         if (previous != Py_None) {
    2581                 :          8 :             PyObject *tmp = PyNumber_Add(previous, joined);
    2582                 :          8 :             Py_DECREF(joined);
    2583                 :          8 :             Py_DECREF(previous);
    2584         [ -  + ]:          8 :             if (!tmp)
    2585                 :          0 :                 return -1;
    2586                 :          8 :             joined = tmp;
    2587                 :            :         } else {
    2588                 :          6 :             Py_DECREF(previous);
    2589                 :            :         }
    2590                 :            : 
    2591                 :         14 :         r = _PyObject_SetAttrId(element, name, joined);
    2592                 :         14 :         Py_DECREF(joined);
    2593         [ -  + ]:         14 :         if (r < 0)
    2594                 :          0 :             return -1;
    2595         [ +  - ]:         14 :         Py_CLEAR(*data);
    2596                 :         14 :         return 0;
    2597                 :            :     }
    2598                 :            : }
    2599                 :            : 
    2600                 :            : LOCAL(int)
    2601                 :       3424 : treebuilder_flush_data(TreeBuilderObject* self)
    2602                 :            : {
    2603         [ +  + ]:       3424 :     if (!self->data) {
    2604                 :       1813 :         return 0;
    2605                 :            :     }
    2606                 :            : 
    2607         [ +  + ]:       1611 :     if (!self->last_for_tail) {
    2608                 :       1349 :         PyObject *element = self->last;
    2609                 :            :         _Py_IDENTIFIER(text);
    2610                 :       1349 :         return treebuilder_extend_element_text_or_tail(
    2611                 :            :                 element, &self->data,
    2612                 :            :                 &((ElementObject *) element)->text, &PyId_text);
    2613                 :            :     }
    2614                 :            :     else {
    2615                 :        262 :         PyObject *element = self->last_for_tail;
    2616                 :            :         _Py_IDENTIFIER(tail);
    2617                 :        262 :         return treebuilder_extend_element_text_or_tail(
    2618                 :            :                 element, &self->data,
    2619                 :            :                 &((ElementObject *) element)->tail, &PyId_tail);
    2620                 :            :     }
    2621                 :            : }
    2622                 :            : 
    2623                 :            : static int
    2624                 :        327 : treebuilder_add_subelement(PyObject *element, PyObject *child)
    2625                 :            : {
    2626                 :            :     _Py_IDENTIFIER(append);
    2627         [ +  + ]:        327 :     if (Element_CheckExact(element)) {
    2628                 :        325 :         ElementObject *elem = (ElementObject *) element;
    2629                 :        325 :         return element_add_subelement(elem, child);
    2630                 :            :     }
    2631                 :            :     else {
    2632                 :            :         PyObject *res;
    2633                 :          2 :         res = _PyObject_CallMethodIdOneArg(element, &PyId_append, child);
    2634         [ -  + ]:          2 :         if (res == NULL)
    2635                 :          0 :             return -1;
    2636                 :          2 :         Py_DECREF(res);
    2637                 :          2 :         return 0;
    2638                 :            :     }
    2639                 :            : }
    2640                 :            : 
    2641                 :            : LOCAL(int)
    2642                 :       3390 : treebuilder_append_event(TreeBuilderObject *self, PyObject *action,
    2643                 :            :                          PyObject *node)
    2644                 :            : {
    2645         [ +  + ]:       3390 :     if (action != NULL) {
    2646                 :            :         PyObject *res;
    2647                 :         99 :         PyObject *event = PyTuple_Pack(2, action, node);
    2648         [ -  + ]:         99 :         if (event == NULL)
    2649                 :          0 :             return -1;
    2650                 :         99 :         res = PyObject_CallOneArg(self->events_append, event);
    2651                 :         99 :         Py_DECREF(event);
    2652         [ -  + ]:         99 :         if (res == NULL)
    2653                 :          0 :             return -1;
    2654                 :         99 :         Py_DECREF(res);
    2655                 :            :     }
    2656                 :       3390 :     return 0;
    2657                 :            : }
    2658                 :            : 
    2659                 :            : /* -------------------------------------------------------------------- */
    2660                 :            : /* handlers */
    2661                 :            : 
    2662                 :            : LOCAL(PyObject*)
    2663                 :       1689 : treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
    2664                 :            :                          PyObject* attrib)
    2665                 :            : {
    2666                 :            :     PyObject* node;
    2667                 :            :     PyObject* this;
    2668                 :       1689 :     elementtreestate *st = ET_STATE_GLOBAL;
    2669                 :            : 
    2670         [ +  + ]:       1689 :     if (treebuilder_flush_data(self) < 0) {
    2671                 :          1 :         return NULL;
    2672                 :            :     }
    2673                 :            : 
    2674         [ +  + ]:       1688 :     if (!self->element_factory) {
    2675                 :       1681 :         node = create_new_element(tag, attrib);
    2676         [ +  + ]:          7 :     } else if (attrib == NULL) {
    2677                 :          5 :         attrib = PyDict_New();
    2678         [ -  + ]:          5 :         if (!attrib)
    2679                 :          0 :             return NULL;
    2680                 :          5 :         node = PyObject_CallFunctionObjArgs(self->element_factory,
    2681                 :            :                                             tag, attrib, NULL);
    2682                 :          5 :         Py_DECREF(attrib);
    2683                 :            :     }
    2684                 :            :     else {
    2685                 :          2 :         node = PyObject_CallFunctionObjArgs(self->element_factory,
    2686                 :            :                                             tag, attrib, NULL);
    2687                 :            :     }
    2688         [ -  + ]:       1688 :     if (!node) {
    2689                 :          0 :         return NULL;
    2690                 :            :     }
    2691                 :            : 
    2692                 :       1688 :     this = self->this;
    2693         [ +  + ]:       1688 :     Py_CLEAR(self->last_for_tail);
    2694                 :            : 
    2695         [ +  + ]:       1688 :     if (this != Py_None) {
    2696         [ -  + ]:        323 :         if (treebuilder_add_subelement(this, node) < 0)
    2697                 :          0 :             goto error;
    2698                 :            :     } else {
    2699         [ -  + ]:       1365 :         if (self->root) {
    2700                 :          0 :             PyErr_SetString(
    2701                 :            :                 st->parseerror_obj,
    2702                 :            :                 "multiple elements on top level"
    2703                 :            :                 );
    2704                 :          0 :             goto error;
    2705                 :            :         }
    2706                 :       1365 :         Py_INCREF(node);
    2707                 :       1365 :         self->root = node;
    2708                 :            :     }
    2709                 :            : 
    2710         [ +  - ]:       1688 :     if (self->index < PyList_GET_SIZE(self->stack)) {
    2711         [ -  + ]:       1688 :         if (PyList_SetItem(self->stack, self->index, this) < 0)
    2712                 :          0 :             goto error;
    2713                 :       1688 :         Py_INCREF(this);
    2714                 :            :     } else {
    2715         [ #  # ]:          0 :         if (PyList_Append(self->stack, this) < 0)
    2716                 :          0 :             goto error;
    2717                 :            :     }
    2718                 :       1688 :     self->index++;
    2719                 :            : 
    2720                 :       1688 :     Py_INCREF(node);
    2721                 :       1688 :     Py_SETREF(self->this, node);
    2722                 :       1688 :     Py_INCREF(node);
    2723                 :       1688 :     Py_SETREF(self->last, node);
    2724                 :            : 
    2725         [ -  + ]:       1688 :     if (treebuilder_append_event(self, self->start_event_obj, node) < 0)
    2726                 :          0 :         goto error;
    2727                 :            : 
    2728                 :       1688 :     return node;
    2729                 :            : 
    2730                 :          0 :   error:
    2731                 :          0 :     Py_DECREF(node);
    2732                 :          0 :     return NULL;
    2733                 :            : }
    2734                 :            : 
    2735                 :            : LOCAL(PyObject*)
    2736                 :       1926 : treebuilder_handle_data(TreeBuilderObject* self, PyObject* data)
    2737                 :            : {
    2738         [ +  + ]:       1926 :     if (!self->data) {
    2739         [ +  + ]:       1612 :         if (self->last == Py_None) {
    2740                 :            :             /* ignore calls to data before the first call to start */
    2741                 :          1 :             Py_RETURN_NONE;
    2742                 :            :         }
    2743                 :            :         /* store the first item as is */
    2744                 :       1611 :         Py_INCREF(data); self->data = data;
    2745                 :            :     } else {
    2746                 :            :         /* more than one item; use a list to collect items */
    2747   [ -  +  -  -  :        314 :         if (PyBytes_CheckExact(self->data) && Py_REFCNT(self->data) == 1 &&
                   -  - ]
    2748         [ #  # ]:          0 :             PyBytes_CheckExact(data) && PyBytes_GET_SIZE(data) == 1) {
    2749                 :            :             /* XXX this code path unused in Python 3? */
    2750                 :            :             /* expat often generates single character data sections; handle
    2751                 :            :                the most common case by resizing the existing string... */
    2752                 :          0 :             Py_ssize_t size = PyBytes_GET_SIZE(self->data);
    2753         [ #  # ]:          0 :             if (_PyBytes_Resize(&self->data, size + 1) < 0)
    2754                 :          0 :                 return NULL;
    2755                 :          0 :             PyBytes_AS_STRING(self->data)[size] = PyBytes_AS_STRING(data)[0];
    2756         [ +  + ]:        314 :         } else if (PyList_CheckExact(self->data)) {
    2757         [ -  + ]:         49 :             if (PyList_Append(self->data, data) < 0)
    2758                 :          0 :                 return NULL;
    2759                 :            :         } else {
    2760                 :        265 :             PyObject* list = PyList_New(2);
    2761         [ -  + ]:        265 :             if (!list)
    2762                 :          0 :                 return NULL;
    2763                 :        265 :             PyList_SET_ITEM(list, 0, self->data);
    2764                 :        265 :             Py_INCREF(data); PyList_SET_ITEM(list, 1, data);
    2765                 :        265 :             self->data = list;
    2766                 :            :         }
    2767                 :            :     }
    2768                 :            : 
    2769                 :       1925 :     Py_RETURN_NONE;
    2770                 :            : }
    2771                 :            : 
    2772                 :            : LOCAL(PyObject*)
    2773                 :       1682 : treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
    2774                 :            : {
    2775                 :            :     PyObject* item;
    2776                 :            : 
    2777         [ +  + ]:       1682 :     if (treebuilder_flush_data(self) < 0) {
    2778                 :          1 :         return NULL;
    2779                 :            :     }
    2780                 :            : 
    2781         [ -  + ]:       1681 :     if (self->index == 0) {
    2782                 :          0 :         PyErr_SetString(
    2783                 :            :             PyExc_IndexError,
    2784                 :            :             "pop from empty stack"
    2785                 :            :             );
    2786                 :          0 :         return NULL;
    2787                 :            :     }
    2788                 :            : 
    2789                 :       1681 :     item = self->last;
    2790                 :       1681 :     self->last = self->this;
    2791                 :       1681 :     Py_INCREF(self->last);
    2792                 :       1681 :     Py_XSETREF(self->last_for_tail, self->last);
    2793                 :       1681 :     self->index--;
    2794                 :       1681 :     self->this = PyList_GET_ITEM(self->stack, self->index);
    2795                 :       1681 :     Py_INCREF(self->this);
    2796                 :       1681 :     Py_DECREF(item);
    2797                 :            : 
    2798         [ -  + ]:       1681 :     if (treebuilder_append_event(self, self->end_event_obj, self->last) < 0)
    2799                 :          0 :         return NULL;
    2800                 :            : 
    2801                 :       1681 :     Py_INCREF(self->last);
    2802                 :       1681 :     return (PyObject*) self->last;
    2803                 :            : }
    2804                 :            : 
    2805                 :            : LOCAL(PyObject*)
    2806                 :         37 : treebuilder_handle_comment(TreeBuilderObject* self, PyObject* text)
    2807                 :            : {
    2808                 :            :     PyObject* comment;
    2809                 :            :     PyObject* this;
    2810                 :            : 
    2811         [ -  + ]:         37 :     if (treebuilder_flush_data(self) < 0) {
    2812                 :          0 :         return NULL;
    2813                 :            :     }
    2814                 :            : 
    2815         [ +  + ]:         37 :     if (self->comment_factory) {
    2816                 :         31 :         comment = PyObject_CallOneArg(self->comment_factory, text);
    2817         [ -  + ]:         31 :         if (!comment)
    2818                 :          0 :             return NULL;
    2819                 :            : 
    2820                 :         31 :         this = self->this;
    2821   [ +  +  +  - ]:         31 :         if (self->insert_comments && this != Py_None) {
    2822         [ -  + ]:          2 :             if (treebuilder_add_subelement(this, comment) < 0)
    2823                 :          0 :                 goto error;
    2824                 :          2 :             Py_INCREF(comment);
    2825                 :          2 :             Py_XSETREF(self->last_for_tail, comment);
    2826                 :            :         }
    2827                 :            :     } else {
    2828                 :          6 :         Py_INCREF(text);
    2829                 :          6 :         comment = text;
    2830                 :            :     }
    2831                 :            : 
    2832   [ +  +  +  + ]:         37 :     if (self->events_append && self->comment_event_obj) {
    2833         [ -  + ]:          5 :         if (treebuilder_append_event(self, self->comment_event_obj, comment) < 0)
    2834                 :          0 :             goto error;
    2835                 :            :     }
    2836                 :            : 
    2837                 :         37 :     return comment;
    2838                 :            : 
    2839                 :          0 :   error:
    2840                 :          0 :     Py_DECREF(comment);
    2841                 :          0 :     return NULL;
    2842                 :            : }
    2843                 :            : 
    2844                 :            : LOCAL(PyObject*)
    2845                 :         16 : treebuilder_handle_pi(TreeBuilderObject* self, PyObject* target, PyObject* text)
    2846                 :            : {
    2847                 :            :     PyObject* pi;
    2848                 :            :     PyObject* this;
    2849                 :         16 :     PyObject* stack[2] = {target, text};
    2850                 :            : 
    2851         [ -  + ]:         16 :     if (treebuilder_flush_data(self) < 0) {
    2852                 :          0 :         return NULL;
    2853                 :            :     }
    2854                 :            : 
    2855         [ +  - ]:         16 :     if (self->pi_factory) {
    2856                 :         16 :         pi = _PyObject_FastCall(self->pi_factory, stack, 2);
    2857         [ -  + ]:         16 :         if (!pi) {
    2858                 :          0 :             return NULL;
    2859                 :            :         }
    2860                 :            : 
    2861                 :         16 :         this = self->this;
    2862   [ +  +  +  - ]:         16 :         if (self->insert_pis && this != Py_None) {
    2863         [ -  + ]:          2 :             if (treebuilder_add_subelement(this, pi) < 0)
    2864                 :          0 :                 goto error;
    2865                 :          2 :             Py_INCREF(pi);
    2866                 :          2 :             Py_XSETREF(self->last_for_tail, pi);
    2867                 :            :         }
    2868                 :            :     } else {
    2869                 :          0 :         pi = PyTuple_Pack(2, target, text);
    2870         [ #  # ]:          0 :         if (!pi) {
    2871                 :          0 :             return NULL;
    2872                 :            :         }
    2873                 :            :     }
    2874                 :            : 
    2875   [ +  +  +  - ]:         16 :     if (self->events_append && self->pi_event_obj) {
    2876         [ -  + ]:          2 :         if (treebuilder_append_event(self, self->pi_event_obj, pi) < 0)
    2877                 :          0 :             goto error;
    2878                 :            :     }
    2879                 :            : 
    2880                 :         16 :     return pi;
    2881                 :            : 
    2882                 :          0 :   error:
    2883                 :          0 :     Py_DECREF(pi);
    2884                 :          0 :     return NULL;
    2885                 :            : }
    2886                 :            : 
    2887                 :            : LOCAL(PyObject*)
    2888                 :          9 : treebuilder_handle_start_ns(TreeBuilderObject* self, PyObject* prefix, PyObject* uri)
    2889                 :            : {
    2890                 :            :     PyObject* parcel;
    2891                 :            : 
    2892   [ +  -  +  - ]:          9 :     if (self->events_append && self->start_ns_event_obj) {
    2893                 :          9 :         parcel = PyTuple_Pack(2, prefix, uri);
    2894         [ -  + ]:          9 :         if (!parcel) {
    2895                 :          0 :             return NULL;
    2896                 :            :         }
    2897                 :            : 
    2898         [ -  + ]:          9 :         if (treebuilder_append_event(self, self->start_ns_event_obj, parcel) < 0) {
    2899                 :          0 :             Py_DECREF(parcel);
    2900                 :          0 :             return NULL;
    2901                 :            :         }
    2902                 :          9 :         Py_DECREF(parcel);
    2903                 :            :     }
    2904                 :            : 
    2905                 :          9 :     Py_RETURN_NONE;
    2906                 :            : }
    2907                 :            : 
    2908                 :            : LOCAL(PyObject*)
    2909                 :          5 : treebuilder_handle_end_ns(TreeBuilderObject* self, PyObject* prefix)
    2910                 :            : {
    2911   [ +  -  +  - ]:          5 :     if (self->events_append && self->end_ns_event_obj) {
    2912         [ -  + ]:          5 :         if (treebuilder_append_event(self, self->end_ns_event_obj, prefix) < 0) {
    2913                 :          0 :             return NULL;
    2914                 :            :         }
    2915                 :            :     }
    2916                 :            : 
    2917                 :          5 :     Py_RETURN_NONE;
    2918                 :            : }
    2919                 :            : 
    2920                 :            : /* -------------------------------------------------------------------- */
    2921                 :            : /* methods (in alphabetical order) */
    2922                 :            : 
    2923                 :            : /*[clinic input]
    2924                 :            : _elementtree.TreeBuilder.data
    2925                 :            : 
    2926                 :            :     data: object
    2927                 :            :     /
    2928                 :            : 
    2929                 :            : [clinic start generated code]*/
    2930                 :            : 
    2931                 :            : static PyObject *
    2932                 :       1027 : _elementtree_TreeBuilder_data(TreeBuilderObject *self, PyObject *data)
    2933                 :            : /*[clinic end generated code: output=69144c7100795bb2 input=a0540c532b284d29]*/
    2934                 :            : {
    2935                 :       1027 :     return treebuilder_handle_data(self, data);
    2936                 :            : }
    2937                 :            : 
    2938                 :            : /*[clinic input]
    2939                 :            : _elementtree.TreeBuilder.end
    2940                 :            : 
    2941                 :            :     tag: object
    2942                 :            :     /
    2943                 :            : 
    2944                 :            : [clinic start generated code]*/
    2945                 :            : 
    2946                 :            : static PyObject *
    2947                 :       1014 : _elementtree_TreeBuilder_end(TreeBuilderObject *self, PyObject *tag)
    2948                 :            : /*[clinic end generated code: output=9a98727cc691cd9d input=22dc3674236f5745]*/
    2949                 :            : {
    2950                 :       1014 :     return treebuilder_handle_end(self, tag);
    2951                 :            : }
    2952                 :            : 
    2953                 :            : /*[clinic input]
    2954                 :            : _elementtree.TreeBuilder.comment
    2955                 :            : 
    2956                 :            :     text: object
    2957                 :            :     /
    2958                 :            : 
    2959                 :            : [clinic start generated code]*/
    2960                 :            : 
    2961                 :            : static PyObject *
    2962                 :          9 : _elementtree_TreeBuilder_comment(TreeBuilderObject *self, PyObject *text)
    2963                 :            : /*[clinic end generated code: output=22835be41deeaa27 input=47e7ebc48ed01dfa]*/
    2964                 :            : {
    2965                 :          9 :     return treebuilder_handle_comment(self, text);
    2966                 :            : }
    2967                 :            : 
    2968                 :            : /*[clinic input]
    2969                 :            : _elementtree.TreeBuilder.pi
    2970                 :            : 
    2971                 :            :     target: object
    2972                 :            :     text: object = None
    2973                 :            :     /
    2974                 :            : 
    2975                 :            : [clinic start generated code]*/
    2976                 :            : 
    2977                 :            : static PyObject *
    2978                 :         13 : _elementtree_TreeBuilder_pi_impl(TreeBuilderObject *self, PyObject *target,
    2979                 :            :                                  PyObject *text)
    2980                 :            : /*[clinic end generated code: output=21eb95ec9d04d1d9 input=349342bd79c35570]*/
    2981                 :            : {
    2982                 :         13 :     return treebuilder_handle_pi(self, target, text);
    2983                 :            : }
    2984                 :            : 
    2985                 :            : LOCAL(PyObject*)
    2986                 :        346 : treebuilder_done(TreeBuilderObject* self)
    2987                 :            : {
    2988                 :            :     PyObject* res;
    2989                 :            : 
    2990                 :            :     /* FIXME: check stack size? */
    2991                 :            : 
    2992         [ +  - ]:        346 :     if (self->root)
    2993                 :        346 :         res = self->root;
    2994                 :            :     else
    2995                 :          0 :         res = Py_None;
    2996                 :            : 
    2997                 :        346 :     Py_INCREF(res);
    2998                 :        346 :     return res;
    2999                 :            : }
    3000                 :            : 
    3001                 :            : /*[clinic input]
    3002                 :            : _elementtree.TreeBuilder.close
    3003                 :            : 
    3004                 :            : [clinic start generated code]*/
    3005                 :            : 
    3006                 :            : static PyObject *
    3007                 :          9 : _elementtree_TreeBuilder_close_impl(TreeBuilderObject *self)
    3008                 :            : /*[clinic end generated code: output=b441fee3202f61ee input=f7c9c65dc718de14]*/
    3009                 :            : {
    3010                 :          9 :     return treebuilder_done(self);
    3011                 :            : }
    3012                 :            : 
    3013                 :            : /*[clinic input]
    3014                 :            : _elementtree.TreeBuilder.start
    3015                 :            : 
    3016                 :            :     tag: object
    3017                 :            :     attrs: object(subclass_of='&PyDict_Type')
    3018                 :            :     /
    3019                 :            : 
    3020                 :            : [clinic start generated code]*/
    3021                 :            : 
    3022                 :            : static PyObject *
    3023                 :       1016 : _elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag,
    3024                 :            :                                     PyObject *attrs)
    3025                 :            : /*[clinic end generated code: output=e7e9dc2861349411 input=7288e9e38e63b2b6]*/
    3026                 :            : {
    3027                 :       1016 :     return treebuilder_handle_start(self, tag, attrs);
    3028                 :            : }
    3029                 :            : 
    3030                 :            : /* ==================================================================== */
    3031                 :            : /* the expat interface */
    3032                 :            : 
    3033                 :            : #include "expat.h"
    3034                 :            : #include "pyexpat.h"
    3035                 :            : 
    3036                 :            : /* The PyExpat_CAPI structure is an immutable dispatch table, so it can be
    3037                 :            :  * cached globally without being in per-module state.
    3038                 :            :  */
    3039                 :            : static struct PyExpat_CAPI *expat_capi;
    3040                 :            : #define EXPAT(func) (expat_capi->func)
    3041                 :            : 
    3042                 :            : static XML_Memory_Handling_Suite ExpatMemoryHandler = {
    3043                 :            :     PyObject_Malloc, PyObject_Realloc, PyObject_Free};
    3044                 :            : 
    3045                 :            : typedef struct {
    3046                 :            :     PyObject_HEAD
    3047                 :            : 
    3048                 :            :     XML_Parser parser;
    3049                 :            : 
    3050                 :            :     PyObject *target;
    3051                 :            :     PyObject *entity;
    3052                 :            : 
    3053                 :            :     PyObject *names;
    3054                 :            : 
    3055                 :            :     PyObject *handle_start_ns;
    3056                 :            :     PyObject *handle_end_ns;
    3057                 :            :     PyObject *handle_start;
    3058                 :            :     PyObject *handle_data;
    3059                 :            :     PyObject *handle_end;
    3060                 :            : 
    3061                 :            :     PyObject *handle_comment;
    3062                 :            :     PyObject *handle_pi;
    3063                 :            :     PyObject *handle_doctype;
    3064                 :            : 
    3065                 :            :     PyObject *handle_close;
    3066                 :            : 
    3067                 :            : } XMLParserObject;
    3068                 :            : 
    3069                 :            : /* helpers */
    3070                 :            : 
    3071                 :            : LOCAL(PyObject*)
    3072                 :       1234 : makeuniversal(XMLParserObject* self, const char* string)
    3073                 :            : {
    3074                 :            :     /* convert a UTF-8 tag/attribute name from the expat parser
    3075                 :            :        to a universal name string */
    3076                 :            : 
    3077                 :       1234 :     Py_ssize_t size = (Py_ssize_t) strlen(string);
    3078                 :            :     PyObject* key;
    3079                 :            :     PyObject* value;
    3080                 :            : 
    3081                 :            :     /* look the 'raw' name up in the names dictionary */
    3082                 :       1234 :     key = PyBytes_FromStringAndSize(string, size);
    3083         [ -  + ]:       1234 :     if (!key)
    3084                 :          0 :         return NULL;
    3085                 :            : 
    3086                 :       1234 :     value = PyDict_GetItemWithError(self->names, key);
    3087                 :            : 
    3088         [ +  + ]:       1234 :     if (value) {
    3089                 :        285 :         Py_INCREF(value);
    3090                 :            :     }
    3091         [ +  - ]:        949 :     else if (!PyErr_Occurred()) {
    3092                 :            :         /* new name.  convert to universal name, and decode as
    3093                 :            :            necessary */
    3094                 :            : 
    3095                 :            :         PyObject* tag;
    3096                 :            :         char* p;
    3097                 :            :         Py_ssize_t i;
    3098                 :            : 
    3099                 :            :         /* look for namespace separator */
    3100         [ +  + ]:       9368 :         for (i = 0; i < size; i++)
    3101         [ +  + ]:       8599 :             if (string[i] == '}')
    3102                 :        180 :                 break;
    3103         [ +  + ]:        949 :         if (i != size) {
    3104                 :            :             /* convert to universal name */
    3105                 :        180 :             tag = PyBytes_FromStringAndSize(NULL, size+1);
    3106         [ -  + ]:        180 :             if (tag == NULL) {
    3107                 :          0 :                 Py_DECREF(key);
    3108                 :          0 :                 return NULL;
    3109                 :            :             }
    3110                 :        180 :             p = PyBytes_AS_STRING(tag);
    3111                 :        180 :             p[0] = '{';
    3112                 :        180 :             memcpy(p+1, string, size);
    3113                 :        180 :             size++;
    3114                 :            :         } else {
    3115                 :            :             /* plain name; use key as tag */
    3116                 :        769 :             Py_INCREF(key);
    3117                 :        769 :             tag = key;
    3118                 :            :         }
    3119                 :            : 
    3120                 :            :         /* decode universal name */
    3121                 :        949 :         p = PyBytes_AS_STRING(tag);
    3122                 :        949 :         value = PyUnicode_DecodeUTF8(p, size, "strict");
    3123                 :        949 :         Py_DECREF(tag);
    3124         [ -  + ]:        949 :         if (!value) {
    3125                 :          0 :             Py_DECREF(key);
    3126                 :          0 :             return NULL;
    3127                 :            :         }
    3128                 :            : 
    3129                 :            :         /* add to names dictionary */
    3130         [ -  + ]:        949 :         if (PyDict_SetItem(self->names, key, value) < 0) {
    3131                 :          0 :             Py_DECREF(key);
    3132                 :          0 :             Py_DECREF(value);
    3133                 :          0 :             return NULL;
    3134                 :            :         }
    3135                 :            :     }
    3136                 :            : 
    3137                 :       1234 :     Py_DECREF(key);
    3138                 :       1234 :     return value;
    3139                 :            : }
    3140                 :            : 
    3141                 :            : /* Set the ParseError exception with the given parameters.
    3142                 :            :  * If message is not NULL, it's used as the error string. Otherwise, the
    3143                 :            :  * message string is the default for the given error_code.
    3144                 :            : */
    3145                 :            : static void
    3146                 :         22 : expat_set_error(enum XML_Error error_code, Py_ssize_t line, Py_ssize_t column,
    3147                 :            :                 const char *message)
    3148                 :            : {
    3149                 :            :     PyObject *errmsg, *error, *position, *code;
    3150                 :         22 :     elementtreestate *st = ET_STATE_GLOBAL;
    3151                 :            : 
    3152         [ +  + ]:         41 :     errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd",
    3153                 :         19 :                 message ? message : EXPAT(ErrorString)(error_code),
    3154                 :            :                 line, column);
    3155         [ -  + ]:         22 :     if (errmsg == NULL)
    3156                 :          0 :         return;
    3157                 :            : 
    3158                 :         22 :     error = PyObject_CallOneArg(st->parseerror_obj, errmsg);
    3159                 :         22 :     Py_DECREF(errmsg);
    3160         [ -  + ]:         22 :     if (!error)
    3161                 :          0 :         return;
    3162                 :            : 
    3163                 :            :     /* Add code and position attributes */
    3164                 :         22 :     code = PyLong_FromLong((long)error_code);
    3165         [ -  + ]:         22 :     if (!code) {
    3166                 :          0 :         Py_DECREF(error);
    3167                 :          0 :         return;
    3168                 :            :     }
    3169         [ -  + ]:         22 :     if (PyObject_SetAttrString(error, "code", code) == -1) {
    3170                 :          0 :         Py_DECREF(error);
    3171                 :          0 :         Py_DECREF(code);
    3172                 :          0 :         return;
    3173                 :            :     }
    3174                 :         22 :     Py_DECREF(code);
    3175                 :            : 
    3176                 :         22 :     position = Py_BuildValue("(nn)", line, column);
    3177         [ -  + ]:         22 :     if (!position) {
    3178                 :          0 :         Py_DECREF(error);
    3179                 :          0 :         return;
    3180                 :            :     }
    3181         [ -  + ]:         22 :     if (PyObject_SetAttrString(error, "position", position) == -1) {
    3182                 :          0 :         Py_DECREF(error);
    3183                 :          0 :         Py_DECREF(position);
    3184                 :          0 :         return;
    3185                 :            :     }
    3186                 :         22 :     Py_DECREF(position);
    3187                 :            : 
    3188                 :         22 :     PyErr_SetObject(st->parseerror_obj, error);
    3189                 :         22 :     Py_DECREF(error);
    3190                 :            : }
    3191                 :            : 
    3192                 :            : /* -------------------------------------------------------------------- */
    3193                 :            : /* handlers */
    3194                 :            : 
    3195                 :            : static void
    3196                 :        684 : expat_default_handler(XMLParserObject* self, const XML_Char* data_in,
    3197                 :            :                       int data_len)
    3198                 :            : {
    3199                 :            :     PyObject* key;
    3200                 :            :     PyObject* value;
    3201                 :            :     PyObject* res;
    3202                 :            : 
    3203   [ +  +  +  + ]:        684 :     if (data_len < 2 || data_in[0] != '&')
    3204                 :        676 :         return;
    3205                 :            : 
    3206         [ +  + ]:          8 :     if (PyErr_Occurred())
    3207                 :          2 :         return;
    3208                 :            : 
    3209                 :          6 :     key = PyUnicode_DecodeUTF8(data_in + 1, data_len - 2, "strict");
    3210         [ -  + ]:          6 :     if (!key)
    3211                 :          0 :         return;
    3212                 :            : 
    3213                 :          6 :     value = PyDict_GetItemWithError(self->entity, key);
    3214                 :            : 
    3215         [ +  + ]:          6 :     if (value) {
    3216         [ +  - ]:          3 :         if (TreeBuilder_CheckExact(self->target))
    3217                 :          3 :             res = treebuilder_handle_data(
    3218                 :          3 :                 (TreeBuilderObject*) self->target, value
    3219                 :            :                 );
    3220         [ #  # ]:          0 :         else if (self->handle_data)
    3221                 :          0 :             res = PyObject_CallOneArg(self->handle_data, value);
    3222                 :            :         else
    3223                 :          0 :             res = NULL;
    3224                 :          3 :         Py_XDECREF(res);
    3225         [ +  - ]:          3 :     } else if (!PyErr_Occurred()) {
    3226                 :            :         /* Report the first error, not the last */
    3227                 :          3 :         char message[128] = "undefined entity ";
    3228                 :          3 :         strncat(message, data_in, data_len < 100?data_len:100);
    3229                 :          3 :         expat_set_error(
    3230                 :            :             XML_ERROR_UNDEFINED_ENTITY,
    3231                 :          3 :             EXPAT(GetErrorLineNumber)(self->parser),
    3232                 :          3 :             EXPAT(GetErrorColumnNumber)(self->parser),
    3233                 :            :             message
    3234                 :            :             );
    3235                 :            :     }
    3236                 :            : 
    3237                 :          6 :     Py_DECREF(key);
    3238                 :            : }
    3239                 :            : 
    3240                 :            : static void
    3241                 :        815 : expat_start_handler(XMLParserObject* self, const XML_Char* tag_in,
    3242                 :            :                     const XML_Char **attrib_in)
    3243                 :            : {
    3244                 :            :     PyObject* res;
    3245                 :            :     PyObject* tag;
    3246                 :            :     PyObject* attrib;
    3247                 :            :     int ok;
    3248                 :            : 
    3249         [ -  + ]:        815 :     if (PyErr_Occurred())
    3250                 :          0 :         return;
    3251                 :            : 
    3252                 :            :     /* tag name */
    3253                 :        815 :     tag = makeuniversal(self, tag_in);
    3254         [ -  + ]:        815 :     if (!tag)
    3255                 :          0 :         return; /* parser will look for errors */
    3256                 :            : 
    3257                 :            :     /* attributes */
    3258         [ +  + ]:        815 :     if (attrib_in[0]) {
    3259                 :        164 :         attrib = PyDict_New();
    3260         [ -  + ]:        164 :         if (!attrib) {
    3261                 :          0 :             Py_DECREF(tag);
    3262                 :          0 :             return;
    3263                 :            :         }
    3264   [ +  +  +  - ]:        378 :         while (attrib_in[0] && attrib_in[1]) {
    3265                 :        214 :             PyObject* key = makeuniversal(self, attrib_in[0]);
    3266                 :        214 :             PyObject* value = PyUnicode_DecodeUTF8(attrib_in[1], strlen(attrib_in[1]), "strict");
    3267   [ +  -  -  + ]:        214 :             if (!key || !value) {
    3268                 :          0 :                 Py_XDECREF(value);
    3269                 :          0 :                 Py_XDECREF(key);
    3270                 :          0 :                 Py_DECREF(attrib);
    3271                 :          0 :                 Py_DECREF(tag);
    3272                 :          0 :                 return;
    3273                 :            :             }
    3274                 :        214 :             ok = PyDict_SetItem(attrib, key, value);
    3275                 :        214 :             Py_DECREF(value);
    3276                 :        214 :             Py_DECREF(key);
    3277         [ -  + ]:        214 :             if (ok < 0) {
    3278                 :          0 :                 Py_DECREF(attrib);
    3279                 :          0 :                 Py_DECREF(tag);
    3280                 :          0 :                 return;
    3281                 :            :             }
    3282                 :        214 :             attrib_in += 2;
    3283                 :            :         }
    3284                 :            :     } else {
    3285                 :        651 :         attrib = NULL;
    3286                 :            :     }
    3287                 :            : 
    3288         [ +  + ]:        815 :     if (TreeBuilder_CheckExact(self->target)) {
    3289                 :            :         /* shortcut */
    3290                 :        673 :         res = treebuilder_handle_start((TreeBuilderObject*) self->target,
    3291                 :            :                                        tag, attrib);
    3292                 :            :     }
    3293         [ +  + ]:        142 :     else if (self->handle_start) {
    3294         [ +  + ]:        128 :         if (attrib == NULL) {
    3295                 :         84 :             attrib = PyDict_New();
    3296         [ -  + ]:         84 :             if (!attrib) {
    3297                 :          0 :                 Py_DECREF(tag);
    3298                 :          0 :                 return;
    3299                 :            :             }
    3300                 :            :         }
    3301                 :        128 :         res = PyObject_CallFunctionObjArgs(self->handle_start,
    3302                 :            :                                            tag, attrib, NULL);
    3303                 :            :     } else
    3304                 :         14 :         res = NULL;
    3305                 :            : 
    3306                 :        815 :     Py_DECREF(tag);
    3307                 :        815 :     Py_XDECREF(attrib);
    3308                 :            : 
    3309                 :        815 :     Py_XDECREF(res);
    3310                 :            : }
    3311                 :            : 
    3312                 :            : static void
    3313                 :       1224 : expat_data_handler(XMLParserObject* self, const XML_Char* data_in,
    3314                 :            :                    int data_len)
    3315                 :            : {
    3316                 :            :     PyObject* data;
    3317                 :            :     PyObject* res;
    3318                 :            : 
    3319         [ -  + ]:       1224 :     if (PyErr_Occurred())
    3320                 :          0 :         return;
    3321                 :            : 
    3322                 :       1224 :     data = PyUnicode_DecodeUTF8(data_in, data_len, "strict");
    3323         [ -  + ]:       1224 :     if (!data)
    3324                 :          0 :         return; /* parser will look for errors */
    3325                 :            : 
    3326         [ +  + ]:       1224 :     if (TreeBuilder_CheckExact(self->target))
    3327                 :            :         /* shortcut */
    3328                 :        896 :         res = treebuilder_handle_data((TreeBuilderObject*) self->target, data);
    3329         [ +  + ]:        328 :     else if (self->handle_data)
    3330                 :        304 :         res = PyObject_CallOneArg(self->handle_data, data);
    3331                 :            :     else
    3332                 :         24 :         res = NULL;
    3333                 :            : 
    3334                 :       1224 :     Py_DECREF(data);
    3335                 :            : 
    3336                 :       1224 :     Py_XDECREF(res);
    3337                 :            : }
    3338                 :            : 
    3339                 :            : static void
    3340                 :        813 : expat_end_handler(XMLParserObject* self, const XML_Char* tag_in)
    3341                 :            : {
    3342                 :            :     PyObject* tag;
    3343                 :        813 :     PyObject* res = NULL;
    3344                 :            : 
    3345         [ +  + ]:        813 :     if (PyErr_Occurred())
    3346                 :          3 :         return;
    3347                 :            : 
    3348         [ +  + ]:        810 :     if (TreeBuilder_CheckExact(self->target))
    3349                 :            :         /* shortcut */
    3350                 :            :         /* the standard tree builder doesn't look at the end tag */
    3351                 :        668 :         res = treebuilder_handle_end(
    3352                 :        668 :             (TreeBuilderObject*) self->target, Py_None
    3353                 :            :             );
    3354         [ +  + ]:        142 :     else if (self->handle_end) {
    3355                 :        128 :         tag = makeuniversal(self, tag_in);
    3356         [ +  - ]:        128 :         if (tag) {
    3357                 :        128 :             res = PyObject_CallOneArg(self->handle_end, tag);
    3358                 :        128 :             Py_DECREF(tag);
    3359                 :            :         }
    3360                 :            :     }
    3361                 :            : 
    3362                 :        810 :     Py_XDECREF(res);
    3363                 :            : }
    3364                 :            : 
    3365                 :            : static void
    3366                 :         96 : expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix_in,
    3367                 :            :                        const XML_Char *uri_in)
    3368                 :            : {
    3369                 :         96 :     PyObject* res = NULL;
    3370                 :            :     PyObject* uri;
    3371                 :            :     PyObject* prefix;
    3372                 :            :     PyObject* stack[2];
    3373                 :            : 
    3374         [ -  + ]:         96 :     if (PyErr_Occurred())
    3375                 :          0 :         return;
    3376                 :            : 
    3377         [ +  + ]:         96 :     if (!uri_in)
    3378                 :         10 :         uri_in = "";
    3379         [ +  + ]:         96 :     if (!prefix_in)
    3380                 :         29 :         prefix_in = "";
    3381                 :            : 
    3382         [ +  + ]:         96 :     if (TreeBuilder_CheckExact(self->target)) {
    3383                 :            :         /* shortcut - TreeBuilder does not actually implement .start_ns() */
    3384                 :          9 :         TreeBuilderObject *target = (TreeBuilderObject*) self->target;
    3385                 :            : 
    3386   [ +  -  +  - ]:          9 :         if (target->events_append && target->start_ns_event_obj) {
    3387                 :          9 :             prefix = PyUnicode_DecodeUTF8(prefix_in, strlen(prefix_in), "strict");
    3388         [ -  + ]:          9 :             if (!prefix)
    3389                 :          0 :                 return;
    3390                 :          9 :             uri = PyUnicode_DecodeUTF8(uri_in, strlen(uri_in), "strict");
    3391         [ -  + ]:          9 :             if (!uri) {
    3392                 :          0 :                 Py_DECREF(prefix);
    3393                 :          0 :                 return;
    3394                 :            :             }
    3395                 :            : 
    3396                 :          9 :             res = treebuilder_handle_start_ns(target, prefix, uri);
    3397                 :          9 :             Py_DECREF(uri);
    3398                 :          9 :             Py_DECREF(prefix);
    3399                 :            :         }
    3400         [ +  + ]:         87 :     } else if (self->handle_start_ns) {
    3401                 :         84 :         prefix = PyUnicode_DecodeUTF8(prefix_in, strlen(prefix_in), "strict");
    3402         [ -  + ]:         84 :         if (!prefix)
    3403                 :          0 :             return;
    3404                 :         84 :         uri = PyUnicode_DecodeUTF8(uri_in, strlen(uri_in), "strict");
    3405         [ -  + ]:         84 :         if (!uri) {
    3406                 :          0 :             Py_DECREF(prefix);
    3407                 :          0 :             return;
    3408                 :            :         }
    3409                 :            : 
    3410                 :         84 :         stack[0] = prefix;
    3411                 :         84 :         stack[1] = uri;
    3412                 :         84 :         res = _PyObject_FastCall(self->handle_start_ns, stack, 2);
    3413                 :         84 :         Py_DECREF(uri);
    3414                 :         84 :         Py_DECREF(prefix);
    3415                 :            :     }
    3416                 :            : 
    3417                 :         96 :     Py_XDECREF(res);
    3418                 :            : }
    3419                 :            : 
    3420                 :            : static void
    3421                 :         96 : expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
    3422                 :            : {
    3423                 :         96 :     PyObject *res = NULL;
    3424                 :            :     PyObject* prefix;
    3425                 :            : 
    3426         [ -  + ]:         96 :     if (PyErr_Occurred())
    3427                 :          0 :         return;
    3428                 :            : 
    3429         [ +  + ]:         96 :     if (!prefix_in)
    3430                 :         29 :         prefix_in = "";
    3431                 :            : 
    3432         [ +  + ]:         96 :     if (TreeBuilder_CheckExact(self->target)) {
    3433                 :            :         /* shortcut - TreeBuilder does not actually implement .end_ns() */
    3434                 :          9 :         TreeBuilderObject *target = (TreeBuilderObject*) self->target;
    3435                 :            : 
    3436   [ +  -  +  + ]:          9 :         if (target->events_append && target->end_ns_event_obj) {
    3437                 :          5 :             res = treebuilder_handle_end_ns(target, Py_None);
    3438                 :            :         }
    3439         [ +  + ]:         87 :     } else if (self->handle_end_ns) {
    3440                 :          4 :         prefix = PyUnicode_DecodeUTF8(prefix_in, strlen(prefix_in), "strict");
    3441         [ -  + ]:          4 :         if (!prefix)
    3442                 :          0 :             return;
    3443                 :            : 
    3444                 :          4 :         res = PyObject_CallOneArg(self->handle_end_ns, prefix);
    3445                 :          4 :         Py_DECREF(prefix);
    3446                 :            :     }
    3447                 :            : 
    3448                 :         96 :     Py_XDECREF(res);
    3449                 :            : }
    3450                 :            : 
    3451                 :            : static void
    3452                 :         41 : expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in)
    3453                 :            : {
    3454                 :            :     PyObject* comment;
    3455                 :            :     PyObject* res;
    3456                 :            : 
    3457         [ -  + ]:         41 :     if (PyErr_Occurred())
    3458                 :          0 :         return;
    3459                 :            : 
    3460         [ +  + ]:         41 :     if (TreeBuilder_CheckExact(self->target)) {
    3461                 :            :         /* shortcut */
    3462                 :         28 :         TreeBuilderObject *target = (TreeBuilderObject*) self->target;
    3463                 :            : 
    3464                 :         28 :         comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict");
    3465         [ -  + ]:         28 :         if (!comment)
    3466                 :          0 :             return; /* parser will look for errors */
    3467                 :            : 
    3468                 :         28 :         res = treebuilder_handle_comment(target,  comment);
    3469                 :         28 :         Py_XDECREF(res);
    3470                 :         28 :         Py_DECREF(comment);
    3471         [ +  - ]:         13 :     } else if (self->handle_comment) {
    3472                 :         13 :         comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict");
    3473         [ -  + ]:         13 :         if (!comment)
    3474                 :          0 :             return;
    3475                 :            : 
    3476                 :         13 :         res = PyObject_CallOneArg(self->handle_comment, comment);
    3477                 :         13 :         Py_XDECREF(res);
    3478                 :         13 :         Py_DECREF(comment);
    3479                 :            :     }
    3480                 :            : }
    3481                 :            : 
    3482                 :            : static void
    3483                 :         35 : expat_start_doctype_handler(XMLParserObject *self,
    3484                 :            :                             const XML_Char *doctype_name,
    3485                 :            :                             const XML_Char *sysid,
    3486                 :            :                             const XML_Char *pubid,
    3487                 :            :                             int has_internal_subset)
    3488                 :            : {
    3489                 :            :     _Py_IDENTIFIER(doctype);
    3490                 :            :     PyObject *doctype_name_obj, *sysid_obj, *pubid_obj;
    3491                 :            :     PyObject *res;
    3492                 :            : 
    3493         [ -  + ]:         35 :     if (PyErr_Occurred())
    3494                 :          0 :         return;
    3495                 :            : 
    3496                 :         35 :     doctype_name_obj = makeuniversal(self, doctype_name);
    3497         [ -  + ]:         35 :     if (!doctype_name_obj)
    3498                 :          0 :         return;
    3499                 :            : 
    3500         [ +  + ]:         35 :     if (sysid) {
    3501                 :         23 :         sysid_obj = makeuniversal(self, sysid);
    3502         [ -  + ]:         23 :         if (!sysid_obj) {
    3503                 :          0 :             Py_DECREF(doctype_name_obj);
    3504                 :          0 :             return;
    3505                 :            :         }
    3506                 :            :     } else {
    3507                 :         12 :         Py_INCREF(Py_None);
    3508                 :         12 :         sysid_obj = Py_None;
    3509                 :            :     }
    3510                 :            : 
    3511         [ +  + ]:         35 :     if (pubid) {
    3512                 :         19 :         pubid_obj = makeuniversal(self, pubid);
    3513         [ -  + ]:         19 :         if (!pubid_obj) {
    3514                 :          0 :             Py_DECREF(doctype_name_obj);
    3515                 :          0 :             Py_DECREF(sysid_obj);
    3516                 :          0 :             return;
    3517                 :            :         }
    3518                 :            :     } else {
    3519                 :         16 :         Py_INCREF(Py_None);
    3520                 :         16 :         pubid_obj = Py_None;
    3521                 :            :     }
    3522                 :            : 
    3523                 :            :     /* If the target has a handler for doctype, call it. */
    3524         [ +  + ]:         35 :     if (self->handle_doctype) {
    3525                 :          7 :         res = PyObject_CallFunctionObjArgs(self->handle_doctype,
    3526                 :            :                                            doctype_name_obj, pubid_obj,
    3527                 :            :                                            sysid_obj, NULL);
    3528                 :          7 :         Py_XDECREF(res);
    3529                 :            :     }
    3530         [ +  + ]:         28 :     else if (_PyObject_LookupAttrId((PyObject *)self, &PyId_doctype, &res) > 0) {
    3531                 :          1 :         (void)PyErr_WarnEx(PyExc_RuntimeWarning,
    3532                 :            :                 "The doctype() method of XMLParser is ignored.  "
    3533                 :            :                 "Define doctype() method on the TreeBuilder target.",
    3534                 :            :                 1);
    3535                 :          1 :         Py_DECREF(res);
    3536                 :            :     }
    3537                 :            : 
    3538                 :         35 :     Py_DECREF(doctype_name_obj);
    3539                 :         35 :     Py_DECREF(pubid_obj);
    3540                 :         35 :     Py_DECREF(sysid_obj);
    3541                 :            : }
    3542                 :            : 
    3543                 :            : static void
    3544                 :         19 : expat_pi_handler(XMLParserObject* self, const XML_Char* target_in,
    3545                 :            :                  const XML_Char* data_in)
    3546                 :            : {
    3547                 :            :     PyObject* pi_target;
    3548                 :            :     PyObject* data;
    3549                 :            :     PyObject* res;
    3550                 :            :     PyObject* stack[2];
    3551                 :            : 
    3552         [ -  + ]:         19 :     if (PyErr_Occurred())
    3553                 :          0 :         return;
    3554                 :            : 
    3555         [ +  + ]:         19 :     if (TreeBuilder_CheckExact(self->target)) {
    3556                 :            :         /* shortcut */
    3557                 :          9 :         TreeBuilderObject *target = (TreeBuilderObject*) self->target;
    3558                 :            : 
    3559   [ +  +  +  +  :          9 :         if ((target->events_append && target->pi_event_obj) || target->insert_pis) {
                   +  + ]
    3560                 :          3 :             pi_target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict");
    3561         [ -  + ]:          3 :             if (!pi_target)
    3562                 :          0 :                 goto error;
    3563                 :          3 :             data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict");
    3564         [ -  + ]:          3 :             if (!data)
    3565                 :          0 :                 goto error;
    3566                 :          3 :             res = treebuilder_handle_pi(target, pi_target, data);
    3567                 :          3 :             Py_XDECREF(res);
    3568                 :          3 :             Py_DECREF(data);
    3569                 :          3 :             Py_DECREF(pi_target);
    3570                 :            :         }
    3571         [ +  - ]:         10 :     } else if (self->handle_pi) {
    3572                 :         10 :         pi_target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict");
    3573         [ -  + ]:         10 :         if (!pi_target)
    3574                 :          0 :             goto error;
    3575                 :         10 :         data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict");
    3576         [ -  + ]:         10 :         if (!data)
    3577                 :          0 :             goto error;
    3578                 :            : 
    3579                 :         10 :         stack[0] = pi_target;
    3580                 :         10 :         stack[1] = data;
    3581                 :         10 :         res = _PyObject_FastCall(self->handle_pi, stack, 2);
    3582                 :         10 :         Py_XDECREF(res);
    3583                 :         10 :         Py_DECREF(data);
    3584                 :         10 :         Py_DECREF(pi_target);
    3585                 :            :     }
    3586                 :            : 
    3587                 :         19 :     return;
    3588                 :            : 
    3589                 :          0 :   error:
    3590                 :          0 :     Py_XDECREF(pi_target);
    3591                 :          0 :     return;
    3592                 :            : }
    3593                 :            : 
    3594                 :            : /* -------------------------------------------------------------------- */
    3595                 :            : 
    3596                 :            : static PyObject *
    3597                 :        453 : xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    3598                 :            : {
    3599                 :        453 :     XMLParserObject *self = (XMLParserObject *)type->tp_alloc(type, 0);
    3600         [ +  - ]:        453 :     if (self) {
    3601                 :        453 :         self->parser = NULL;
    3602                 :        453 :         self->target = self->entity = self->names = NULL;
    3603                 :        453 :         self->handle_start_ns = self->handle_end_ns = NULL;
    3604                 :        453 :         self->handle_start = self->handle_data = self->handle_end = NULL;
    3605                 :        453 :         self->handle_comment = self->handle_pi = self->handle_close = NULL;
    3606                 :        453 :         self->handle_doctype = NULL;
    3607                 :            :     }
    3608                 :        453 :     return (PyObject *)self;
    3609                 :            : }
    3610                 :            : 
    3611                 :            : static int
    3612                 :       4048 : ignore_attribute_error(PyObject *value)
    3613                 :            : {
    3614         [ +  + ]:       4048 :     if (value == NULL) {
    3615         [ +  + ]:       1364 :         if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
    3616                 :          5 :             return -1;
    3617                 :            :         }
    3618                 :       1359 :         PyErr_Clear();
    3619                 :            :     }
    3620                 :       4043 :     return 0;
    3621                 :            : }
    3622                 :            : 
    3623                 :            : /*[clinic input]
    3624                 :            : _elementtree.XMLParser.__init__
    3625                 :            : 
    3626                 :            :     *
    3627                 :            :     target: object = None
    3628                 :            :     encoding: str(accept={str, NoneType}) = None
    3629                 :            : 
    3630                 :            : [clinic start generated code]*/
    3631                 :            : 
    3632                 :            : static int
    3633                 :        452 : _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target,
    3634                 :            :                                      const char *encoding)
    3635                 :            : /*[clinic end generated code: output=3ae45ec6cdf344e4 input=7e716dd6e4f3e439]*/
    3636                 :            : {
    3637                 :        452 :     self->entity = PyDict_New();
    3638         [ -  + ]:        452 :     if (!self->entity)
    3639                 :          0 :         return -1;
    3640                 :            : 
    3641                 :        452 :     self->names = PyDict_New();
    3642         [ -  + ]:        452 :     if (!self->names) {
    3643         [ #  # ]:          0 :         Py_CLEAR(self->entity);
    3644                 :          0 :         return -1;
    3645                 :            :     }
    3646                 :            : 
    3647                 :        452 :     self->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}");
    3648         [ -  + ]:        452 :     if (!self->parser) {
    3649         [ #  # ]:          0 :         Py_CLEAR(self->entity);
    3650         [ #  # ]:          0 :         Py_CLEAR(self->names);
    3651                 :            :         PyErr_NoMemory();
    3652                 :          0 :         return -1;
    3653                 :            :     }
    3654                 :            :     /* expat < 2.1.0 has no XML_SetHashSalt() */
    3655         [ +  - ]:        452 :     if (EXPAT(SetHashSalt) != NULL) {
    3656                 :        452 :         EXPAT(SetHashSalt)(self->parser,
    3657                 :        452 :                            (unsigned long)_Py_HashSecret.expat.hashsalt);
    3658                 :            :     }
    3659                 :            : 
    3660         [ +  + ]:        452 :     if (target != Py_None) {
    3661                 :        421 :         Py_INCREF(target);
    3662                 :            :     } else {
    3663                 :         31 :         target = treebuilder_new(&TreeBuilder_Type, NULL, NULL);
    3664         [ -  + ]:         31 :         if (!target) {
    3665         [ #  # ]:          0 :             Py_CLEAR(self->entity);
    3666         [ #  # ]:          0 :             Py_CLEAR(self->names);
    3667                 :          0 :             return -1;
    3668                 :            :         }
    3669                 :            :     }
    3670                 :        452 :     self->target = target;
    3671                 :            : 
    3672                 :        452 :     self->handle_start_ns = PyObject_GetAttrString(target, "start_ns");
    3673         [ -  + ]:        452 :     if (ignore_attribute_error(self->handle_start_ns)) {
    3674                 :          0 :         return -1;
    3675                 :            :     }
    3676                 :        452 :     self->handle_end_ns = PyObject_GetAttrString(target, "end_ns");
    3677         [ -  + ]:        452 :     if (ignore_attribute_error(self->handle_end_ns)) {
    3678                 :          0 :         return -1;
    3679                 :            :     }
    3680                 :        452 :     self->handle_start = PyObject_GetAttrString(target, "start");
    3681         [ +  + ]:        452 :     if (ignore_attribute_error(self->handle_start)) {
    3682                 :          1 :         return -1;
    3683                 :            :     }
    3684                 :        451 :     self->handle_data = PyObject_GetAttrString(target, "data");
    3685         [ +  + ]:        451 :     if (ignore_attribute_error(self->handle_data)) {
    3686                 :          1 :         return -1;
    3687                 :            :     }
    3688                 :        450 :     self->handle_end = PyObject_GetAttrString(target, "end");
    3689         [ +  + ]:        450 :     if (ignore_attribute_error(self->handle_end)) {
    3690                 :          1 :         return -1;
    3691                 :            :     }
    3692                 :        449 :     self->handle_comment = PyObject_GetAttrString(target, "comment");
    3693         [ +  + ]:        449 :     if (ignore_attribute_error(self->handle_comment)) {
    3694                 :          1 :         return -1;
    3695                 :            :     }
    3696                 :        448 :     self->handle_pi = PyObject_GetAttrString(target, "pi");
    3697         [ +  + ]:        448 :     if (ignore_attribute_error(self->handle_pi)) {
    3698                 :          1 :         return -1;
    3699                 :            :     }
    3700                 :        447 :     self->handle_close = PyObject_GetAttrString(target, "close");
    3701         [ -  + ]:        447 :     if (ignore_attribute_error(self->handle_close)) {
    3702                 :          0 :         return -1;
    3703                 :            :     }
    3704                 :        447 :     self->handle_doctype = PyObject_GetAttrString(target, "doctype");
    3705         [ -  + ]:        447 :     if (ignore_attribute_error(self->handle_doctype)) {
    3706                 :          0 :         return -1;
    3707                 :            :     }
    3708                 :            : 
    3709                 :            :     /* configure parser */
    3710                 :        447 :     EXPAT(SetUserData)(self->parser, self);
    3711   [ +  +  +  + ]:        447 :     if (self->handle_start_ns || self->handle_end_ns)
    3712                 :         35 :         EXPAT(SetNamespaceDeclHandler)(
    3713                 :            :             self->parser,
    3714                 :            :             (XML_StartNamespaceDeclHandler) expat_start_ns_handler,
    3715                 :            :             (XML_EndNamespaceDeclHandler) expat_end_ns_handler
    3716                 :            :             );
    3717                 :        447 :     EXPAT(SetElementHandler)(
    3718                 :            :         self->parser,
    3719                 :            :         (XML_StartElementHandler) expat_start_handler,
    3720                 :            :         (XML_EndElementHandler) expat_end_handler
    3721                 :            :         );
    3722                 :        447 :     EXPAT(SetDefaultHandlerExpand)(
    3723                 :            :         self->parser,
    3724                 :            :         (XML_DefaultHandler) expat_default_handler
    3725                 :            :         );
    3726                 :        447 :     EXPAT(SetCharacterDataHandler)(
    3727                 :            :         self->parser,
    3728                 :            :         (XML_CharacterDataHandler) expat_data_handler
    3729                 :            :         );
    3730         [ +  + ]:        447 :     if (self->handle_comment)
    3731                 :        438 :         EXPAT(SetCommentHandler)(
    3732                 :            :             self->parser,
    3733                 :            :             (XML_CommentHandler) expat_comment_handler
    3734                 :            :             );
    3735         [ +  + ]:        447 :     if (self->handle_pi)
    3736                 :        438 :         EXPAT(SetProcessingInstructionHandler)(
    3737                 :            :             self->parser,
    3738                 :            :             (XML_ProcessingInstructionHandler) expat_pi_handler
    3739                 :            :             );
    3740                 :        447 :     EXPAT(SetStartDoctypeDeclHandler)(
    3741                 :            :         self->parser,
    3742                 :            :         (XML_StartDoctypeDeclHandler) expat_start_doctype_handler
    3743                 :            :         );
    3744                 :        447 :     EXPAT(SetUnknownEncodingHandler)(
    3745                 :            :         self->parser,
    3746                 :        447 :         EXPAT(DefaultUnknownEncodingHandler), NULL
    3747                 :            :         );
    3748                 :            : 
    3749                 :        447 :     return 0;
    3750                 :            : }
    3751                 :            : 
    3752                 :            : static int
    3753                 :         16 : xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg)
    3754                 :            : {
    3755   [ +  +  -  + ]:         16 :     Py_VISIT(self->handle_close);
    3756   [ +  +  -  + ]:         16 :     Py_VISIT(self->handle_pi);
    3757   [ +  +  -  + ]:         16 :     Py_VISIT(self->handle_comment);
    3758   [ +  +  -  + ]:         16 :     Py_VISIT(self->handle_end);
    3759   [ +  +  -  + ]:         16 :     Py_VISIT(self->handle_data);
    3760   [ +  +  -  + ]:         16 :     Py_VISIT(self->handle_start);
    3761   [ +  +  -  + ]:         16 :     Py_VISIT(self->handle_start_ns);
    3762   [ +  +  -  + ]:         16 :     Py_VISIT(self->handle_end_ns);
    3763   [ +  +  -  + ]:         16 :     Py_VISIT(self->handle_doctype);
    3764                 :            : 
    3765   [ +  -  -  + ]:         16 :     Py_VISIT(self->target);
    3766   [ +  -  -  + ]:         16 :     Py_VISIT(self->entity);
    3767   [ +  -  -  + ]:         16 :     Py_VISIT(self->names);
    3768                 :            : 
    3769                 :         16 :     return 0;
    3770                 :            : }
    3771                 :            : 
    3772                 :            : static int
    3773                 :        454 : xmlparser_gc_clear(XMLParserObject *self)
    3774                 :            : {
    3775         [ +  + ]:        454 :     if (self->parser != NULL) {
    3776                 :        452 :         XML_Parser parser = self->parser;
    3777                 :        452 :         self->parser = NULL;
    3778                 :        452 :         EXPAT(ParserFree)(parser);
    3779                 :            :     }
    3780                 :            : 
    3781         [ +  + ]:        454 :     Py_CLEAR(self->handle_close);
    3782         [ +  + ]:        454 :     Py_CLEAR(self->handle_pi);
    3783         [ +  + ]:        454 :     Py_CLEAR(self->handle_comment);
    3784         [ +  + ]:        454 :     Py_CLEAR(self->handle_end);
    3785         [ +  + ]:        454 :     Py_CLEAR(self->handle_data);
    3786         [ +  + ]:        454 :     Py_CLEAR(self->handle_start);
    3787         [ +  + ]:        454 :     Py_CLEAR(self->handle_start_ns);
    3788         [ +  + ]:        454 :     Py_CLEAR(self->handle_end_ns);
    3789         [ +  + ]:        454 :     Py_CLEAR(self->handle_doctype);
    3790                 :            : 
    3791         [ +  + ]:        454 :     Py_CLEAR(self->target);
    3792         [ +  + ]:        454 :     Py_CLEAR(self->entity);
    3793         [ +  + ]:        454 :     Py_CLEAR(self->names);
    3794                 :            : 
    3795                 :        454 :     return 0;
    3796                 :            : }
    3797                 :            : 
    3798                 :            : static void
    3799                 :        453 : xmlparser_dealloc(XMLParserObject* self)
    3800                 :            : {
    3801                 :        453 :     PyObject_GC_UnTrack(self);
    3802                 :        453 :     xmlparser_gc_clear(self);
    3803                 :        453 :     Py_TYPE(self)->tp_free((PyObject *)self);
    3804                 :        453 : }
    3805                 :            : 
    3806                 :            : Py_LOCAL_INLINE(int)
    3807                 :       1019 : _check_xmlparser(XMLParserObject* self)
    3808                 :            : {
    3809         [ +  + ]:       1019 :     if (self->target == NULL) {
    3810                 :          4 :         PyErr_SetString(PyExc_ValueError,
    3811                 :            :                         "XMLParser.__init__() wasn't called");
    3812                 :          4 :         return 0;
    3813                 :            :     }
    3814                 :       1015 :     return 1;
    3815                 :            : }
    3816                 :            : 
    3817                 :            : LOCAL(PyObject*)
    3818                 :        996 : expat_parse(XMLParserObject* self, const char* data, int data_len, int final)
    3819                 :            : {
    3820                 :            :     int ok;
    3821                 :            : 
    3822                 :            :     assert(!PyErr_Occurred());
    3823                 :        996 :     ok = EXPAT(Parse)(self->parser, data, data_len, final);
    3824                 :            : 
    3825         [ +  + ]:        996 :     if (PyErr_Occurred())
    3826                 :         23 :         return NULL;
    3827                 :            : 
    3828         [ +  + ]:        973 :     if (!ok) {
    3829                 :         19 :         expat_set_error(
    3830                 :         19 :             EXPAT(GetErrorCode)(self->parser),
    3831                 :         19 :             EXPAT(GetErrorLineNumber)(self->parser),
    3832                 :         19 :             EXPAT(GetErrorColumnNumber)(self->parser),
    3833                 :            :             NULL
    3834                 :            :             );
    3835                 :         19 :         return NULL;
    3836                 :            :     }
    3837                 :            : 
    3838                 :        954 :     Py_RETURN_NONE;
    3839                 :            : }
    3840                 :            : 
    3841                 :            : /*[clinic input]
    3842                 :            : _elementtree.XMLParser.close
    3843                 :            : 
    3844                 :            : [clinic start generated code]*/
    3845                 :            : 
    3846                 :            : static PyObject *
    3847                 :        364 : _elementtree_XMLParser_close_impl(XMLParserObject *self)
    3848                 :            : /*[clinic end generated code: output=d68d375dd23bc7fb input=ca7909ca78c3abfe]*/
    3849                 :            : {
    3850                 :            :     /* end feeding data to parser */
    3851                 :            : 
    3852                 :            :     PyObject* res;
    3853                 :            : 
    3854         [ +  + ]:        364 :     if (!_check_xmlparser(self)) {
    3855                 :          1 :         return NULL;
    3856                 :            :     }
    3857                 :        363 :     res = expat_parse(self, "", 0, 1);
    3858         [ +  + ]:        363 :     if (!res)
    3859                 :          2 :         return NULL;
    3860                 :            : 
    3861         [ +  + ]:        361 :     if (TreeBuilder_CheckExact(self->target)) {
    3862                 :        318 :         Py_DECREF(res);
    3863                 :        318 :         return treebuilder_done((TreeBuilderObject*) self->target);
    3864                 :            :     }
    3865         [ +  + ]:         43 :     else if (self->handle_close) {
    3866                 :         15 :         Py_DECREF(res);
    3867                 :         15 :         return PyObject_CallNoArgs(self->handle_close);
    3868                 :            :     }
    3869                 :            :     else {
    3870                 :         28 :         return res;
    3871                 :            :     }
    3872                 :            : }
    3873                 :            : 
    3874                 :            : /*[clinic input]
    3875                 :            : _elementtree.XMLParser.feed
    3876                 :            : 
    3877                 :            :     data: object
    3878                 :            :     /
    3879                 :            : 
    3880                 :            : [clinic start generated code]*/
    3881                 :            : 
    3882                 :            : static PyObject *
    3883                 :        596 : _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
    3884                 :            : /*[clinic end generated code: output=e42b6a78eec7446d input=fe231b6b8de3ce1f]*/
    3885                 :            : {
    3886                 :            :     /* feed data to parser */
    3887                 :            : 
    3888         [ +  + ]:        596 :     if (!_check_xmlparser(self)) {
    3889                 :          1 :         return NULL;
    3890                 :            :     }
    3891         [ +  + ]:        595 :     if (PyUnicode_Check(data)) {
    3892                 :            :         Py_ssize_t data_len;
    3893                 :        441 :         const char *data_ptr = PyUnicode_AsUTF8AndSize(data, &data_len);
    3894         [ -  + ]:        441 :         if (data_ptr == NULL)
    3895                 :          0 :             return NULL;
    3896         [ -  + ]:        441 :         if (data_len > INT_MAX) {
    3897                 :          0 :             PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
    3898                 :          0 :             return NULL;
    3899                 :            :         }
    3900                 :            :         /* Explicitly set UTF-8 encoding. Return code ignored. */
    3901                 :        441 :         (void)EXPAT(SetEncoding)(self->parser, "utf-8");
    3902                 :        441 :         return expat_parse(self, data_ptr, (int)data_len, 0);
    3903                 :            :     }
    3904                 :            :     else {
    3905                 :            :         Py_buffer view;
    3906                 :            :         PyObject *res;
    3907         [ -  + ]:        154 :         if (PyObject_GetBuffer(data, &view, PyBUF_SIMPLE) < 0)
    3908                 :          0 :             return NULL;
    3909         [ -  + ]:        154 :         if (view.len > INT_MAX) {
    3910                 :          0 :             PyBuffer_Release(&view);
    3911                 :          0 :             PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
    3912                 :          0 :             return NULL;
    3913                 :            :         }
    3914                 :        154 :         res = expat_parse(self, view.buf, (int)view.len, 0);
    3915                 :        154 :         PyBuffer_Release(&view);
    3916                 :        154 :         return res;
    3917                 :            :     }
    3918                 :            : }
    3919                 :            : 
    3920                 :            : /*[clinic input]
    3921                 :            : _elementtree.XMLParser._parse_whole
    3922                 :            : 
    3923                 :            :     file: object
    3924                 :            :     /
    3925                 :            : 
    3926                 :            : [clinic start generated code]*/
    3927                 :            : 
    3928                 :            : static PyObject *
    3929                 :         21 : _elementtree_XMLParser__parse_whole(XMLParserObject *self, PyObject *file)
    3930                 :            : /*[clinic end generated code: output=f797197bb818dda3 input=19ecc893b6f3e752]*/
    3931                 :            : {
    3932                 :            :     /* (internal) parse the whole input, until end of stream */
    3933                 :            :     PyObject* reader;
    3934                 :            :     PyObject* buffer;
    3935                 :            :     PyObject* temp;
    3936                 :            :     PyObject* res;
    3937                 :            : 
    3938         [ +  + ]:         21 :     if (!_check_xmlparser(self)) {
    3939                 :          1 :         return NULL;
    3940                 :            :     }
    3941                 :         20 :     reader = PyObject_GetAttrString(file, "read");
    3942         [ +  - ]:         20 :     if (!reader)
    3943                 :          0 :         return NULL;
    3944                 :            : 
    3945                 :            :     /* read from open file object */
    3946                 :            :     for (;;) {
    3947                 :            : 
    3948                 :         39 :         buffer = PyObject_CallFunction(reader, "i", 64*1024);
    3949                 :            : 
    3950         [ +  + ]:         39 :         if (!buffer) {
    3951                 :            :             /* read failed (e.g. due to KeyboardInterrupt) */
    3952                 :          1 :             Py_DECREF(reader);
    3953                 :          1 :             return NULL;
    3954                 :            :         }
    3955                 :            : 
    3956         [ +  + ]:         38 :         if (PyUnicode_CheckExact(buffer)) {
    3957                 :            :             /* A unicode object is encoded into bytes using UTF-8 */
    3958         [ +  + ]:          4 :             if (PyUnicode_GET_LENGTH(buffer) == 0) {
    3959                 :          2 :                 Py_DECREF(buffer);
    3960                 :          2 :                 break;
    3961                 :            :             }
    3962                 :          2 :             temp = PyUnicode_AsEncodedString(buffer, "utf-8", "surrogatepass");
    3963                 :          2 :             Py_DECREF(buffer);
    3964         [ -  + ]:          2 :             if (!temp) {
    3965                 :            :                 /* Propagate exception from PyUnicode_AsEncodedString */
    3966                 :          0 :                 Py_DECREF(reader);
    3967                 :          0 :                 return NULL;
    3968                 :            :             }
    3969                 :          2 :             buffer = temp;
    3970                 :            :         }
    3971   [ +  -  +  + ]:         34 :         else if (!PyBytes_CheckExact(buffer) || PyBytes_GET_SIZE(buffer) == 0) {
    3972                 :         17 :             Py_DECREF(buffer);
    3973                 :         17 :             break;
    3974                 :            :         }
    3975                 :            : 
    3976         [ -  + ]:         19 :         if (PyBytes_GET_SIZE(buffer) > INT_MAX) {
    3977                 :          0 :             Py_DECREF(buffer);
    3978                 :          0 :             Py_DECREF(reader);
    3979                 :          0 :             PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
    3980                 :          0 :             return NULL;
    3981                 :            :         }
    3982                 :         19 :         res = expat_parse(
    3983                 :         19 :             self, PyBytes_AS_STRING(buffer), (int)PyBytes_GET_SIZE(buffer), 0
    3984                 :            :             );
    3985                 :            : 
    3986                 :         19 :         Py_DECREF(buffer);
    3987                 :            : 
    3988         [ -  + ]:         19 :         if (!res) {
    3989                 :          0 :             Py_DECREF(reader);
    3990                 :          0 :             return NULL;
    3991                 :            :         }
    3992                 :         19 :         Py_DECREF(res);
    3993                 :            : 
    3994                 :            :     }
    3995                 :            : 
    3996                 :         19 :     Py_DECREF(reader);
    3997                 :            : 
    3998                 :         19 :     res = expat_parse(self, "", 0, 1);
    3999                 :            : 
    4000   [ +  -  +  - ]:         19 :     if (res && TreeBuilder_CheckExact(self->target)) {
    4001                 :         19 :         Py_DECREF(res);
    4002                 :         19 :         return treebuilder_done((TreeBuilderObject*) self->target);
    4003                 :            :     }
    4004                 :            : 
    4005                 :          0 :     return res;
    4006                 :            : }
    4007                 :            : 
    4008                 :            : /*[clinic input]
    4009                 :            : _elementtree.XMLParser._setevents
    4010                 :            : 
    4011                 :            :     events_queue: object
    4012                 :            :     events_to_report: object = None
    4013                 :            :     /
    4014                 :            : 
    4015                 :            : [clinic start generated code]*/
    4016                 :            : 
    4017                 :            : static PyObject *
    4018                 :         38 : _elementtree_XMLParser__setevents_impl(XMLParserObject *self,
    4019                 :            :                                        PyObject *events_queue,
    4020                 :            :                                        PyObject *events_to_report)
    4021                 :            : /*[clinic end generated code: output=1440092922b13ed1 input=abf90830a1c3b0fc]*/
    4022                 :            : {
    4023                 :            :     /* activate element event reporting */
    4024                 :            :     Py_ssize_t i;
    4025                 :            :     TreeBuilderObject *target;
    4026                 :            :     PyObject *events_append, *events_seq;
    4027                 :            : 
    4028         [ +  + ]:         38 :     if (!_check_xmlparser(self)) {
    4029                 :          1 :         return NULL;
    4030                 :            :     }
    4031         [ -  + ]:         37 :     if (!TreeBuilder_CheckExact(self->target)) {
    4032                 :          0 :         PyErr_SetString(
    4033                 :            :             PyExc_TypeError,
    4034                 :            :             "event handling only supported for ElementTree.TreeBuilder "
    4035                 :            :             "targets"
    4036                 :            :             );
    4037                 :          0 :         return NULL;
    4038                 :            :     }
    4039                 :            : 
    4040                 :         37 :     target = (TreeBuilderObject*) self->target;
    4041                 :            : 
    4042                 :         37 :     events_append = PyObject_GetAttrString(events_queue, "append");
    4043         [ -  + ]:         37 :     if (events_append == NULL)
    4044                 :          0 :         return NULL;
    4045                 :         37 :     Py_XSETREF(target->events_append, events_append);
    4046                 :            : 
    4047                 :            :     /* clear out existing events */
    4048         [ -  + ]:         37 :     Py_CLEAR(target->start_event_obj);
    4049         [ -  + ]:         37 :     Py_CLEAR(target->end_event_obj);
    4050         [ -  + ]:         37 :     Py_CLEAR(target->start_ns_event_obj);
    4051         [ -  + ]:         37 :     Py_CLEAR(target->end_ns_event_obj);
    4052         [ -  + ]:         37 :     Py_CLEAR(target->comment_event_obj);
    4053         [ -  + ]:         37 :     Py_CLEAR(target->pi_event_obj);
    4054                 :            : 
    4055         [ -  + ]:         37 :     if (events_to_report == Py_None) {
    4056                 :            :         /* default is "end" only */
    4057                 :          0 :         target->end_event_obj = PyUnicode_FromString("end");
    4058                 :          0 :         Py_RETURN_NONE;
    4059                 :            :     }
    4060                 :            : 
    4061         [ -  + ]:         37 :     if (!(events_seq = PySequence_Fast(events_to_report,
    4062                 :            :                                        "events must be a sequence"))) {
    4063                 :          0 :         return NULL;
    4064                 :            :     }
    4065                 :            : 
    4066   [ +  +  +  + ]:         94 :     for (i = 0; i < PySequence_Fast_GET_SIZE(events_seq); ++i) {
    4067         [ +  + ]:         60 :         PyObject *event_name_obj = PySequence_Fast_GET_ITEM(events_seq, i);
    4068                 :         60 :         const char *event_name = NULL;
    4069         [ +  - ]:         60 :         if (PyUnicode_Check(event_name_obj)) {
    4070                 :         60 :             event_name = PyUnicode_AsUTF8(event_name_obj);
    4071         [ #  # ]:          0 :         } else if (PyBytes_Check(event_name_obj)) {
    4072                 :          0 :             event_name = PyBytes_AS_STRING(event_name_obj);
    4073                 :            :         }
    4074         [ -  + ]:         60 :         if (event_name == NULL) {
    4075                 :          0 :             Py_DECREF(events_seq);
    4076                 :          0 :             PyErr_Format(PyExc_ValueError, "invalid events sequence");
    4077                 :          0 :             return NULL;
    4078                 :            :         }
    4079                 :            : 
    4080                 :         60 :         Py_INCREF(event_name_obj);
    4081         [ +  + ]:         60 :         if (strcmp(event_name, "start") == 0) {
    4082                 :         14 :             Py_XSETREF(target->start_event_obj, event_name_obj);
    4083         [ +  + ]:         46 :         } else if (strcmp(event_name, "end") == 0) {
    4084                 :         28 :             Py_XSETREF(target->end_event_obj, event_name_obj);
    4085         [ +  + ]:         18 :         } else if (strcmp(event_name, "start-ns") == 0) {
    4086                 :          7 :             Py_XSETREF(target->start_ns_event_obj, event_name_obj);
    4087                 :          7 :             EXPAT(SetNamespaceDeclHandler)(
    4088                 :            :                 self->parser,
    4089                 :            :                 (XML_StartNamespaceDeclHandler) expat_start_ns_handler,
    4090                 :            :                 (XML_EndNamespaceDeclHandler) expat_end_ns_handler
    4091                 :            :                 );
    4092         [ +  + ]:         11 :         } else if (strcmp(event_name, "end-ns") == 0) {
    4093                 :          4 :             Py_XSETREF(target->end_ns_event_obj, event_name_obj);
    4094                 :          4 :             EXPAT(SetNamespaceDeclHandler)(
    4095                 :            :                 self->parser,
    4096                 :            :                 (XML_StartNamespaceDeclHandler) expat_start_ns_handler,
    4097                 :            :                 (XML_EndNamespaceDeclHandler) expat_end_ns_handler
    4098                 :            :                 );
    4099         [ +  + ]:          7 :         } else if (strcmp(event_name, "comment") == 0) {
    4100                 :          2 :             Py_XSETREF(target->comment_event_obj, event_name_obj);
    4101                 :          2 :             EXPAT(SetCommentHandler)(
    4102                 :            :                 self->parser,
    4103                 :            :                 (XML_CommentHandler) expat_comment_handler
    4104                 :            :                 );
    4105         [ +  + ]:          5 :         } else if (strcmp(event_name, "pi") == 0) {
    4106                 :          2 :             Py_XSETREF(target->pi_event_obj, event_name_obj);
    4107                 :          2 :             EXPAT(SetProcessingInstructionHandler)(
    4108                 :            :                 self->parser,
    4109                 :            :                 (XML_ProcessingInstructionHandler) expat_pi_handler
    4110                 :            :                 );
    4111                 :            :         } else {
    4112                 :          3 :             Py_DECREF(event_name_obj);
    4113                 :          3 :             Py_DECREF(events_seq);
    4114                 :          3 :             PyErr_Format(PyExc_ValueError, "unknown event '%s'", event_name);
    4115                 :          3 :             return NULL;
    4116                 :            :         }
    4117                 :            :     }
    4118                 :            : 
    4119                 :         34 :     Py_DECREF(events_seq);
    4120                 :         34 :     Py_RETURN_NONE;
    4121                 :            : }
    4122                 :            : 
    4123                 :            : static PyMemberDef xmlparser_members[] = {
    4124                 :            :     {"entity", T_OBJECT, offsetof(XMLParserObject, entity), READONLY, NULL},
    4125                 :            :     {"target", T_OBJECT, offsetof(XMLParserObject, target), READONLY, NULL},
    4126                 :            :     {NULL}
    4127                 :            : };
    4128                 :            : 
    4129                 :            : static PyObject*
    4130                 :          1 : xmlparser_version_getter(XMLParserObject *self, void *closure)
    4131                 :            : {
    4132                 :          1 :     return PyUnicode_FromFormat(
    4133                 :            :         "Expat %d.%d.%d", XML_MAJOR_VERSION,
    4134                 :            :         XML_MINOR_VERSION, XML_MICRO_VERSION);
    4135                 :            : }
    4136                 :            : 
    4137                 :            : static PyGetSetDef xmlparser_getsetlist[] = {
    4138                 :            :     {"version", (getter)xmlparser_version_getter, NULL, NULL},
    4139                 :            :     {NULL},
    4140                 :            : };
    4141                 :            : 
    4142                 :            : #include "clinic/_elementtree.c.h"
    4143                 :            : 
    4144                 :            : static PyMethodDef element_methods[] = {
    4145                 :            : 
    4146                 :            :     _ELEMENTTREE_ELEMENT_CLEAR_METHODDEF
    4147                 :            : 
    4148                 :            :     _ELEMENTTREE_ELEMENT_GET_METHODDEF
    4149                 :            :     _ELEMENTTREE_ELEMENT_SET_METHODDEF
    4150                 :            : 
    4151                 :            :     _ELEMENTTREE_ELEMENT_FIND_METHODDEF
    4152                 :            :     _ELEMENTTREE_ELEMENT_FINDTEXT_METHODDEF
    4153                 :            :     _ELEMENTTREE_ELEMENT_FINDALL_METHODDEF
    4154                 :            : 
    4155                 :            :     _ELEMENTTREE_ELEMENT_APPEND_METHODDEF
    4156                 :            :     _ELEMENTTREE_ELEMENT_EXTEND_METHODDEF
    4157                 :            :     _ELEMENTTREE_ELEMENT_INSERT_METHODDEF
    4158                 :            :     _ELEMENTTREE_ELEMENT_REMOVE_METHODDEF
    4159                 :            : 
    4160                 :            :     _ELEMENTTREE_ELEMENT_ITER_METHODDEF
    4161                 :            :     _ELEMENTTREE_ELEMENT_ITERTEXT_METHODDEF
    4162                 :            :     _ELEMENTTREE_ELEMENT_ITERFIND_METHODDEF
    4163                 :            : 
    4164                 :            :     _ELEMENTTREE_ELEMENT_ITEMS_METHODDEF
    4165                 :            :     _ELEMENTTREE_ELEMENT_KEYS_METHODDEF
    4166                 :            : 
    4167                 :            :     _ELEMENTTREE_ELEMENT_MAKEELEMENT_METHODDEF
    4168                 :            : 
    4169                 :            :     _ELEMENTTREE_ELEMENT___COPY___METHODDEF
    4170                 :            :     _ELEMENTTREE_ELEMENT___DEEPCOPY___METHODDEF
    4171                 :            :     _ELEMENTTREE_ELEMENT___SIZEOF___METHODDEF
    4172                 :            :     _ELEMENTTREE_ELEMENT___GETSTATE___METHODDEF
    4173                 :            :     _ELEMENTTREE_ELEMENT___SETSTATE___METHODDEF
    4174                 :            : 
    4175                 :            :     {NULL, NULL}
    4176                 :            : };
    4177                 :            : 
    4178                 :            : static PyMappingMethods element_as_mapping = {
    4179                 :            :     (lenfunc) element_length,
    4180                 :            :     (binaryfunc) element_subscr,
    4181                 :            :     (objobjargproc) element_ass_subscr,
    4182                 :            : };
    4183                 :            : 
    4184                 :            : static PyGetSetDef element_getsetlist[] = {
    4185                 :            :     {"tag",
    4186                 :            :         (getter)element_tag_getter,
    4187                 :            :         (setter)element_tag_setter,
    4188                 :            :         "A string identifying what kind of data this element represents"},
    4189                 :            :     {"text",
    4190                 :            :         (getter)element_text_getter,
    4191                 :            :         (setter)element_text_setter,
    4192                 :            :         "A string of text directly after the start tag, or None"},
    4193                 :            :     {"tail",
    4194                 :            :         (getter)element_tail_getter,
    4195                 :            :         (setter)element_tail_setter,
    4196                 :            :         "A string of text directly after the end tag, or None"},
    4197                 :            :     {"attrib",
    4198                 :            :         (getter)element_attrib_getter,
    4199                 :            :         (setter)element_attrib_setter,
    4200                 :            :         "A dictionary containing the element's attributes"},
    4201                 :            :     {NULL},
    4202                 :            : };
    4203                 :            : 
    4204                 :            : static PyTypeObject Element_Type = {
    4205                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
    4206                 :            :     "xml.etree.ElementTree.Element", sizeof(ElementObject), 0,
    4207                 :            :     /* methods */
    4208                 :            :     (destructor)element_dealloc,                    /* tp_dealloc */
    4209                 :            :     0,                                              /* tp_vectorcall_offset */
    4210                 :            :     0,                                              /* tp_getattr */
    4211                 :            :     0,                                              /* tp_setattr */
    4212                 :            :     0,                                              /* tp_as_async */
    4213                 :            :     (reprfunc)element_repr,                         /* tp_repr */
    4214                 :            :     0,                                              /* tp_as_number */
    4215                 :            :     &element_as_sequence,                           /* tp_as_sequence */
    4216                 :            :     &element_as_mapping,                            /* tp_as_mapping */
    4217                 :            :     0,                                              /* tp_hash */
    4218                 :            :     0,                                              /* tp_call */
    4219                 :            :     0,                                              /* tp_str */
    4220                 :            :     PyObject_GenericGetAttr,                        /* tp_getattro */
    4221                 :            :     0,                                              /* tp_setattro */
    4222                 :            :     0,                                              /* tp_as_buffer */
    4223                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
    4224                 :            :                                                     /* tp_flags */
    4225                 :            :     0,                                              /* tp_doc */
    4226                 :            :     (traverseproc)element_gc_traverse,              /* tp_traverse */
    4227                 :            :     (inquiry)element_gc_clear,                      /* tp_clear */
    4228                 :            :     0,                                              /* tp_richcompare */
    4229                 :            :     offsetof(ElementObject, weakreflist),           /* tp_weaklistoffset */
    4230                 :            :     0,                                              /* tp_iter */
    4231                 :            :     0,                                              /* tp_iternext */
    4232                 :            :     element_methods,                                /* tp_methods */
    4233                 :            :     0,                                              /* tp_members */
    4234                 :            :     element_getsetlist,                             /* tp_getset */
    4235                 :            :     0,                                              /* tp_base */
    4236                 :            :     0,                                              /* tp_dict */
    4237                 :            :     0,                                              /* tp_descr_get */
    4238                 :            :     0,                                              /* tp_descr_set */
    4239                 :            :     0,                                              /* tp_dictoffset */
    4240                 :            :     (initproc)element_init,                         /* tp_init */
    4241                 :            :     PyType_GenericAlloc,                            /* tp_alloc */
    4242                 :            :     element_new,                                    /* tp_new */
    4243                 :            :     0,                                              /* tp_free */
    4244                 :            : };
    4245                 :            : 
    4246                 :            : static PyMethodDef treebuilder_methods[] = {
    4247                 :            :     _ELEMENTTREE_TREEBUILDER_DATA_METHODDEF
    4248                 :            :     _ELEMENTTREE_TREEBUILDER_START_METHODDEF
    4249                 :            :     _ELEMENTTREE_TREEBUILDER_END_METHODDEF
    4250                 :            :     _ELEMENTTREE_TREEBUILDER_COMMENT_METHODDEF
    4251                 :            :     _ELEMENTTREE_TREEBUILDER_PI_METHODDEF
    4252                 :            :     _ELEMENTTREE_TREEBUILDER_CLOSE_METHODDEF
    4253                 :            :     {NULL, NULL}
    4254                 :            : };
    4255                 :            : 
    4256                 :            : static PyTypeObject TreeBuilder_Type = {
    4257                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
    4258                 :            :     "xml.etree.ElementTree.TreeBuilder", sizeof(TreeBuilderObject), 0,
    4259                 :            :     /* methods */
    4260                 :            :     (destructor)treebuilder_dealloc,                /* tp_dealloc */
    4261                 :            :     0,                                              /* tp_vectorcall_offset */
    4262                 :            :     0,                                              /* tp_getattr */
    4263                 :            :     0,                                              /* tp_setattr */
    4264                 :            :     0,                                              /* tp_as_async */
    4265                 :            :     0,                                              /* tp_repr */
    4266                 :            :     0,                                              /* tp_as_number */
    4267                 :            :     0,                                              /* tp_as_sequence */
    4268                 :            :     0,                                              /* tp_as_mapping */
    4269                 :            :     0,                                              /* tp_hash */
    4270                 :            :     0,                                              /* tp_call */
    4271                 :            :     0,                                              /* tp_str */
    4272                 :            :     0,                                              /* tp_getattro */
    4273                 :            :     0,                                              /* tp_setattro */
    4274                 :            :     0,                                              /* tp_as_buffer */
    4275                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
    4276                 :            :                                                     /* tp_flags */
    4277                 :            :     0,                                              /* tp_doc */
    4278                 :            :     (traverseproc)treebuilder_gc_traverse,          /* tp_traverse */
    4279                 :            :     (inquiry)treebuilder_gc_clear,                  /* tp_clear */
    4280                 :            :     0,                                              /* tp_richcompare */
    4281                 :            :     0,                                              /* tp_weaklistoffset */
    4282                 :            :     0,                                              /* tp_iter */
    4283                 :            :     0,                                              /* tp_iternext */
    4284                 :            :     treebuilder_methods,                            /* tp_methods */
    4285                 :            :     0,                                              /* tp_members */
    4286                 :            :     0,                                              /* tp_getset */
    4287                 :            :     0,                                              /* tp_base */
    4288                 :            :     0,                                              /* tp_dict */
    4289                 :            :     0,                                              /* tp_descr_get */
    4290                 :            :     0,                                              /* tp_descr_set */
    4291                 :            :     0,                                              /* tp_dictoffset */
    4292                 :            :     _elementtree_TreeBuilder___init__,              /* tp_init */
    4293                 :            :     PyType_GenericAlloc,                            /* tp_alloc */
    4294                 :            :     treebuilder_new,                                /* tp_new */
    4295                 :            :     0,                                              /* tp_free */
    4296                 :            : };
    4297                 :            : 
    4298                 :            : static PyMethodDef xmlparser_methods[] = {
    4299                 :            :     _ELEMENTTREE_XMLPARSER_FEED_METHODDEF
    4300                 :            :     _ELEMENTTREE_XMLPARSER_CLOSE_METHODDEF
    4301                 :            :     _ELEMENTTREE_XMLPARSER__PARSE_WHOLE_METHODDEF
    4302                 :            :     _ELEMENTTREE_XMLPARSER__SETEVENTS_METHODDEF
    4303                 :            :     {NULL, NULL}
    4304                 :            : };
    4305                 :            : 
    4306                 :            : static PyTypeObject XMLParser_Type = {
    4307                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
    4308                 :            :     "xml.etree.ElementTree.XMLParser", sizeof(XMLParserObject), 0,
    4309                 :            :     /* methods */
    4310                 :            :     (destructor)xmlparser_dealloc,                  /* tp_dealloc */
    4311                 :            :     0,                                              /* tp_vectorcall_offset */
    4312                 :            :     0,                                              /* tp_getattr */
    4313                 :            :     0,                                              /* tp_setattr */
    4314                 :            :     0,                                              /* tp_as_async */
    4315                 :            :     0,                                              /* tp_repr */
    4316                 :            :     0,                                              /* tp_as_number */
    4317                 :            :     0,                                              /* tp_as_sequence */
    4318                 :            :     0,                                              /* tp_as_mapping */
    4319                 :            :     0,                                              /* tp_hash */
    4320                 :            :     0,                                              /* tp_call */
    4321                 :            :     0,                                              /* tp_str */
    4322                 :            :     0,                                              /* tp_getattro */
    4323                 :            :     0,                                              /* tp_setattro */
    4324                 :            :     0,                                              /* tp_as_buffer */
    4325                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
    4326                 :            :                                                     /* tp_flags */
    4327                 :            :     0,                                              /* tp_doc */
    4328                 :            :     (traverseproc)xmlparser_gc_traverse,            /* tp_traverse */
    4329                 :            :     (inquiry)xmlparser_gc_clear,                    /* tp_clear */
    4330                 :            :     0,                                              /* tp_richcompare */
    4331                 :            :     0,                                              /* tp_weaklistoffset */
    4332                 :            :     0,                                              /* tp_iter */
    4333                 :            :     0,                                              /* tp_iternext */
    4334                 :            :     xmlparser_methods,                              /* tp_methods */
    4335                 :            :     xmlparser_members,                              /* tp_members */
    4336                 :            :     xmlparser_getsetlist,                           /* tp_getset */
    4337                 :            :     0,                                              /* tp_base */
    4338                 :            :     0,                                              /* tp_dict */
    4339                 :            :     0,                                              /* tp_descr_get */
    4340                 :            :     0,                                              /* tp_descr_set */
    4341                 :            :     0,                                              /* tp_dictoffset */
    4342                 :            :     _elementtree_XMLParser___init__,                /* tp_init */
    4343                 :            :     PyType_GenericAlloc,                            /* tp_alloc */
    4344                 :            :     xmlparser_new,                                  /* tp_new */
    4345                 :            :     0,                                              /* tp_free */
    4346                 :            : };
    4347                 :            : 
    4348                 :            : /* ==================================================================== */
    4349                 :            : /* python module interface */
    4350                 :            : 
    4351                 :            : static PyMethodDef _functions[] = {
    4352                 :            :     {"SubElement", _PyCFunction_CAST(subelement), METH_VARARGS | METH_KEYWORDS},
    4353                 :            :     _ELEMENTTREE__SET_FACTORIES_METHODDEF
    4354                 :            :     {NULL, NULL}
    4355                 :            : };
    4356                 :            : 
    4357                 :            : 
    4358                 :            : static struct PyModuleDef elementtreemodule = {
    4359                 :            :     PyModuleDef_HEAD_INIT,
    4360                 :            :     "_elementtree",
    4361                 :            :     NULL,
    4362                 :            :     sizeof(elementtreestate),
    4363                 :            :     _functions,
    4364                 :            :     NULL,
    4365                 :            :     elementtree_traverse,
    4366                 :            :     elementtree_clear,
    4367                 :            :     elementtree_free
    4368                 :            : };
    4369                 :            : 
    4370                 :            : PyMODINIT_FUNC
    4371                 :         14 : PyInit__elementtree(void)
    4372                 :            : {
    4373                 :            :     PyObject *m;
    4374                 :            :     elementtreestate *st;
    4375                 :            : 
    4376                 :         14 :     m = PyState_FindModule(&elementtreemodule);
    4377         [ +  + ]:         14 :     if (m) {
    4378                 :          1 :         Py_INCREF(m);
    4379                 :          1 :         return m;
    4380                 :            :     }
    4381                 :            : 
    4382                 :            :     /* Initialize object types */
    4383         [ -  + ]:         13 :     if (PyType_Ready(&ElementIter_Type) < 0)
    4384                 :          0 :         return NULL;
    4385         [ -  + ]:         13 :     if (PyType_Ready(&TreeBuilder_Type) < 0)
    4386                 :          0 :         return NULL;
    4387         [ -  + ]:         13 :     if (PyType_Ready(&Element_Type) < 0)
    4388                 :          0 :         return NULL;
    4389         [ -  + ]:         13 :     if (PyType_Ready(&XMLParser_Type) < 0)
    4390                 :          0 :         return NULL;
    4391                 :            : 
    4392                 :         13 :     m = PyModule_Create(&elementtreemodule);
    4393         [ -  + ]:         13 :     if (!m)
    4394                 :          0 :         return NULL;
    4395                 :         13 :     st = get_elementtree_state(m);
    4396                 :            : 
    4397                 :         13 :     st->deepcopy_obj = _PyImport_GetModuleAttrString("copy", "deepcopy");
    4398         [ -  + ]:         13 :     if (st->deepcopy_obj == NULL) {
    4399                 :          0 :         return NULL;
    4400                 :            :     }
    4401                 :            : 
    4402                 :            :     assert(!PyErr_Occurred());
    4403         [ -  + ]:         13 :     if (!(st->elementpath_obj = PyImport_ImportModule("xml.etree.ElementPath")))
    4404                 :          0 :         return NULL;
    4405                 :            : 
    4406                 :            :     /* link against pyexpat */
    4407                 :         13 :     expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0);
    4408         [ +  - ]:         13 :     if (expat_capi) {
    4409                 :            :         /* check that it's usable */
    4410         [ +  - ]:         13 :         if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||
    4411         [ +  - ]:         13 :             (size_t)expat_capi->size < sizeof(struct PyExpat_CAPI) ||
    4412         [ +  - ]:         13 :             expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION ||
    4413         [ +  - ]:         13 :             expat_capi->MINOR_VERSION != XML_MINOR_VERSION ||
    4414         [ -  + ]:         13 :             expat_capi->MICRO_VERSION != XML_MICRO_VERSION) {
    4415                 :          0 :             PyErr_SetString(PyExc_ImportError,
    4416                 :            :                             "pyexpat version is incompatible");
    4417                 :          0 :             return NULL;
    4418                 :            :         }
    4419                 :            :     } else {
    4420                 :          0 :         return NULL;
    4421                 :            :     }
    4422                 :            : 
    4423                 :         13 :     st->parseerror_obj = PyErr_NewException(
    4424                 :            :         "xml.etree.ElementTree.ParseError", PyExc_SyntaxError, NULL
    4425                 :            :         );
    4426                 :         13 :     Py_INCREF(st->parseerror_obj);
    4427         [ -  + ]:         13 :     if (PyModule_AddObject(m, "ParseError", st->parseerror_obj) < 0) {
    4428                 :          0 :         Py_DECREF(st->parseerror_obj);
    4429                 :          0 :         return NULL;
    4430                 :            :     }
    4431                 :            : 
    4432                 :         13 :     PyTypeObject *types[] = {
    4433                 :            :         &Element_Type,
    4434                 :            :         &TreeBuilder_Type,
    4435                 :            :         &XMLParser_Type
    4436                 :            :     };
    4437                 :            : 
    4438         [ +  + ]:         52 :     for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) {
    4439         [ -  + ]:         39 :         if (PyModule_AddType(m, types[i]) < 0) {
    4440                 :          0 :             return NULL;
    4441                 :            :         }
    4442                 :            :     }
    4443                 :            : 
    4444                 :         13 :     return m;
    4445                 :            : }

Generated by: LCOV version 1.14