Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of libdom.
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
  6.  */
  7.  
  8. #include <assert.h>
  9. #include <stdlib.h>
  10.  
  11. #include <libwapcaplet/libwapcaplet.h>
  12.  
  13. #include "html/html_collection.h"
  14.  
  15. #include "core/node.h"
  16. #include "core/element.h"
  17. #include "core/string.h"
  18.  
  19. /*-----------------------------------------------------------------------*/
  20. /* Constructor and destructor */
  21.  
  22. /**
  23.  * Create a dom_html_collection
  24.  *
  25.  * \param doc   The document
  26.  * \param root  The root element of the collection
  27.  * \param ic    The callback function used to determin whether certain node
  28.  *              beint32_ts to the collection
  29.  * \param col   The result collection object
  30.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  31.  */
  32. dom_exception _dom_html_collection_create(struct dom_html_document *doc,
  33.                 struct dom_node_internal *root,
  34.                 dom_callback_is_in_collection ic,
  35.                 void *ctx,
  36.                 struct dom_html_collection **col)
  37. {
  38.         *col = malloc(sizeof(dom_html_collection));
  39.         if (*col == NULL)
  40.                 return DOM_NO_MEM_ERR;
  41.        
  42.         return _dom_html_collection_initialise(doc, *col, root, ic, ctx);
  43. }
  44.  
  45. /**
  46.  * Intialiase a dom_html_collection
  47.  *
  48.  * \param doc   The document
  49.  * \param col   The collection object to be initialised
  50.  * \param root  The root element of the collection
  51.  * \param ic    The callback function used to determin whether certain node
  52.  *              beint32_ts to the collection
  53.  * \return DOM_NO_ERR on success.
  54.  */
  55. dom_exception _dom_html_collection_initialise(struct dom_html_document *doc,
  56.                 struct dom_html_collection *col,
  57.                 struct dom_node_internal *root,
  58.                 dom_callback_is_in_collection ic, void *ctx)
  59. {
  60.         assert(doc != NULL);
  61.         assert(ic != NULL);
  62.         assert(root != NULL);
  63.  
  64.         col->doc = doc;
  65.         dom_node_ref(doc);
  66.  
  67.         col->root = root;
  68.         dom_node_ref(root);
  69.  
  70.         col->ic = ic;
  71.         col->ctx = ctx;
  72.         col->refcnt = 1;
  73.  
  74.         return DOM_NO_ERR;
  75. }
  76.  
  77. /**
  78.  * Finalise a dom_html_collection object
  79.  *
  80.  * \param col  The dom_html_collection object
  81.  */
  82. void _dom_html_collection_finalise(struct dom_html_collection *col)
  83. {
  84.         dom_node_unref(col->doc);
  85.         col->doc = NULL;
  86.  
  87.         dom_node_unref(col->root);
  88.         col->root = NULL;
  89.  
  90.         col->ic = NULL;
  91. }
  92.  
  93. /**
  94.  * Destroy a dom_html_collection object
  95.  * \param col  The dom_html_collection object
  96.  */
  97. void _dom_html_collection_destroy(struct dom_html_collection *col)
  98. {
  99.         _dom_html_collection_finalise(col);
  100.  
  101.         free(col);
  102. }
  103.  
  104.  
  105. /*-----------------------------------------------------------------------*/
  106. /* Public API */
  107.  
  108. /**
  109.  * Get the length of this dom_html_collection
  110.  *
  111.  * \param col  The dom_html_collection object
  112.  * \param len  The returned length of this collection
  113.  * \return DOM_NO_ERR on success.
  114.  */
  115. dom_exception dom_html_collection_get_length(dom_html_collection *col,
  116.                 uint32_t *len)
  117. {
  118.         struct dom_node_internal *node = col->root;
  119.         *len = 0;
  120.  
  121.         while (node != NULL) {
  122.                 if (node->type == DOM_ELEMENT_NODE &&
  123.                     col->ic(node, col->ctx) == true)
  124.                         (*len)++;
  125.  
  126.                 /* Depth first iterating */
  127.                 if (node->first_child != NULL) {
  128.                         node = node->first_child;
  129.                 } else if (node->next != NULL) {
  130.                         node = node->next;
  131.                 } else {
  132.                         /* No children and siblings */
  133.                         struct dom_node_internal *parent = node->parent;
  134.  
  135.                         while (parent != col->root &&
  136.                                         node == parent->last_child) {
  137.                                 node = parent;
  138.                                 parent = parent->parent;
  139.                         }
  140.                        
  141.                         if (node == col->root)
  142.                                 node = NULL;
  143.                         else
  144.                                 node = node->next;
  145.                 }
  146.         }
  147.  
  148.         return DOM_NO_ERR;
  149. }
  150.  
  151. /**
  152.  * Get the node with certain index
  153.  *
  154.  * \param col  The dom_html_collection object
  155.  * \param index  The index number based on zero
  156.  * \param node   The returned node object
  157.  * \return DOM_NO_ERR on success.
  158.  */
  159. dom_exception dom_html_collection_item(dom_html_collection *col,
  160.                 uint32_t index, struct dom_node **node)
  161. {
  162.         struct dom_node_internal *n = col->root;
  163.         uint32_t len = 0;
  164.  
  165.         while (n != NULL) {
  166.                 if (n->type == DOM_ELEMENT_NODE &&
  167.                     col->ic(n, col->ctx) == true)
  168.                         len++;
  169.  
  170.                 if (len == index + 1) {
  171.                         dom_node_ref(n);
  172.                         *node = (struct dom_node *) n;
  173.                         return DOM_NO_ERR;
  174.                 }
  175.  
  176.                 /* Depth first iterating */
  177.                 if (n->first_child != NULL) {
  178.                         n = n->first_child;
  179.                 } else if (n->next != NULL) {
  180.                         n = n->next;
  181.                 } else {
  182.                         /* No children and siblings */
  183.                         struct dom_node_internal *parent = n->parent;
  184.  
  185.                         while (parent != col->root &&
  186.                                         n == parent->last_child) {
  187.                                 n = parent;
  188.                                 parent = parent->parent;
  189.                         }
  190.                        
  191.                         if (n == col->root)
  192.                                 n = NULL;
  193.                         else
  194.                                 n = n->next;
  195.                 }
  196.         }
  197.  
  198.         /* Not find the node */
  199.         *node = NULL;
  200.         return DOM_NO_ERR;
  201. }
  202.  
  203. /**
  204.  * Get the node in the collection according name
  205.  *
  206.  * \param col   The collection
  207.  * \param name  The name of target node
  208.  * \param node  The returned node object
  209.  * \return DOM_NO_ERR on success.
  210.  */
  211. dom_exception dom_html_collection_named_item(dom_html_collection *col,
  212.                 dom_string *name, struct dom_node **node)
  213. {
  214.         struct dom_node_internal *n = col->root;
  215.         dom_exception err;
  216.        
  217.         while (n != NULL) {
  218.                 if (n->type == DOM_ELEMENT_NODE &&
  219.                     col->ic(n, col->ctx) == true) {
  220.                         dom_string *id = NULL;
  221.  
  222.                         err = _dom_element_get_id((struct dom_element *) n,
  223.                                         &id);
  224.                         if (err != DOM_NO_ERR) {
  225.                                 return err;
  226.                         }
  227.  
  228.                         if (id != NULL && dom_string_isequal(name, id)) {
  229.                                 *node = (struct dom_node *) n;
  230.                                 dom_node_ref(n);
  231.                                 dom_string_unref(id);
  232.  
  233.                                 return DOM_NO_ERR;
  234.                         }
  235.  
  236.                         if (id != NULL)
  237.                                 dom_string_unref(id);
  238.                 }
  239.  
  240.                 /* Depth first iterating */
  241.                 if (n->first_child != NULL) {
  242.                         n = n->first_child;
  243.                 } else if (n->next != NULL) {
  244.                         n = n->next;
  245.                 } else {
  246.                         /* No children and siblings */
  247.                         struct dom_node_internal *parent = n->parent;
  248.  
  249.                         while (parent != col->root &&
  250.                                         n == parent->last_child) {
  251.                                 n = parent;
  252.                                 parent = parent->parent;
  253.                         }
  254.                        
  255.                         if (parent == col->root)
  256.                                 n = NULL;
  257.                         else
  258.                                 n = n->next;
  259.                 }
  260.         }
  261.  
  262.         /* Not found the target node */
  263.         *node = NULL;
  264.  
  265.         return DOM_NO_ERR;
  266. }
  267.  
  268. /**
  269.  * Claim a reference on this collection
  270.  *
  271.  * \pram col  The collection object
  272.  */
  273. void dom_html_collection_ref(dom_html_collection *col)
  274. {
  275.         if (col == NULL)
  276.                 return;
  277.        
  278.         col->refcnt ++;
  279. }
  280.  
  281. /**
  282.  * Relese a reference on this collection
  283.  *
  284.  * \pram col  The collection object
  285.  */
  286. void dom_html_collection_unref(dom_html_collection *col)
  287. {
  288.         if (col == NULL)
  289.                 return;
  290.        
  291.         if (col->refcnt > 0)
  292.                 col->refcnt --;
  293.        
  294.         if (col->refcnt == 0)
  295.                 _dom_html_collection_destroy(col);
  296. }
  297.  
  298.