@@ -2399,6 +2399,7 @@ typedef struct {
2399
2399
2400
2400
PyObject * this ; /* current node */
2401
2401
PyObject * last ; /* most recently created node */
2402
+ PyObject * last_for_tail ; /* most recently created node that takes a tail */
2402
2403
2403
2404
PyObject * data ; /* data collector (string or list), or NULL */
2404
2405
@@ -2530,6 +2531,7 @@ treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg)
2530
2531
Py_VISIT (self -> root );
2531
2532
Py_VISIT (self -> this );
2532
2533
Py_VISIT (self -> last );
2534
+ Py_VISIT (self -> last_for_tail );
2533
2535
Py_VISIT (self -> data );
2534
2536
Py_VISIT (self -> stack );
2535
2537
Py_VISIT (self -> pi_factory );
@@ -2551,6 +2553,7 @@ treebuilder_gc_clear(TreeBuilderObject *self)
2551
2553
Py_CLEAR (self -> stack );
2552
2554
Py_CLEAR (self -> data );
2553
2555
Py_CLEAR (self -> last );
2556
+ Py_CLEAR (self -> last_for_tail );
2554
2557
Py_CLEAR (self -> this );
2555
2558
Py_CLEAR (self -> pi_factory );
2556
2559
Py_CLEAR (self -> comment_factory );
@@ -2622,21 +2625,50 @@ _elementtree__set_factories_impl(PyObject *module, PyObject *comment_factory,
2622
2625
}
2623
2626
2624
2627
static 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 )
2627
2630
{
2631
+ /* Fast paths for the "almost always" cases. */
2628
2632
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
+ }
2634
2647
}
2635
- else {
2636
- PyObject * joined = list_join (* data );
2648
+
2649
+ /* Fallback for the non-Element / non-trivial cases. */
2650
+ {
2637
2651
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 );
2639
2659
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
+
2640
2672
r = _PyObject_SetAttrId (element , name , joined );
2641
2673
Py_DECREF (joined );
2642
2674
if (r < 0 )
@@ -2649,21 +2681,21 @@ treebuilder_set_element_text_or_tail(PyObject *element, PyObject **data,
2649
2681
LOCAL (int )
2650
2682
treebuilder_flush_data (TreeBuilderObject * self )
2651
2683
{
2652
- PyObject * element = self -> last ;
2653
-
2654
2684
if (!self -> data ) {
2655
2685
return 0 ;
2656
2686
}
2657
2687
2658
- if (self -> this == element ) {
2688
+ if (!self -> last_for_tail ) {
2689
+ PyObject * element = self -> last ;
2659
2690
_Py_IDENTIFIER (text );
2660
- return treebuilder_set_element_text_or_tail (
2691
+ return treebuilder_extend_element_text_or_tail (
2661
2692
element , & self -> data ,
2662
2693
& ((ElementObject * ) element )-> text , & PyId_text );
2663
2694
}
2664
2695
else {
2696
+ PyObject * element = self -> last_for_tail ;
2665
2697
_Py_IDENTIFIER (tail );
2666
- return treebuilder_set_element_text_or_tail (
2698
+ return treebuilder_extend_element_text_or_tail (
2667
2699
element , & self -> data ,
2668
2700
& ((ElementObject * ) element )-> tail , & PyId_tail );
2669
2701
}
@@ -2739,6 +2771,7 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
2739
2771
}
2740
2772
2741
2773
this = self -> this ;
2774
+ Py_CLEAR (self -> last_for_tail );
2742
2775
2743
2776
if (this != Py_None ) {
2744
2777
if (treebuilder_add_subelement (this , node ) < 0 )
@@ -2836,6 +2869,8 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
2836
2869
2837
2870
item = self -> last ;
2838
2871
self -> last = self -> this ;
2872
+ Py_INCREF (self -> last );
2873
+ Py_XSETREF (self -> last_for_tail , self -> last );
2839
2874
self -> index -- ;
2840
2875
self -> this = PyList_GET_ITEM (self -> stack , self -> index );
2841
2876
Py_INCREF (self -> this );
@@ -2851,7 +2886,7 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
2851
2886
LOCAL (PyObject * )
2852
2887
treebuilder_handle_comment (TreeBuilderObject * self , PyObject * text )
2853
2888
{
2854
- PyObject * comment = NULL ;
2889
+ PyObject * comment ;
2855
2890
PyObject * this ;
2856
2891
2857
2892
if (treebuilder_flush_data (self ) < 0 ) {
@@ -2867,6 +2902,8 @@ treebuilder_handle_comment(TreeBuilderObject* self, PyObject* text)
2867
2902
if (self -> insert_comments && this != Py_None ) {
2868
2903
if (treebuilder_add_subelement (this , comment ) < 0 )
2869
2904
goto error ;
2905
+ Py_INCREF (comment );
2906
+ Py_XSETREF (self -> last_for_tail , comment );
2870
2907
}
2871
2908
} else {
2872
2909
Py_INCREF (text );
@@ -2888,7 +2925,7 @@ treebuilder_handle_comment(TreeBuilderObject* self, PyObject* text)
2888
2925
LOCAL (PyObject * )
2889
2926
treebuilder_handle_pi (TreeBuilderObject * self , PyObject * target , PyObject * text )
2890
2927
{
2891
- PyObject * pi = NULL ;
2928
+ PyObject * pi ;
2892
2929
PyObject * this ;
2893
2930
PyObject * stack [2 ] = {target , text };
2894
2931
@@ -2906,6 +2943,8 @@ treebuilder_handle_pi(TreeBuilderObject* self, PyObject* target, PyObject* text)
2906
2943
if (self -> insert_pis && this != Py_None ) {
2907
2944
if (treebuilder_add_subelement (this , pi ) < 0 )
2908
2945
goto error ;
2946
+ Py_INCREF (pi );
2947
+ Py_XSETREF (self -> last_for_tail , pi );
2909
2948
}
2910
2949
} else {
2911
2950
pi = PyTuple_Pack (2 , target , text );
@@ -3495,8 +3534,8 @@ expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
3495
3534
static void
3496
3535
expat_comment_handler<
F438
/span>(XMLParserObject * self , const XML_Char * comment_in )
3497
3536
{
3498
- PyObject * comment = NULL ;
3499
- PyObject * res = NULL ;
3537
+ PyObject * comment ;
3538
+ PyObject * res ;
3500
3539
3501
3540
if (PyErr_Occurred ())
3502
3541
return ;
@@ -3510,16 +3549,17 @@ expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in)
3510
3549
return ; /* parser will look for errors */
3511
3550
3512
3551
res = treebuilder_handle_comment (target , comment );
3552
+ Py_XDECREF (res );
3553
+ Py_DECREF (comment );
3513
3554
} else if (self -> handle_comment ) {
3514
3555
comment = PyUnicode_DecodeUTF8 (comment_in , strlen (comment_in ), "strict" );
3515
3556
if (!comment )
3516
3557
return ;
3517
3558
3518
3559
res = _PyObject_FastCall (self -> handle_comment , & comment , 1 );
3560
+ Py_XDECREF (res );
3561
+ Py_DECREF (comment );
3519
3562
}
3520
-
3521
- Py_XDECREF (res );
3522
- Py_DECREF (comment );
3523
3563
}
3524
3564
3525
3565
static void
@@ -3587,7 +3627,7 @@ static void
3587
3627
expat_pi_handler (XMLParserObject * self , const XML_Char * target_in ,
3588
3628
const XML_Char * data_in )
3589
3629
{
3590
- PyObject * pi_target = NULL ;
3630
+ PyObject * pi_target ;
3591
3631
PyObject * data ;
3592
3632
PyObject * res ;
3593
3633
PyObject * stack [2 ];
@@ -3599,7 +3639,7 @@ expat_pi_handler(XMLParserObject* self, const XML_Char* target_in,
3599
3639
/* shortcut */
3600
3640
TreeBuilderObject * target = (TreeBuilderObject * ) self -> target ;
3601
3641
3602
- if (target -> events_append && target -> pi_event_obj ) {
3642
+ if (( target -> events_append && target -> pi_event_obj ) || target -> insert_pis ) {
3603
3643
pi_target = PyUnicode_DecodeUTF8 (target_in , strlen (target_in ), "strict" );
3604
3644
if (!pi_target )
3605
3645
goto error ;
0 commit comments