@@ -2399,6 +2399,7 @@ typedef struct {
23992399
24002400 PyObject * this ; /* current node */
24012401 PyObject * last ; /* most recently created node */
2402+ PyObject * last_for_tail ; /* most recently created node that takes a tail */
24022403
24032404 PyObject * data ; /* data collector (string or list), or NULL */
24042405
@@ -2530,6 +2531,7 @@ treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg)
25302531 Py_VISIT (self -> root );
25312532 Py_VISIT (self -> this );
25322533 Py_VISIT (self -> last );
2534+ Py_VISIT (self -> last_for_tail );
25332535 Py_VISIT (self -> data );
25342536 Py_VISIT (self -> stack );
25352537 Py_VISIT (self -> pi_factory );
@@ -2551,6 +2553,7 @@ treebuilder_gc_clear(TreeBuilderObject *self)
25512553 Py_CLEAR (self -> stack );
25522554 Py_CLEAR (self -> data );
25532555 Py_CLEAR (self -> last );
2556+ Py_CLEAR (self -> last_for_tail );
25542557 Py_CLEAR (self -> this );
25552558 Py_CLEAR (self -> pi_factory );
25562559 Py_CLEAR (self -> comment_factory );
@@ -2622,21 +2625,50 @@ _elementtree__set_factories_impl(PyObject *module, PyObject *comment_factory,
26222625}
26232626
26242627static int
2625- treebuilder_set_element_text_or_tail (PyObject * element , PyObject * * data ,
2626- PyObject * * dest , _Py_Identifier * name )
2628+ treebuilder_extend_element_text_or_tail (PyObject * element , PyObject * * data ,
2629+ PyObject * * dest , _Py_Identifier * name )
26272630{
2631+ /* Fast paths for the "almost always" cases. */
26282632 if (Element_CheckExact (element )) {
2629- PyObject * tmp = JOIN_OBJ (* dest );
2630- * dest = JOIN_SET (* data , PyList_CheckExact (* data ));
2631- * data = NULL ;
2632- Py_DECREF (tmp );
2633- return 0 ;
2633+ PyObject * dest_obj = JOIN_OBJ (* dest );
2634+ if (dest_obj == Py_None ) {
2635+ * dest = JOIN_SET (* data , PyList_CheckExact (* data ));
2636+ * data = NULL ;
2637+ Py_DECREF (dest_obj );
2638+ return 0 ;
2639+ }
2640+ else if (JOIN_GET (* dest )) {
2641+ if (PyList_SetSlice (dest_obj , PY_SSIZE_T_MAX , PY_SSIZE_T_MAX , * data ) < 0 ) {
2642+ return -1 ;
2643+ }
2644+ Py_CLEAR (* data );
2645+ return 0 ;
2646+ }
26342647 }
2635- else {
2636- PyObject * joined = list_join (* data );
2648+
2649+ /* Fallback for the non-Element / non-trivial cases. */
2650+ {
26372651 int r ;
2638- if (joined == NULL )
2652+ PyObject * joined ;
2653+ PyObject * previous = _PyObject_GetAttrId (element , name );
2654+ if (!previous )
2655+ return -1 ;
2656+ joined = list_join (* data );
2657+ if (!joined ) {
2658+ Py_DECREF (previous );
26392659 return -1 ;
2660+ }
2661+ if (previous != Py_None ) {
2662+ PyObject * tmp = PyNumber_Add (previous , joined );
2663+ Py_DECREF (joined );
2664+ Py_DECREF (previous );
2665+ if (!tmp )
2666+ return -1 ;
2667+ joined = tmp ;
2668+ } else {
2669+ Py_DECREF (previous );
2670+ }
2671+
26402672 r = _PyObject_SetAttrId (element , name , joined );
26412673 Py_DECREF (joined );
26422674 if (r < 0 )
@@ -2649,21 +2681,21 @@ treebuilder_set_element_text_or_tail(PyObject *element, PyObject **data,
26492681LOCAL (int )
26502682treebuilder_flush_data (TreeBuilderObject * self )
26512683{
2652- PyObject * element = self -> last ;
2653-
26542684 if (!self -> data ) {
26552685 return 0 ;
26562686 }
26572687
2658- if (self -> this == element ) {
2688+ if (!self -> last_for_tail ) {
2689+ PyObject * element = self -> last ;
26592690 _Py_IDENTIFIER (text );
2660- return treebuilder_set_element_text_or_tail (
2691+ return treebuilder_extend_element_text_or_tail (
26612692 element , & self -> data ,
26622693 & ((ElementObject * ) element )-> text , & PyId_text );
26632694 }
26642695 else {
2696+ PyObject * element = self -> last_for_tail ;
26652697 _Py_IDENTIFIER (tail );
2666- return treebuilder_set_element_text_or_tail (
2698+ return treebuilder_extend_element_text_or_tail (
26672699 element , & self -> data ,
26682700 & ((ElementObject * ) element )-> tail , & PyId_tail );
26692701 }
@@ -2739,6 +2771,7 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
27392771 }
27402772
27412773 this = self -> this ;
2774+ Py_CLEAR (self -> last_for_tail );
27422775
27432776 if (this != Py_None ) {
27442777 if (treebuilder_add_subelement (this , node ) < 0 )
@@ -2836,6 +2869,8 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
28362869
28372870 item = self -> last ;
28382871 self -> last = self -> this ;
2872+ Py_INCREF (self -> last );
2873+ Py_XSETREF (self -> last_for_tail , self -> last );
28392874 self -> index -- ;
28402875 self -> this = PyList_GET_ITEM (self -> stack , self -> index );
28412876 Py_INCREF (self -> this );
@@ -2851,7 +2886,7 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
28512886LOCAL (PyObject * )
28522887treebuilder_handle_comment (TreeBuilderObject * self , PyObject * text )
28532888{
2854- PyObject * comment = NULL ;
2889+ PyObject * comment ;
28552890 PyObject * this ;
28562891
28572892 if (treebuilder_flush_data (self ) < 0 ) {
@@ -2867,6 +2902,8 @@ treebuilder_handle_comment(TreeBuilderObject* self, PyObject* text)
28672902 if (self -> insert_comments && this != Py_None ) {
28682903 if (treebuilder_add_subelement (this , comment ) < 0 )
28692904 goto error ;
2905+ Py_INCREF (comment );
2906+ Py_XSETREF (self -> last_for_tail , comment );
28702907 }
28712908 } else {
28722909 Py_INCREF (text );
@@ -2888,7 +2925,7 @@ treebuilder_handle_comment(TreeBuilderObject* self, PyObject* text)
28882925LOCAL (PyObject * )
28892926treebuilder_handle_pi (TreeBuilderObject * self , PyObject * target , PyObject * text )
28902927{
2891- PyObject * pi = NULL ;
2928+ PyObject * pi ;
28922929 PyObject * this ;
28932930 PyObject * stack [2 ] = {target , text };
28942931
@@ -2906,6 +2943,8 @@ treebuilder_handle_pi(TreeBuilderObject* self, PyObject* target, PyObject* text)
29062943 if (self -> insert_pis && this != Py_None ) {
29072944 if (treebuilder_add_subelement (this , pi ) < 0 )
29082945 goto error ;
2946+ Py_INCREF (pi );
2947+ Py_XSETREF (self -> last_for_tail , pi );
29092948 }
29102949 } else {
29112950 pi = PyTuple_Pack (2 , target , text );
@@ -3495,8 +3534,8 @@ expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
34953534static void
34963535expat_comment_handler (XMLParserObject * self , const XML_Char * comment_in )
34973536{
3498- PyObject * comment = NULL ;
3499- PyObject * res = NULL ;
3537+ PyObject * comment ;
3538+ PyObject * res ;
35003539
35013540 if (PyErr_Occurred ())
35023541 return ;
@@ -3510,16 +3549,17 @@ expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in)
35103549 return ; /* parser will look for errors */
35113550
35123551 res = treebuilder_handle_comment (target , comment );
3552+ Py_XDECREF (res );
3553+ Py_DECREF (comment );
35133554 } else if (self -> handle_comment ) {
35143555 comment = PyUnicode_DecodeUTF8 (comment_in , strlen (comment_in ), "strict" );
35153556 if (!comment )
35163557 return ;
35173558
35183559 res = _PyObject_CallOneArg (self -> handle_comment , comment );
3560+ Py_XDECREF (res );
3561+ Py_DECREF (comment );
35193562 }
3520-
3521- Py_XDECREF (res );
3522- Py_DECREF (comment );
35233563}
35243564
35253565static void
@@ -3587,7 +3627,7 @@ static void
35873627expat_pi_handler (XMLParserObject * self , const XML_Char * target_in ,
35883628 const XML_Char * data_in )
35893629{
3590- PyObject * pi_target = NULL ;
3630+ PyObject * pi_target ;
35913631 PyObject * data ;
35923632 PyObject * res ;
35933633 PyObject * stack [2 ];
@@ -3599,7 +3639,7 @@ expat_pi_handler(XMLParserObject* self, const XML_Char* target_in,
35993639 /* shortcut */
36003640 TreeBuilderObject * target = (TreeBuilderObject * ) self -> target ;
36013641
3602- if (target -> events_append && target -> pi_event_obj ) {
3642+ if (( target -> events_append && target -> pi_event_obj ) || target -> insert_pis ) {
36033643 pi_target = PyUnicode_DecodeUTF8 (target_in , strlen (target_in ), "strict" );
36043644 if (!pi_target )
36053645 goto error ;
0 commit comments