From b657c277f517f4ab0a4da21e4f8c4cb6f8f53013 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Mon, 30 Aug 2010 13:06:19 +0000 Subject: Merge branches/struggleyb/libdom-html to trunk. A few additional fixes to reduce the number of regressions to single figures. svn path=/trunk/dom/; revision=10724 --- src/html/html_collection.c | 300 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 src/html/html_collection.c (limited to 'src/html/html_collection.c') diff --git a/src/html/html_collection.c b/src/html/html_collection.c new file mode 100644 index 0000000..e0c96b9 --- /dev/null +++ b/src/html/html_collection.c @@ -0,0 +1,300 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2009 Bo Yang + */ + +#include + +#include + +#include "html/html_collection.h" + +#include "core/node.h" +#include "core/document.h" +#include "core/element.h" +#include "core/string.h" + +/*-----------------------------------------------------------------------*/ +/* Constructor and destructor */ + +/** + * Create a dom_html_collection + * + * \param doc The document + * \param root The root element of the collection + * \param ic The callback function used to determin whether certain node + * belongs to the collection + * \param col The result collection object + * \return DOM_NO_ERR on success, appropriate dom_exception on failure. + */ +dom_exception _dom_html_collection_create(struct dom_document *doc, + struct dom_node_internal *root, + dom_callback_is_in_collection ic, + struct dom_html_collection **col) +{ + *col = _dom_document_alloc(doc, NULL, sizeof(dom_html_collection)); + if (*col == NULL) + return DOM_NO_MEM_ERR; + + return _dom_html_collection_initialise(doc, *col, root, ic); +} + +/** + * Intialiase a dom_html_collection + * + * \param doc The document + * \param col The collection object to be initialised + * \param root The root element of the collection + * \param ic The callback function used to determin whether certain node + * belongs to the collection + * \return DOM_NO_ERR on success. + */ +dom_exception _dom_html_collection_initialise(struct dom_document *doc, + struct dom_html_collection *col, + struct dom_node_internal *root, + dom_callback_is_in_collection ic) +{ + assert(doc != NULL); + assert(ic != NULL); + assert(root != NULL); + + col->doc = doc; + dom_node_ref(doc); + + col->root = root; + dom_node_ref(root); + + col->ic = ic; + col->refcnt = 1; + + return DOM_NO_ERR; +} + +/** + * Finalise a dom_html_collection object + * + * \param col The dom_html_collection object + */ +void _dom_html_collection_finalise(struct dom_html_collection *col) +{ + dom_node_unref(col->doc); + col->doc = NULL; + + dom_node_unref(col->root); + col->root = NULL; + + col->ic = NULL; +} + +/** + * Destroy a dom_html_collection object + * \param col The dom_html_collection object + */ +void _dom_html_collection_destroy(struct dom_html_collection *col) +{ + struct dom_document *doc = col->doc; + _dom_html_collection_finalise(col); + + _dom_document_alloc(doc, col, 0); +} + + +/*-----------------------------------------------------------------------*/ +/* Public API */ + +/** + * Get the length of this dom_html_collection + * + * \param col The dom_html_collection object + * \param len The returned length of this collection + * \return DOM_NO_ERR on success. + */ +dom_exception dom_html_collection_get_length(dom_html_collection *col, + unsigned long *len) +{ + struct dom_node_internal *node = col->root; + *len = 0; + + while (node != NULL) { + if (node->type == DOM_ELEMENT_NODE && col->ic(node) == true) + (*len)++; + + /* Depth first iterating */ + if (node->first_child != NULL) { + node = node->first_child; + } else if (node->next != NULL) { + node = node->next; + } else { + /* No children and siblings */ + struct dom_node_internal *parent = node->parent; + + while (parent != col->root && + node == parent->last_child) { + node = parent; + parent = parent->parent; + } + + if (parent == col->root) + node = NULL; + else + node = node->next; + } + } + + return DOM_NO_ERR; +} + +/** + * Get the node with certain index + * + * \param col The dom_html_collection object + * \param index The index number based on zero + * \param node The returned node object + * \return DOM_NO_ERR on success. + */ +dom_exception dom_html_collection_item(dom_html_collection *col, + unsigned long index, struct dom_node **node) +{ + struct dom_node_internal *n = col->root; + unsigned long len = 0; + + while (n != NULL) { + if (n->type == DOM_ELEMENT_NODE && col->ic(n) == true) + len++; + + if (len == index + 1) { + dom_node_ref(n); + *node = (struct dom_node *) n; + return DOM_NO_ERR; + } + + /* Depth first iterating */ + if (n->first_child != NULL) { + n = n->first_child; + } else if (n->next != NULL) { + n = n->next; + } else { + /* No children and siblings */ + struct dom_node_internal *parent = n->parent; + + while (parent != col->root && + n == parent->last_child) { + n = parent; + parent = parent->parent; + } + + if (parent == col->root) + n = NULL; + else + n = n->next; + } + } + + /* Not find the node */ + *node = NULL; + return DOM_NO_ERR; +} + +/** + * Get the node in the collection according name + * + * \param col The collection + * \param name The name of target node + * \param node The returned node object + * \return DOM_NO_ERR on success. + */ +dom_exception dom_html_collection_named_item(dom_html_collection *col, + struct dom_string *name, struct dom_node **node) +{ + struct dom_node_internal *n = col->root; + dom_exception err; + lwc_string *str = NULL; + err = _dom_node_get_intern_string(n, name, &str); + if (err != DOM_NO_ERR) + return err; + + + while (node != NULL) { + if (n->type == DOM_ELEMENT_NODE && col->ic(n) == true) { + lwc_string *id = NULL; + err = _dom_element_get_id((struct dom_element *) n, + &id); + if (err != DOM_NO_ERR) { + _dom_node_unref_intern_string(n, id); + return err; + } + + /* Compare the lwc_string directly */ + if (str == id) { + *node = (struct dom_node *) n; + dom_node_ref(n); + _dom_node_unref_intern_string(n, id); + _dom_node_unref_intern_string(n, str); + + return DOM_NO_ERR; + } + + _dom_node_unref_intern_string(n, id); + } + + /* Depth first iterating */ + if (n->first_child != NULL) { + n = n->first_child; + } else if (n->next != NULL) { + n = n->next; + } else { + /* No children and siblings */ + struct dom_node_internal *parent = n->parent; + + while (parent != col->root && + n == parent->last_child) { + n = parent; + parent = parent->parent; + } + + if (parent == col->root) + n = NULL; + else + n = n->next; + } + } + + /* Not found the target node */ + *node = NULL; + _dom_node_unref_intern_string(n, str); + + return DOM_NO_ERR; +} + +/** + * Claim a reference on this collection + * + * \pram col The collection object + */ +void dom_html_collection_ref(dom_html_collection *col) +{ + if (col == NULL) + return; + + col->refcnt ++; +} + +/** + * Relese a reference on this collection + * + * \pram col The collection object + */ +void dom_html_collection_unref(dom_html_collection *col) +{ + if (col == NULL) + return; + + if (col->refcnt > 0) + col->refcnt --; + + if (col->refcnt == 0) + _dom_html_collection_destroy(col); +} + -- cgit v1.2.3