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