summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/attr.c47
-rw-r--r--src/core/attr.h1
-rw-r--r--src/core/cdatasection.c18
-rw-r--r--src/core/cdatasection.h3
-rw-r--r--src/core/characterdata.c14
-rw-r--r--src/core/characterdata.h3
-rw-r--r--src/core/comment.c18
-rw-r--r--src/core/comment.h3
-rw-r--r--src/core/doc_fragment.c42
-rw-r--r--src/core/doc_fragment.h3
-rw-r--r--src/core/document.c1
-rw-r--r--src/core/element.c69
-rw-r--r--src/core/element.h3
-rw-r--r--src/core/entity_ref.c42
-rw-r--r--src/core/entity_ref.h3
-rw-r--r--src/core/node.c139
-rw-r--r--src/core/node.h4
-rw-r--r--src/core/pi.c18
-rw-r--r--src/core/pi.h3
-rw-r--r--src/core/text.c30
-rw-r--r--src/core/text.h4
21 files changed, 463 insertions, 5 deletions
diff --git a/src/core/attr.c b/src/core/attr.c
index ed20c93..ca6047a 100644
--- a/src/core/attr.c
+++ b/src/core/attr.c
@@ -80,6 +80,53 @@ dom_exception dom_attr_create(struct dom_document *doc,
}
/**
+ * Destroy an attribute node
+ *
+ * \param doc The owning document
+ * \param attr The attribute to destroy
+ *
+ * The contents of ::attr will be destroyed and ::attr will be freed
+ */
+void dom_attr_destroy(struct dom_document *doc, struct dom_attr *attr)
+{
+ struct dom_node *c, *d;
+
+ /* Destroy children of this node */
+ for (c = attr->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);
+ }
+
+ /* Now, clean up this node and destroy it */
+
+ if (attr->schema_type_info != NULL) {
+ /** \todo destroy schema type info */
+ }
+
+ attr->owner = NULL;
+
+ dom_node_finalise(doc, &attr->base);
+
+ dom_document_alloc(doc, attr, 0);
+}
+
+/**
* Retrieve an attribute's name
*
* \param attr Attribute to retrieve name from
diff --git a/src/core/attr.h b/src/core/attr.h
index 9605926..dc73ae0 100644
--- a/src/core/attr.h
+++ b/src/core/attr.h
@@ -16,5 +16,6 @@ struct dom_string;
dom_exception dom_attr_create(struct dom_document *doc,
struct dom_string *name, struct dom_attr **result);
+void dom_attr_destroy(struct dom_document *doc, struct dom_attr *attr);
#endif
diff --git a/src/core/cdatasection.c b/src/core/cdatasection.c
index c477dd7..71d3d43 100644
--- a/src/core/cdatasection.c
+++ b/src/core/cdatasection.c
@@ -54,3 +54,21 @@ dom_exception dom_cdata_section_create(struct dom_document *doc,
return DOM_NO_ERR;
}
+
+/**
+ * Destroy a CDATA section
+ *
+ * \param doc The owning document
+ * \param cdata The cdata section to destroy
+ *
+ * The contents of ::cdata will be destroyed and ::cdata will be freed.
+ */
+void dom_cdata_section_destroy(struct dom_document *doc,
+ struct dom_cdata_section *cdata)
+{
+ /* Clean up base node contents */
+ dom_text_finalise(doc, &cdata->base);
+
+ /* Destroy the node */
+ dom_document_alloc(doc, cdata, 0);
+}
diff --git a/src/core/cdatasection.h b/src/core/cdatasection.h
index c53985b..740c7d7 100644
--- a/src/core/cdatasection.h
+++ b/src/core/cdatasection.h
@@ -18,4 +18,7 @@ dom_exception dom_cdata_section_create(struct dom_document *doc,
struct dom_string *name, struct dom_string *value,
struct dom_cdata_section **result);
+void dom_cdata_section_destroy(struct dom_document *doc,
+ struct dom_cdata_section *cdata);
+
#endif
diff --git a/src/core/characterdata.c b/src/core/characterdata.c
index 7b38fd2..9cf3a49 100644
--- a/src/core/characterdata.c
+++ b/src/core/characterdata.c
@@ -32,6 +32,20 @@ dom_exception dom_characterdata_initialise(struct dom_characterdata *cdata,
}
/**
+ * Finalise a character data node
+ *
+ * \param doc The owning document
+ * \param cdata The node to finalise
+ *
+ * The contents of ::cdata will be cleaned up. ::cdata will not be freed.
+ */
+void dom_characterdata_finalise(struct dom_document *doc,
+ struct dom_characterdata *cdata)
+{
+ dom_node_finalise(doc, &cdata->base);
+}
+
+/**
* Retrieve data from a character data node
*
* \param cdata Character data node to retrieve data from
diff --git a/src/core/characterdata.h b/src/core/characterdata.h
index 6a2b329..1351505 100644
--- a/src/core/characterdata.h
+++ b/src/core/characterdata.h
@@ -21,4 +21,7 @@ dom_exception dom_characterdata_initialise(struct dom_characterdata *cdata,
struct dom_document *doc, dom_node_type type,
struct dom_string *name, struct dom_string *value);
+void dom_characterdata_finalise(struct dom_document *doc,
+ struct dom_characterdata *cdata);
+
#endif
diff --git a/src/core/comment.c b/src/core/comment.c
index e29edda..2e1c323 100644
--- a/src/core/comment.c
+++ b/src/core/comment.c
@@ -54,3 +54,21 @@ dom_exception dom_comment_create(struct dom_document *doc,
return DOM_NO_ERR;
}
+
+/**
+ * Destroy a comment node
+ *
+ * \param doc The owning document
+ * \param comment The node to destroy
+ *
+ * The contents of ::comment will be destroyed and ::comment will be freed
+ */
+void dom_comment_destroy(struct dom_document *doc,
+ struct dom_comment *comment)
+{
+ /* Finalise base class contents */
+ dom_characterdata_finalise(doc, &comment->base);
+
+ /* Free node */
+ dom_document_alloc(doc, comment, 0);
+}
diff --git a/src/core/comment.h b/src/core/comment.h
index 1cc7d28..38bb448 100644
--- a/src/core/comment.h
+++ b/src/core/comment.h
@@ -18,4 +18,7 @@ dom_exception dom_comment_create(struct dom_document *doc,
struct dom_string *name, struct dom_string *value,
struct dom_comment **result);
+void dom_comment_destroy(struct dom_document *doc,
+ struct dom_comment *comment);
+
#endif
diff --git a/src/core/doc_fragment.c b/src/core/doc_fragment.c
index 0792467..eaef388 100644
--- a/src/core/doc_fragment.c
+++ b/src/core/doc_fragment.c
@@ -55,3 +55,45 @@ dom_exception dom_document_fragment_create(struct dom_document *doc,
return DOM_NO_ERR;
}
+
+/**
+ * Destroy a document fragment
+ *
+ * \param doc The owning document
+ * \param frag The document fragment to destroy
+ *
+ * The contents of ::frag will be destroyed and ::frag will be freed.
+ */
+void dom_document_fragment_destroy(struct dom_document *doc,
+ struct dom_document_fragment *frag)
+{
+ struct dom_node *c, *d;
+
+ /* Destroy children of this node */
+ for (c = frag->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);
+ }
+
+ /* Finalise base class */
+ dom_node_finalise(doc, &frag->base);
+
+ /* Destroy fragment */
+ dom_document_alloc(doc, frag, 0);
+}
diff --git a/src/core/doc_fragment.h b/src/core/doc_fragment.h
index 9e27811..08e3422 100644
--- a/src/core/doc_fragment.h
+++ b/src/core/doc_fragment.h
@@ -18,4 +18,7 @@ dom_exception dom_document_fragment_create(struct dom_document *doc,
struct dom_string *name, struct dom_string *value,
struct dom_document_fragment **result);
+void dom_document_fragment_destroy(struct dom_document *doc,
+ struct dom_document_fragment *frag);
+
#endif
diff --git a/src/core/document.c b/src/core/document.c
index 0495f59..ff9e5ec 100644
--- a/src/core/document.c
+++ b/src/core/document.c
@@ -15,7 +15,6 @@
#include "core/attr.h"
#include "core/cdatasection.h"
-#include "core/characterdata.h"
#include "core/comment.h"
#include "core/document.h"
#include "core/doc_fragment.h"
diff --git a/src/core/element.c b/src/core/element.c
index 11b41a1..8c5ed6a 100644
--- a/src/core/element.c
+++ b/src/core/element.c
@@ -65,6 +65,75 @@ dom_exception dom_element_create(struct dom_document *doc,
}
/**
+ * Destroy an element
+ *
+ * \param doc The owning document
+ * \param element The element to destroy
+ *
+ * The contents of ::element will be destroyed and ::element will be freed.
+ */
+void dom_element_destroy(struct dom_document *doc,
+ struct dom_element *element)
+{
+ struct dom_node *c, *d;
+
+ /* Destroy children of this node */
+ for (c = element->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);
+ }
+
+ /* Destroy attributes attached to this node */
+ for (c = (struct dom_node *) element->base.attributes;
+ c != NULL; c = d) {
+ d = c->next;
+
+ /* Detach child */
+ c->parent = NULL;
+
+ if (c->refcnt > 0) {
+ /* Something is using this attribute */
+
+ /** \todo add to list of nodes pending deletion */
+
+ continue;
+ }
+
+ /* Detach from sibling list */
+ c->previous = NULL;
+ c->next = NULL;
+
+ dom_node_destroy(c);
+ }
+
+ if (element->schema_type_info != NULL) {
+ /** \todo destroy schema type info */
+ }
+
+ /* Finalise base class */
+ dom_node_finalise(doc, &element->base);
+
+ /* Free the element */
+ dom_document_alloc(doc, element, 0);
+}
+
+/**
* Retrieve an element's tag name
*
* \param element The element to retrieve the name from
diff --git a/src/core/element.h b/src/core/element.h
index 69a0b04..2a79997 100644
--- a/src/core/element.h
+++ b/src/core/element.h
@@ -17,4 +17,7 @@ struct dom_string;
dom_exception dom_element_create(struct dom_document *doc,
struct dom_string *name, struct dom_element **result);
+void dom_element_destroy(struct dom_document *doc,
+ struct dom_element *element);
+
#endif
diff --git a/src/core/entity_ref.c b/src/core/entity_ref.c
index 7bc103e..8382249 100644
--- a/src/core/entity_ref.c
+++ b/src/core/entity_ref.c
@@ -55,3 +55,45 @@ dom_exception dom_entity_reference_create(struct dom_document *doc,
return DOM_NO_ERR;
}
+
+/**
+ * Destroy an entity reference
+ *
+ * \param doc The owning document
+ * \param entity The entity reference to destroy
+ *
+ * The contents of ::entity will be destroyed and ::entity will be freed.
+ */
+void dom_entity_reference_destroy(struct dom_document *doc,
+ struct dom_entity_reference *entity)
+{
+ struct dom_node *c, *d;
+
+ /* Destroy children of this node */
+ for (c = entity->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);
+ }
+
+ /* Finalise base class */
+ dom_node_finalise(doc, &entity->base);
+
+ /* Destroy fragment */
+ dom_document_alloc(doc, entity, 0);
+}
diff --git a/src/core/entity_ref.h b/src/core/entity_ref.h
index b1f9dff..047ff30 100644
--- a/src/core/entity_ref.h
+++ b/src/core/entity_ref.h
@@ -18,4 +18,7 @@ dom_exception dom_entity_reference_create(struct dom_document *doc,
struct dom_string *name, struct dom_string *value,
struct dom_entity_reference **result);
+void dom_entity_reference_destroy(struct dom_document *doc,
+ struct dom_entity_reference *entity);
+
#endif
diff --git a/src/core/node.c b/src/core/node.c
index 04a1230..db0fb05 100644
--- a/src/core/node.c
+++ b/src/core/node.c
@@ -8,11 +8,90 @@
#include <dom/core/document.h>
#include <dom/core/string.h>
+#include "core/attr.h"
+#include "core/cdatasection.h"
+#include "core/comment.h"
#include "core/document.h"
+#include "core/doc_fragment.h"
+#include "core/element.h"
+#include "core/entity_ref.h"
#include "core/node.h"
+#include "core/pi.h"
+#include "core/text.h"
#include "utils/utils.h"
/**
+ * Destroy a DOM node
+ *
+ * \param node The node to destroy
+ *
+ * ::node's parent link must be NULL and its reference count must be 0.
+ *
+ * ::node will be freed.
+ *
+ * This function should only be called from dom_node_unref or type-specific
+ * destructors (for destroying child nodes). Anything else should not
+ * be attempting to destroy nodes -- they should simply be unreferencing
+ * them (so destruction will occur at the appropriate time).
+ */
+void dom_node_destroy(struct dom_node *node)
+{
+ struct dom_document *owner = node->owner;
+
+ /* This function simply acts as a central despatcher
+ * for type-specific destructors. It claims a reference upon the
+ * owning document during destruction to ensure that the document
+ * doesn't get destroyed before its contents. */
+
+ dom_node_ref((struct dom_node *) owner);
+
+ switch (node->type) {
+ case DOM_ELEMENT_NODE:
+ dom_element_destroy(owner, (struct dom_element *) node);
+ break;
+ case DOM_ATTRIBUTE_NODE:
+ dom_attr_destroy(owner, (struct dom_attr *) node);
+ break;
+ case DOM_TEXT_NODE:
+ dom_text_destroy(owner, (struct dom_text *) node);
+ break;
+ case DOM_CDATA_SECTION_NODE:
+ dom_cdata_section_destroy(owner,
+ (struct dom_cdata_section *) node);
+ break;
+ case DOM_ENTITY_REFERENCE_NODE:
+ dom_entity_reference_destroy(owner,
+ (struct dom_entity_reference *) node);
+ break;
+ case DOM_ENTITY_NODE:
+ /** \todo entity node */
+ break;
+ case DOM_PROCESSING_INSTRUCTION_NODE:
+ dom_processing_instruction_destroy(owner,
+ (struct dom_processing_instruction *) node);
+ break;
+ case DOM_COMMENT_NODE:
+ dom_comment_destroy(owner, (struct dom_comment *) node);
+ break;
+ case DOM_DOCUMENT_NODE:
+ /** \todo document node */
+ break;
+ case DOM_DOCUMENT_TYPE_NODE:
+ /** \todo document type node */
+ break;
+ case DOM_DOCUMENT_FRAGMENT_NODE:
+ dom_document_fragment_destroy(owner,
+ (struct dom_document_fragment *) node);
+ break;
+ case DOM_NOTATION_NODE:
+ /** \todo notation node */
+ break;
+ }
+
+ dom_node_unref((struct dom_node *) owner);
+}
+
+/**
* Initialise a DOM node
*
* \param node The node to initialise
@@ -61,6 +140,55 @@ dom_exception dom_node_initialise(struct dom_node *node,
}
/**
+ * Finalise a DOM node
+ *
+ * \param doc The owning document
+ * \param node The node to finalise
+ *
+ * The contents of ::node will be cleaned up. ::node will not be freed.
+ * All children of ::node should have been removed prior to finalisation.
+ */
+void dom_node_finalise(struct dom_document *doc, struct dom_node *node)
+{
+ struct dom_user_data *u, *v;
+
+ /* Destroy user data */
+ for (u = node->user_data; u != NULL; u = v) {
+ v = u->next;
+
+ dom_string_unref(u->key);
+
+ dom_document_alloc(doc, u, 0);
+ }
+
+ if (node->localname != NULL)
+ dom_string_unref(node->localname);
+
+ if (node->prefix != NULL)
+ dom_string_unref(node->prefix);
+
+ if (node->namespace != NULL)
+ dom_string_unref(node->namespace);
+
+ dom_node_unref((struct dom_node *) node->owner);
+ node->owner = NULL;
+
+ /* Paranoia */
+ node->attributes = NULL;
+ node->next = NULL;
+ node->previous = NULL;
+ node->last_child = NULL;
+ node->first_child = NULL;
+ node->parent = NULL;
+
+ if (node->value != NULL)
+ dom_string_unref(node->value);
+
+ if (node->name != NULL)
+ dom_string_unref(node->name);
+}
+
+/**
* Claim a reference on a DOM node
*
* \param node The node to claim a reference on
@@ -75,13 +203,16 @@ void dom_node_ref(struct dom_node *node)
*
* \param node The node to release the reference from
*
- * If the reference count reaches zero, any memory claimed by the
- * node will be released
+ * If the reference count reaches zero and the node is not part of any
+ * document, any memory claimed by the node will be released.
*/
void dom_node_unref(struct dom_node *node)
{
- if (--node->refcnt == 0) {
- /** \todo implement */
+ if (node->refcnt > 0)
+ node->refcnt--;
+
+ if (node->refcnt == 0 && node->parent == NULL) {
+ dom_node_destroy(node);
}
}
diff --git a/src/core/node.h b/src/core/node.h
index 168d2ec..beee0bd 100644
--- a/src/core/node.h
+++ b/src/core/node.h
@@ -52,8 +52,12 @@ struct dom_node {
uint32_t refcnt; /**< Reference count */
};
+void dom_node_destroy(struct dom_node *node);
+
dom_exception dom_node_initialise(struct dom_node *node,
struct dom_document *doc, dom_node_type type,
struct dom_string *name, struct dom_string *value);
+void dom_node_finalise(struct dom_document *doc, struct dom_node *node);
+
#endif
diff --git a/src/core/pi.c b/src/core/pi.c
index 55e85f7..c2b6cc9 100644
--- a/src/core/pi.c
+++ b/src/core/pi.c
@@ -56,3 +56,21 @@ dom_exception dom_processing_instruction_create(struct dom_document *doc,
return DOM_NO_ERR;
}
+
+/**
+ * Destroy a processing instruction
+ *
+ * \param doc The owning document
+ * \param pi The processing instruction to destroy
+ *
+ * The contents of ::pi will be destroyed and ::pi will be freed.
+ */
+void dom_processing_instruction_destroy(struct dom_document *doc,
+ struct dom_processing_instruction *pi)
+{
+ /* Finalise base class */
+ dom_node_finalise(doc, &pi->base);
+
+ /* Free processing instruction */
+ dom_document_alloc(doc, pi, 0);
+}
diff --git a/src/core/pi.h b/src/core/pi.h
index 1d7560f..4dca989 100644
--- a/src/core/pi.h
+++ b/src/core/pi.h
@@ -18,4 +18,7 @@ dom_exception dom_processing_instruction_create(struct dom_document *doc,
struct dom_string *name, struct dom_string *value,
struct dom_processing_instruction **result);
+void dom_processing_instruction_destroy(struct dom_document *doc,
+ struct dom_processing_instruction *pi);
+
#endif
diff --git a/src/core/text.c b/src/core/text.c
index 05e2b7d..ec94311 100644
--- a/src/core/text.c
+++ b/src/core/text.c
@@ -52,6 +52,23 @@ dom_exception dom_text_create(struct dom_document *doc,
}
/**
+ * Destroy a text node
+ *
+ * \param doc The owning document
+ * \param text The text node to destroy
+ *
+ * The contents of ::text will be destroyed and ::text will be freed.
+ */
+void dom_text_destroy(struct dom_document *doc, struct dom_text *text)
+{
+ /* Finalise node */
+ dom_text_finalise(doc, text);
+
+ /* Free node */
+ dom_document_alloc(doc, text, 0);
+}
+
+/**
* Initialise a text node
*
* \param text The node to initialise
@@ -82,6 +99,19 @@ dom_exception dom_text_initialise(struct dom_text *text,
}
/**
+ * Finalise a text node
+ *
+ * \param doc The owning document
+ * \param text The text node to finalise
+ *
+ * The contents of ::text will be cleaned up. ::text will not be freed.
+ */
+void dom_text_finalise(struct dom_document *doc, struct dom_text *text)
+{
+ dom_characterdata_finalise(doc, &text->base);
+}
+
+/**
* Split a text node at a given character offset
*
* \param text The node to split
diff --git a/src/core/text.h b/src/core/text.h
index be927df..7af0f76 100644
--- a/src/core/text.h
+++ b/src/core/text.h
@@ -31,8 +31,12 @@ dom_exception dom_text_create(struct dom_document *doc,
struct dom_string *name, struct dom_string *value,
struct dom_text **result);
+void dom_text_destroy(struct dom_document *doc, struct dom_text *text);
+
dom_exception dom_text_initialise(struct dom_text *text,
struct dom_document *doc, dom_node_type type,
struct dom_string *name, struct dom_string *value);
+void dom_text_finalise(struct dom_document *doc, struct dom_text *text);
+
#endif