summaryrefslogtreecommitdiff
path: root/src/core/document.c
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2007-07-28 23:03:56 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2007-07-28 23:03:56 +0000
commitbe76092abf32f4c586717452fe0d2357220ea29d (patch)
treeb6b9a2daf9e28fdffe8a05c1e0455f44a6412ee4 /src/core/document.c
parentbb9a9029b6ec4f26ee31f4879cde52d58dcb49c0 (diff)
downloadlibdom-be76092abf32f4c586717452fe0d2357220ea29d.tar.gz
libdom-be76092abf32f4c586717452fe0d2357220ea29d.tar.bz2
Implement Document destructor.
Fix handling of nodes within a document (they no longer explicitly reference the document) svn path=/trunk/dom/; revision=3468
Diffstat (limited to 'src/core/document.c')
-rw-r--r--src/core/document.c79
1 files changed, 77 insertions, 2 deletions
diff --git a/src/core/document.c b/src/core/document.c
index ff9e5ec..d238558 100644
--- a/src/core/document.c
+++ b/src/core/document.c
@@ -138,8 +138,10 @@ dom_exception dom_document_create(struct dom_implementation *impl,
}
}
- /* Initialise base class */
- err = dom_node_initialise(&d->base, d, DOM_DOCUMENT_NODE,
+ /* Initialise base class -- the Document has no parent, so
+ * destruction will be attempted as soon as its reference count
+ * reaches zero. */
+ err = dom_node_initialise(&d->base, NULL, DOM_DOCUMENT_NODE,
NULL, NULL);
if (err != DOM_NO_ERR) {
/* Clean up interned strings */
@@ -168,6 +170,79 @@ dom_exception dom_document_create(struct dom_implementation *impl,
}
/**
+ * Destroy a document
+ *
+ * \param doc The document to destroy
+ *
+ * The contents of ::doc will be destroyed and ::doc will be freed.
+ */
+void dom_document_destroy(struct dom_document *doc)
+{
+ struct dom_node *c, *d;
+
+ /* Destroy children of this node */
+ for (c = doc->base.first_child; c != NULL; c = d) {
+ d = c->next;
+
+ /* Detach child */
+ c->parent = NULL;
+
+ if (c->refcnt > 0) {
+ /* Something is using this child */
+
+ /** \todo add to list of nodes pending deletion */
+
+ continue;
+ }
+
+ /* Detach from sibling list */
+ c->previous = NULL;
+ c->next = NULL;
+
+ dom_node_destroy(c);
+ }
+
+ /** \todo Ensure list of nodes pending deletion is empty. If not,
+ * then we can't yet destroy the document (its destruction will
+ * have to wait until the pending nodes are destroyed) */
+
+ /* Ok, the document tree is empty, as is the list of nodes pending
+ * deletion. Therefore, it is safe to destroy the document. */
+
+ /* Destroy the doctype (if there is one) */
+ if (doc->type != NULL) {
+ ((struct dom_node *) doc->type)->parent = NULL;
+
+ dom_node_destroy((struct dom_node *) doc->type);
+ }
+
+ doc->type = NULL;
+
+ if (doc->impl != NULL)
+ dom_implementation_unref(doc->impl);
+ doc->impl = NULL;
+
+ /* This is paranoia -- if there are any remaining nodelists or
+ * namednodemaps, then the document's reference count will be
+ * non-zero as these data structures reference the document because
+ * they are held by the client. */
+ doc->nodelists = NULL;
+ doc->maps = NULL;
+
+ /* Clean up interned strings */
+ for (int i = 0; i <= DOM_NODE_TYPE_COUNT; i++) {
+ if (doc->nodenames[i] != NULL)
+ dom_string_unref(doc->nodenames[i]);
+ }
+
+ /* Finalise base class */
+ dom_node_finalise(doc, &doc->base);
+
+ /* Free document */
+ doc->alloc(doc, 0, doc->pw);
+}
+
+/**
* Retrieve the doctype of a document
*
* \param doc The document to retrieve the doctype from