ยปCore Development>Code coverage>Modules/_elementtree.c

Python code coverage for Modules/_elementtree.c

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