summaryrefslogtreecommitdiff
path: root/src/core/nodelist.c
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2007-07-10 21:36:14 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2007-07-10 21:36:14 +0000
commitacfc9fd1b44f7b72ba66705daf34914940509793 (patch)
tree9ed7dfde5664ff05fd47565d3f68c27792604500 /src/core/nodelist.c
parentd39dbc93d93f537962fe998031ade04d7ee6ca6a (diff)
downloadlibdom-acfc9fd1b44f7b72ba66705daf34914940509793.tar.gz
libdom-acfc9fd1b44f7b72ba66705daf34914940509793.tar.bz2
Add NodeList and string comparison API
svn path=/trunk/dom/; revision=3394
Diffstat (limited to 'src/core/nodelist.c')
-rw-r--r--src/core/nodelist.c228
1 files changed, 228 insertions, 0 deletions
diff --git a/src/core/nodelist.c b/src/core/nodelist.c
new file mode 100644
index 0000000..1fff561
--- /dev/null
+++ b/src/core/nodelist.c
@@ -0,0 +1,228 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org>
+ */
+
+#include <dom/core/node.h>
+#include <dom/core/nodelist.h>
+#include <dom/core/string.h>
+
+#include "core/document.h"
+#include "core/nodelist.h"
+
+#include "utils/utils.h"
+
+struct dom_node;
+
+/**
+ * DOM node list
+ */
+struct dom_nodelist {
+ struct dom_document *owner; /**< Owning document */
+
+ struct dom_node *root; /**< Root of applicable subtree */
+
+ enum { DOM_NODELIST_CHILDREN,
+ DOM_NODELIST_BY_NAME,
+ DOM_NODELIST_BY_NAMESPACE
+ } type; /**< List type */
+
+ union {
+ struct dom_string *name; /**< Tag name to match */
+ struct {
+ struct dom_string *namespace; /**< Namespace */
+ struct dom_string *localname; /**< Localname */
+ } ns; /**< Data for namespace matching */
+ } data;
+
+ uint32_t refcnt; /**< Reference count */
+};
+
+/**
+ * Create a nodelist
+ *
+ * \param doc Owning document
+ * \param root Root node of subtree that list applies to
+ * \param tagname Name of nodes in list (or NULL)
+ * \param namespace Namespace part of nodes in list (or NULL)
+ * \param localname Local part of nodes in list (or NULL)
+ * \param list Pointer to location to receive list
+ * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion
+ *
+ * ::root must be a node owned by ::doc
+ *
+ * If ::tagname is non-NULL, ::namespace and ::localname must be NULL and
+ * the created list will match nodes by name
+ * If ::namespace is non-NULL, ::localname must be non-NULL and
+ * ::tagname must be NULL and the created list will match nodes by namespace
+ * and localname
+ * If ::tagname, ::namespace and ::localname are NULL, the created list
+ * will match the children of ::root.
+ *
+ * The returned list will already be referenced, so the client need not
+ * do so explicitly. The client should unref the list once finished with it.
+ */
+dom_exception dom_nodelist_create(struct dom_document *doc,
+ struct dom_node *root, struct dom_string *tagname,
+ struct dom_string *namespace, struct dom_string *localname,
+ struct dom_nodelist **list)
+{
+ struct dom_nodelist *l;
+
+ l = dom_document_alloc(doc, NULL, sizeof(struct dom_nodelist));
+ if (l == NULL)
+ return DOM_NO_MEM_ERR;
+
+ dom_node_ref((struct dom_node *) doc);
+ l->owner = doc;
+
+ dom_node_ref(root);
+ l->root = root;
+
+ if (tagname != NULL && namespace == NULL && localname == NULL) {
+ dom_string_ref(tagname);
+ l->type = DOM_NODELIST_BY_NAME;
+ l->data.name = tagname;
+ } else if (namespace != NULL && localname != NULL &&
+ tagname == NULL) {
+ dom_string_ref(namespace);
+ dom_string_ref(localname);
+ l->type = DOM_NODELIST_BY_NAMESPACE;
+ l->data.ns.namespace = namespace;
+ l->data.ns.localname = localname;
+ } else {
+ l->type = DOM_NODELIST_CHILDREN;
+ }
+
+ l->refcnt = 1;
+
+ *list = l;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Claim a reference on a DOM node list
+ *
+ * \param list The list to claim a reference on
+ */
+void dom_nodelist_ref(struct dom_nodelist *list)
+{
+ list->refcnt++;
+}
+
+/**
+ * Release a reference on a DOM node list
+ *
+ * \param list The list to release the reference from
+ *
+ * If the reference count reaches zero, any memory claimed by the
+ * list will be released
+ */
+void dom_nodelist_unref(struct dom_nodelist *list)
+{
+ if (--list->refcnt == 0) {
+ switch (list->type) {
+ case DOM_NODELIST_CHILDREN:
+ /* Nothing to do */
+ break;
+ case DOM_NODELIST_BY_NAMESPACE:
+ dom_string_unref(list->data.ns.namespace);
+ dom_string_unref(list->data.ns.localname);
+ break;
+ case DOM_NODELIST_BY_NAME:
+ dom_string_unref(list->data.name);
+ break;
+ }
+
+ dom_node_unref(list->root);
+
+ dom_node_unref((struct dom_node *) list->owner);
+
+ /* Remove list from document */
+ dom_document_remove_nodelist(list->owner, list);
+
+ /* And destroy the list object */
+ dom_document_alloc(list->owner, list, 0);
+ }
+}
+
+/**
+ * Retrieve the length of a node list
+ *
+ * \param list List to retrieve length of
+ * \param length Pointer to location to receive length
+ * \return DOM_NO_ERR.
+ */
+dom_exception dom_nodelist_get_length(struct dom_nodelist *list,
+ unsigned long *length)
+{
+ UNUSED(list);
+ UNUSED(length);
+
+ return DOM_NOT_SUPPORTED_ERR;
+}
+
+/**
+ * Retrieve an item from a node list
+ *
+ * \param list The list to retrieve the item from
+ * \param index The list index to retrieve
+ * \param node Pointer to location to receive item
+ * \return DOM_NO_ERR.
+ *
+ * ::index is a zero-based index into ::list.
+ * ::index lies in the range [0, length-1]
+ *
+ * The returned node will have had its reference count increased. The client
+ * should unref the node once it has finished with it.
+ */
+dom_exception dom_nodelist_item(struct dom_nodelist *list,
+ unsigned long index, struct dom_node **node)
+{
+ UNUSED(list);
+ UNUSED(index);
+ UNUSED(node);
+
+ return DOM_NOT_SUPPORTED_ERR;
+}
+
+/**
+ * Match a nodelist instance against a set of nodelist creation parameters
+ *
+ * \param list List to match
+ * \param root Root node of subtree that list applies to
+ * \param tagname Name of nodes in list (or NULL)
+ * \param namespace Namespace part of nodes in list (or NULL)
+ * \param localname Local part of nodes in list (or NULL)
+ * \return true if list matches, false otherwise
+ */
+bool dom_nodelist_match(struct dom_nodelist *list, struct dom_node *root,
+ struct dom_string *tagname, struct dom_string *namespace,
+ struct dom_string *localname)
+{
+ if (list->root != root)
+ return false;
+
+ if (list->type == DOM_NODELIST_CHILDREN && tagname == NULL &&
+ namespace == NULL && localname == NULL) {
+ return true;
+ }
+
+ if (list->type == DOM_NODELIST_BY_NAME && tagname != NULL &&
+ namespace == NULL && localname == NULL) {
+ return (dom_string_cmp(list->data.name, tagname) == 0);
+ }
+
+ if (list->type == DOM_NODELIST_BY_NAMESPACE && tagname == NULL &&
+ namespace != NULL && localname != NULL) {
+ return (dom_string_cmp(list->data.ns.namespace,
+ namespace) == 0) &&
+ (dom_string_cmp(list->data.ns.localname,
+ localname) == 0);
+ }
+
+ return false;
+}