summaryrefslogtreecommitdiffstats
path: root/Modules/_elementtree.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2015-12-21 10:57:27 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2015-12-21 10:57:27 (GMT)
commit060ed718cecbfb7bb3292b76eef8312896ba7317 (patch)
treea17b05c1b9f8ee431b59da093450628df7832600 /Modules/_elementtree.c
parent22adf2ac022d6667a8689d6fac8af44c7663e3f2 (diff)
downloadcpython-060ed718cecbfb7bb3292b76eef8312896ba7317.zip
cpython-060ed718cecbfb7bb3292b76eef8312896ba7317.tar.gz
cpython-060ed718cecbfb7bb3292b76eef8312896ba7317.tar.bz2
Issue #25869: Optimized deepcopying ElementTree; it is now 20 times faster.
Diffstat (limited to 'Modules/_elementtree.c')
-rw-r--r--Modules/_elementtree.c78
1 files changed, 54 insertions, 24 deletions
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index ad3e45c..5908c72 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -129,30 +129,6 @@ elementtree_free(void *m)
/* helpers */
LOCAL(PyObject*)
-deepcopy(PyObject* object, PyObject* memo)
-{
- /* do a deep copy of the given object */
- PyObject* args;
- PyObject* result;
- elementtreestate *st = ET_STATE_GLOBAL;
-
- if (!st->deepcopy_obj) {
- PyErr_SetString(
- PyExc_RuntimeError,
- "deepcopy helper not found"
- );
- return NULL;
- }
-
- args = PyTuple_Pack(2, object, memo);
- if (!args)
- return NULL;
- result = PyObject_CallObject(st->deepcopy_obj, args);
- Py_DECREF(args);
- return result;
-}
-
-LOCAL(PyObject*)
list_join(PyObject* list)
{
/* join list elements (destroying the list in the process) */
@@ -748,6 +724,9 @@ _elementtree_Element___copy___impl(ElementObject *self)
return (PyObject*) element;
}
+/* Helper for a deep copy. */
+LOCAL(PyObject *) deepcopy(PyObject *, PyObject *);
+
/*[clinic input]
_elementtree.Element.__deepcopy__
@@ -838,6 +817,57 @@ _elementtree_Element___deepcopy__(ElementObject *self, PyObject *memo)
return NULL;
}
+LOCAL(PyObject *)
+deepcopy(PyObject *object, PyObject *memo)
+{
+ /* do a deep copy of the given object */
+ PyObject *args;
+ PyObject *result;
+ elementtreestate *st;
+
+ /* Fast paths */
+ if (object == Py_None || PyUnicode_CheckExact(object)) {
+ Py_INCREF(object);
+ return object;
+ }
+
+ if (Py_REFCNT(object) == 1) {
+ if (PyDict_CheckExact(object)) {
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+ int simple = 1;
+ while (PyDict_Next(object, &pos, &key, &value)) {
+ if (!PyUnicode_CheckExact(key) || !PyUnicode_CheckExact(value)) {
+ simple = 0;
+ break;
+ }
+ }
+ if (simple)
+ return PyDict_Copy(object);
+ /* Fall through to general case */
+ }
+ else if (Element_CheckExact(object)) {
+ return _elementtree_Element___deepcopy__((ElementObject *)object, memo);
+ }
+ }
+
+ /* General case */
+ st = ET_STATE_GLOBAL;
+ if (!st->deepcopy_obj) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "deepcopy helper not found");
+ return NULL;
+ }
+
+ args = PyTuple_Pack(2, object, memo);
+ if (!args)
+ return NULL;
+ result = PyObject_CallObject(st->deepcopy_obj, args);
+ Py_DECREF(args);
+ return result;
+}
+
+
/*[clinic input]
_elementtree.Element.__sizeof__ -> Py_ssize_t