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.com>
  6.  */
  7.  
  8. #include <assert.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12.  
  13. #include "html/html_document.h"
  14. #include "html/html_element.h"
  15.  
  16. #include "core/node.h"
  17. #include "core/attr.h"
  18. #include "core/document.h"
  19. #include "utils/utils.h"
  20.  
  21. struct dom_html_element_vtable _dom_html_element_vtable = {
  22.         {
  23.                 {
  24.                         {
  25.                                 DOM_NODE_EVENT_TARGET_VTABLE
  26.                         },
  27.                         DOM_NODE_VTABLE_ELEMENT,
  28.                 },
  29.                 DOM_ELEMENT_VTABLE_HTML_ELEMENT,
  30.         },
  31.         DOM_HTML_ELEMENT_VTABLE
  32. };
  33.  
  34. static struct dom_element_protected_vtable _dom_html_element_protect_vtable = {
  35.         {
  36.                 DOM_HTML_ELEMENT_PROTECT_VTABLE
  37.         },
  38.         DOM_ELEMENT_PROTECT_VTABLE
  39. };
  40.  
  41. dom_exception _dom_html_element_create(struct dom_html_document *doc,
  42.                 dom_string *name, dom_string *namespace,
  43.                 dom_string *prefix, struct dom_html_element **result)
  44. {
  45.         dom_exception error;
  46.         dom_html_element *el;
  47.  
  48.         el = malloc(sizeof(struct dom_html_element));
  49.         if (el == NULL)
  50.                 return DOM_NO_MEM_ERR;
  51.  
  52.         el->base.base.base.vtable = &_dom_html_element_vtable;
  53.         el->base.base.vtable = &_dom_html_element_protect_vtable;
  54.  
  55.         error = _dom_html_element_initialise(doc, el, name, namespace,
  56.                         prefix);
  57.         if (error != DOM_NO_ERR) {
  58.                 free(el);
  59.                 return error;
  60.         }
  61.  
  62.         *result = el;
  63.  
  64.         return DOM_NO_ERR;
  65. }
  66.  
  67. dom_exception _dom_html_element_initialise(struct dom_html_document *doc,
  68.                 struct dom_html_element *el, dom_string *name,
  69.                 dom_string *namespace, dom_string *prefix)
  70. {
  71.         dom_exception err;
  72.  
  73.         err = _dom_element_initialise(&doc->base, &el->base, name, namespace, prefix);
  74.         if (err != DOM_NO_ERR)
  75.                 return err;
  76.        
  77.         return err;
  78. }
  79.  
  80. void _dom_html_element_finalise(struct dom_html_element *ele)
  81. {
  82.         _dom_element_finalise(&ele->base);
  83. }
  84.  
  85. /*------------------------------------------------------------------------*/
  86. /* The protected virtual functions */
  87.  
  88. /* The virtual destroy function, see src/core/node.c for detail */
  89. void _dom_html_element_destroy(dom_node_internal *node)
  90. {
  91.         dom_html_element *html = (dom_html_element *) node;
  92.  
  93.         _dom_html_element_finalise(html);
  94.  
  95.         free(html);
  96. }
  97.  
  98. /* The virtual copy function, see src/core/node.c for detail */
  99. dom_exception _dom_html_element_copy(dom_node_internal *old,
  100.                 dom_node_internal **copy)
  101. {
  102.         return _dom_element_copy(old, copy);
  103. }
  104.  
  105. /*-----------------------------------------------------------------------*/
  106. /* API functions */
  107.  
  108. #define SIMPLE_GET_SET(fattr,attr)                                    \
  109. dom_exception _dom_html_element_get_##fattr(dom_html_element *element, \
  110.                                            dom_string **fattr)          \
  111. {                                                                       \
  112.         dom_exception ret;                                              \
  113.         dom_string *_memo_##attr;                                       \
  114.                                                                         \
  115.         _memo_##attr =                                                  \
  116.                 ((struct dom_html_document *)                           \
  117.                  ((struct dom_node_internal *)element)->owner)->memoised[hds_##attr]; \
  118.                                                                         \
  119.         ret = dom_element_get_attribute(element, _memo_##attr, fattr);  \
  120.                                                                         \
  121.         return ret;                                                     \
  122. }                                                                       \
  123.                                                                         \
  124. dom_exception _dom_html_element_set_##fattr(dom_html_element *element,  \
  125.                                            dom_string *fattr)           \
  126. {                                                                       \
  127.         dom_exception ret;                                              \
  128.         dom_string *_memo_##attr;                                       \
  129.                                                                         \
  130.         _memo_##attr =                                                  \
  131.                 ((struct dom_html_document *)                           \
  132.                  ((struct dom_node_internal *)element)->owner)->memoised[hds_##attr]; \
  133.                                                                         \
  134.         ret = dom_element_set_attribute(element, _memo_##attr, fattr);  \
  135.                                                                         \
  136.         return ret;                                                     \
  137. }
  138.  
  139. SIMPLE_GET_SET(id,id)
  140. SIMPLE_GET_SET(title,title)
  141. SIMPLE_GET_SET(lang,lang)
  142. SIMPLE_GET_SET(dir,dir)
  143. SIMPLE_GET_SET(class_name,class)
  144.  
  145. /**
  146.  * Retrieve a list of descendant elements of an element which match a given
  147.  * tag name (caselessly)
  148.  *
  149.  * \param element  The root of the subtree to search
  150.  * \param name     The tag name to match (or "*" for all tags)
  151.  * \param result   Pointer to location to receive result
  152.  * \return DOM_NO_ERR.
  153.  *
  154.  * The returned nodelist will have its reference count increased. It is
  155.  * the responsibility of the caller to unref the nodelist once it has
  156.  * finished with it.
  157.  */
  158. dom_exception _dom_html_element_get_elements_by_tag_name(
  159.                 struct dom_element *element, dom_string *name,
  160.                 struct dom_nodelist **result)
  161. {
  162.         dom_exception err;
  163.         dom_node_internal *base = (dom_node_internal *) element;
  164.  
  165.         assert(base->owner != NULL);
  166.  
  167.         err = _dom_document_get_nodelist(base->owner,
  168.                         DOM_NODELIST_BY_NAME_CASELESS,
  169.                         (struct dom_node_internal *) element, name, NULL,
  170.                         NULL, result);
  171.  
  172.         return err;
  173. }
  174.  
  175. /**
  176.  * Retrieve a list of descendant elements of an element which match a given
  177.  * namespace/localname pair, caselessly.
  178.  *
  179.  * \param element  The root of the subtree to search
  180.  * \param namespace  The namespace URI to match (or "*" for all)
  181.  * \param localname  The local name to match (or "*" for all)
  182.  * \param result   Pointer to location to receive result
  183.  * \return DOM_NO_ERR            on success,
  184.  *         DOM_NOT_SUPPORTED_ERR if the implementation does not support
  185.  *                               the feature "XML" and the language exposed
  186.  *                               through the Document does not support
  187.  *                               Namespaces.
  188.  *
  189.  * The returned nodelist will have its reference count increased. It is
  190.  * the responsibility of the caller to unref the nodelist once it has
  191.  * finished with it.
  192.  */
  193. dom_exception _dom_html_element_get_elements_by_tag_name_ns(
  194.                 struct dom_element *element, dom_string *namespace,
  195.                 dom_string *localname, struct dom_nodelist **result)
  196. {
  197.         dom_exception err;
  198.  
  199.         /** \todo ensure XML feature is supported */
  200.  
  201.         err = _dom_document_get_nodelist(element->base.owner,
  202.                         DOM_NODELIST_BY_NAMESPACE_CASELESS,
  203.                         (struct dom_node_internal *) element, NULL,
  204.                         namespace, localname,
  205.                         result);
  206.  
  207.         return err;
  208. }
  209.  
  210. /*-----------------------------------------------------------------------*/
  211. /* Common functions */
  212.  
  213. /**
  214.  * Get the a bool property
  215.  *
  216.  * \param ele   The dom_html_element object
  217.  * \param name  The name of the attribute
  218.  * \param len   The length of ::name
  219.  * \param has   The returned status
  220.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  221.  */
  222. dom_exception dom_html_element_get_bool_property(dom_html_element *ele,
  223.                 const char *name, uint32_t len, bool *has)
  224. {
  225.         dom_string *str = NULL;
  226.         dom_attr *a = NULL;
  227.         dom_exception err;
  228.  
  229.         err = dom_string_create((const uint8_t *) name, len, &str);
  230.         if (err != DOM_NO_ERR)
  231.                 goto fail;
  232.  
  233.         err = dom_element_get_attribute_node(ele, str, &a);
  234.         if (err != DOM_NO_ERR)
  235.                 goto cleanup1;
  236.  
  237.         if (a != NULL) {
  238.                 *has = true;
  239.         } else {
  240.                 *has = false;
  241.         }
  242.  
  243.         dom_node_unref(a);
  244.  
  245. cleanup1:
  246.         dom_string_unref(str);
  247.  
  248. fail:
  249.         return err;
  250. }
  251.  
  252. /**
  253.  * Set a bool property
  254.  *
  255.  * \param ele   The dom_html_element object
  256.  * \param name  The name of the attribute
  257.  * \param len   The length of ::name
  258.  * \param has   The status
  259.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  260.  */
  261. dom_exception dom_html_element_set_bool_property(dom_html_element *ele,
  262.                 const char *name, uint32_t len, bool has)
  263. {
  264.         dom_string *str = NULL;
  265.         dom_attr *a = NULL;
  266.         dom_exception err;
  267.  
  268.         err = dom_string_create((const uint8_t *) name, len, &str);
  269.         if (err != DOM_NO_ERR)
  270.                 goto fail;
  271.  
  272.         err = dom_element_get_attribute_node(ele, str, &a);
  273.         if (err != DOM_NO_ERR)
  274.                 goto cleanup1;
  275.        
  276.         if (a != NULL && has == false) {
  277.                 dom_attr *res = NULL;
  278.  
  279.                 err = dom_element_remove_attribute_node(ele, a, &res);
  280.                 if (err != DOM_NO_ERR)
  281.                         goto cleanup2;
  282.  
  283.                 dom_node_unref(res);
  284.         } else if (a == NULL && has == true) {
  285.                 dom_document *doc = dom_node_get_owner(ele);
  286.                 dom_attr *res = NULL;
  287.  
  288.                 err = _dom_attr_create(doc, str, NULL, NULL, true, &a);
  289.                 if (err != DOM_NO_ERR) {
  290.                         goto cleanup1;
  291.                 }
  292.  
  293.                 err = dom_element_set_attribute_node(ele, a, &res);
  294.                 if (err != DOM_NO_ERR)
  295.                         goto cleanup2;
  296.  
  297.                 dom_node_unref(res);
  298.         }
  299.  
  300. cleanup2:
  301.         dom_node_unref(a);
  302.  
  303. cleanup1:
  304.         dom_string_unref(str);
  305.  
  306. fail:
  307.         return err;
  308. }
  309.  
  310. static char *_strndup(const char *s, size_t n)
  311. {
  312.         size_t len;
  313.         char *s2;
  314.  
  315.         for (len = 0; len != n && s[len] != '\0'; len++)
  316.                 continue;
  317.  
  318.         s2 = malloc(len + 1);
  319.         if (s2 == NULL)
  320.                 return NULL;
  321.  
  322.         memcpy(s2, s, len);
  323.         s2[len] = '\0';
  324.         return s2;
  325. }
  326.  
  327. /**
  328.  * Get the a int32_t property
  329.  *
  330.  * \param ele   The dom_html_element object
  331.  * \param name  The name of the attribute
  332.  * \param len   The length of ::name
  333.  * \param value   The returned value, or -1 if prop. not set
  334.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  335.  */
  336. dom_exception dom_html_element_get_int32_t_property(dom_html_element *ele,
  337.                 const char *name, uint32_t len, int32_t *value)
  338. {
  339.         dom_string *str = NULL, *s2 = NULL;
  340.         dom_attr *a = NULL;
  341.         dom_exception err;
  342.  
  343.         err = dom_string_create((const uint8_t *) name, len, &str);
  344.         if (err != DOM_NO_ERR)
  345.                 goto fail;
  346.  
  347.         err = dom_element_get_attribute_node(ele, str, &a);
  348.         if (err != DOM_NO_ERR)
  349.                 goto cleanup1;
  350.  
  351.         if (a != NULL) {
  352.                 err = dom_node_get_text_content(a, &s2);
  353.                 if (err == DOM_NO_ERR) {
  354.                         char *s3 = _strndup(dom_string_data(s2),
  355.                                             dom_string_byte_length(s2));
  356.                         if (s3 != NULL) {
  357.                                 *value = strtoul(s3, NULL, 0);
  358.                                 free(s3);
  359.                         } else {
  360.                                 err = DOM_NO_MEM_ERR;
  361.                         }
  362.                         dom_string_unref(s2);
  363.                 }
  364.         } else {
  365.                 /* Property is not set on this node */
  366.                 *value = -1;
  367.         }
  368.  
  369.         dom_node_unref(a);
  370.  
  371. cleanup1:
  372.         dom_string_unref(str);
  373.  
  374. fail:
  375.         return err;
  376. }
  377.  
  378. /**
  379.  * Set a int32_t property
  380.  *
  381.  * \param ele   The dom_html_element object
  382.  * \param name  The name of the attribute
  383.  * \param len   The length of ::name
  384.  * \param value   The value
  385.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  386.  */
  387. dom_exception dom_html_element_set_int32_t_property(dom_html_element *ele,
  388.                 const char *name, uint32_t len, uint32_t value)
  389. {
  390.         dom_string *str = NULL, *svalue = NULL;
  391.         dom_exception err;
  392.         char numbuffer[32];
  393.  
  394.         err = dom_string_create((const uint8_t *) name, len, &str);
  395.         if (err != DOM_NO_ERR)
  396.                 goto fail;
  397.        
  398.         if (snprintf(numbuffer, 32, "%u", value) == 32)
  399.                 numbuffer[31] = '\0';
  400.        
  401.         err = dom_string_create((const uint8_t *) numbuffer,
  402.                                 strlen(numbuffer), &svalue);
  403.         if (err != DOM_NO_ERR)
  404.                 goto cleanup;
  405.        
  406.         err = dom_element_set_attribute(ele, svalue, str);
  407.        
  408.         dom_string_unref(svalue);
  409. cleanup:
  410.         dom_string_unref(str);
  411.  
  412. fail:
  413.         return err;
  414. }
  415.