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 2007 John-Mark Bell <jmb@netsurf-browser.org>
  6.  * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
  7.  */
  8.  
  9. #include <assert.h>
  10. #include <stdlib.h>
  11.  
  12. #include <dom/core/characterdata.h>
  13. #include <dom/core/string.h>
  14. #include <dom/events/events.h>
  15.  
  16. #include "core/characterdata.h"
  17. #include "core/document.h"
  18. #include "core/node.h"
  19. #include "utils/utils.h"
  20. #include "events/mutation_event.h"
  21.  
  22. /* The virtual functions for dom_characterdata, we make this vtable
  23.  * public to each child class */
  24. struct dom_characterdata_vtable characterdata_vtable = {
  25.         {
  26.                 {
  27.                         DOM_NODE_EVENT_TARGET_VTABLE
  28.                 },
  29.                 DOM_NODE_VTABLE_CHARACTERDATA
  30.         },
  31.         DOM_CHARACTERDATA_VTABLE
  32. };
  33.  
  34.  
  35. /* Create a DOM characterdata node and compose the vtable */
  36. dom_characterdata *_dom_characterdata_create(void)
  37. {
  38.         dom_characterdata *cdata = malloc(sizeof(struct dom_characterdata));
  39.         if (cdata == NULL)
  40.                 return NULL;
  41.  
  42.         cdata->base.base.vtable = &characterdata_vtable;
  43.         cdata->base.vtable = NULL;
  44.  
  45.         return cdata;
  46. }
  47.  
  48. /**
  49.  * Initialise a character data node
  50.  *
  51.  * \param node   The node to initialise
  52.  * \param doc    The document which owns the node
  53.  * \param type   The node type required
  54.  * \param name   The node name, or NULL
  55.  * \param value  The node value, or NULL
  56.  * \return DOM_NO_ERR on success.
  57.  *
  58.  * ::doc, ::name and ::value will have their reference counts increased.
  59.  */
  60. dom_exception _dom_characterdata_initialise(struct dom_characterdata *cdata,
  61.                 struct dom_document *doc, dom_node_type type,
  62.                 dom_string *name, dom_string *value)
  63. {
  64.         return _dom_node_initialise(&cdata->base, doc, type,
  65.                         name, value, NULL, NULL);
  66. }
  67.  
  68. /**
  69.  * Finalise a character data node
  70.  *
  71.  * \param cdata  The node to finalise
  72.  *
  73.  * The contents of ::cdata will be cleaned up. ::cdata will not be freed.
  74.  */
  75. void _dom_characterdata_finalise(struct dom_characterdata *cdata)
  76. {
  77.         _dom_node_finalise(&cdata->base);
  78. }
  79.  
  80.  
  81. /*----------------------------------------------------------------------*/
  82.  
  83. /* The public virtual functions */
  84.  
  85. /**
  86.  * Retrieve data from a character data node
  87.  *
  88.  * \param cdata  Character data node to retrieve data from
  89.  * \param data   Pointer to location to receive data
  90.  * \return DOM_NO_ERR.
  91.  *
  92.  * The returned string will have its reference count increased. It is
  93.  * the responsibility of the caller to unref the string once it has
  94.  * finished with it.
  95.  *
  96.  * DOM3Core states that this can raise DOMSTRING_SIZE_ERR. It will not in
  97.  * this implementation; dom_strings are unbounded.
  98.  */
  99. dom_exception _dom_characterdata_get_data(struct dom_characterdata *cdata,
  100.                 dom_string **data)
  101. {
  102.         struct dom_node_internal *c = (struct dom_node_internal *) cdata;
  103.  
  104.         if (c->value != NULL) {
  105.                 dom_string_ref(c->value);
  106.         }
  107.         *data = c->value;
  108.  
  109.         return DOM_NO_ERR;
  110. }
  111.  
  112. /**
  113.  * Set the content of a character data node
  114.  *
  115.  * \param cdata  Node to set the content of
  116.  * \param data   New value for node
  117.  * \return DOM_NO_ERR                      on success,
  118.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::cdata is readonly.
  119.  *
  120.  * The new content will have its reference count increased, so the caller
  121.  * should unref it after the call (as the caller should have already claimed
  122.  * a reference on the string). The node's existing content will be unrefed.
  123.  */
  124. dom_exception _dom_characterdata_set_data(struct dom_characterdata *cdata,
  125.                 dom_string *data)
  126. {
  127.         struct dom_node_internal *c = (struct dom_node_internal *) cdata;
  128.         dom_exception err;
  129.         struct dom_document *doc;
  130.         bool success = true;
  131.  
  132.         if (_dom_node_readonly(c)) {
  133.                 return DOM_NO_MODIFICATION_ALLOWED_ERR;
  134.         }
  135.  
  136.         /* Dispatch a DOMCharacterDataModified event */
  137.         doc = dom_node_get_owner(cdata);
  138.         err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
  139.                         data, &success);
  140.         if (err != DOM_NO_ERR)
  141.                 return err;
  142.  
  143.         if (c->value != NULL) {
  144.                 dom_string_unref(c->value);
  145.         }
  146.  
  147.         dom_string_ref(data);
  148.         c->value = data;
  149.  
  150.         success = true;
  151.         return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
  152. }
  153.  
  154. /**
  155.  * Get the length (in characters) of a character data node's content
  156.  *
  157.  * \param cdata   Node to read content length of
  158.  * \param length  Pointer to location to receive character length of content
  159.  * \return DOM_NO_ERR.
  160.  */
  161. dom_exception _dom_characterdata_get_length(struct dom_characterdata *cdata,
  162.                 uint32_t *length)
  163. {
  164.         struct dom_node_internal *c = (struct dom_node_internal *) cdata;
  165.  
  166.         if (c->value != NULL) {
  167.                 *length = dom_string_length(c->value);
  168.         } else {
  169.                 *length = 0;
  170.         }
  171.  
  172.         return DOM_NO_ERR;
  173. }
  174.  
  175. /**
  176.  * Extract a range of data from a character data node
  177.  *
  178.  * \param cdata   The node to extract data from
  179.  * \param offset  The character offset of substring to extract
  180.  * \param count   The number of characters to extract
  181.  * \param data    Pointer to location to receive substring
  182.  * \return DOM_NO_ERR         on success,
  183.  *         DOM_INDEX_SIZE_ERR if ::offset is negative or greater than the
  184.  *                            number of characters in ::cdata or
  185.  *                            ::count is negative.
  186.  *
  187.  * The returned string will have its reference count increased. It is
  188.  * the responsibility of the caller to unref the string once it has
  189.  * finished with it.
  190.  *
  191.  * DOM3Core states that this can raise DOMSTRING_SIZE_ERR. It will not in
  192.  * this implementation; dom_strings are unbounded.
  193.  */
  194. dom_exception _dom_characterdata_substring_data(
  195.                 struct dom_characterdata *cdata, uint32_t offset,
  196.                 uint32_t count, dom_string **data)
  197. {
  198.         struct dom_node_internal *c = (struct dom_node_internal *) cdata;
  199.         uint32_t len, end;
  200.  
  201.         if ((int32_t) offset < 0 || (int32_t) count < 0) {
  202.                 return DOM_INDEX_SIZE_ERR;
  203.         }
  204.  
  205.         if (c->value != NULL) {
  206.                 len = dom_string_length(c->value);
  207.         } else {
  208.                 len = 0;
  209.         }
  210.  
  211.         if (offset > len) {
  212.                 return DOM_INDEX_SIZE_ERR;
  213.         }
  214.  
  215.         end = (offset + count) >= len ? len : offset + count;
  216.  
  217.         return dom_string_substr(c->value, offset, end, data);
  218. }
  219.  
  220. /**
  221.  * Append data to the end of a character data node's content
  222.  *
  223.  * \param cdata  The node to append data to
  224.  * \param data   The data to append
  225.  * \return DOM_NO_ERR                      on success,
  226.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::cdata is readonly.
  227.  */
  228. dom_exception _dom_characterdata_append_data(struct dom_characterdata *cdata,
  229.                 dom_string *data)
  230. {
  231.         struct dom_node_internal *c = (struct dom_node_internal *) cdata;
  232.         dom_string *temp;
  233.         dom_exception err;
  234.         struct dom_document *doc;
  235.         bool success = true;
  236.  
  237.         if (_dom_node_readonly(c)) {
  238.                 return DOM_NO_MODIFICATION_ALLOWED_ERR;
  239.         }
  240.  
  241.         err = dom_string_concat(c->value, data, &temp);
  242.         if (err != DOM_NO_ERR) {
  243.                 return err;
  244.         }
  245.  
  246.         /* Dispatch a DOMCharacterDataModified event */
  247.         doc = dom_node_get_owner(cdata);
  248.         err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
  249.                         temp, &success);
  250.         if (err != DOM_NO_ERR) {
  251.                 dom_string_unref(temp);
  252.                 return err;
  253.         }
  254.  
  255.         if (c->value != NULL) {
  256.                 dom_string_unref(c->value);
  257.         }
  258.  
  259.         c->value = temp;
  260.  
  261.         success = true;
  262.         return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
  263. }
  264.  
  265. /**
  266.  * Insert data into a character data node's content
  267.  *
  268.  * \param cdata   The node to insert into
  269.  * \param offset  The character offset to insert at
  270.  * \param data    The data to insert
  271.  * \return DOM_NO_ERR                      on success,
  272.  *         DOM_INDEX_SIZE_ERR              if ::offset is negative or greater
  273.  *                                         than the number of characters in
  274.  *                                         ::cdata,
  275.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::cdata is readonly.
  276.  */
  277. dom_exception _dom_characterdata_insert_data(struct dom_characterdata *cdata,
  278.                 uint32_t offset, dom_string *data)
  279. {
  280.         struct dom_node_internal *c = (struct dom_node_internal *) cdata;
  281.         dom_string *temp;
  282.         uint32_t len;
  283.         dom_exception err;
  284.         struct dom_document *doc;
  285.         bool success = true;
  286.  
  287.         if (_dom_node_readonly(c)) {
  288.                 return DOM_NO_MODIFICATION_ALLOWED_ERR;
  289.         }
  290.  
  291.         if ((int32_t) offset < 0) {
  292.                 return DOM_INDEX_SIZE_ERR;
  293.         }
  294.  
  295.         if (c->value != NULL) {
  296.                 len = dom_string_length(c->value);
  297.         } else {
  298.                 len = 0;
  299.         }
  300.  
  301.         if (offset > len) {
  302.                 return DOM_INDEX_SIZE_ERR;
  303.         }
  304.  
  305.         err = dom_string_insert(c->value, data, offset, &temp);
  306.         if (err != DOM_NO_ERR) {
  307.                 return err;
  308.         }
  309.  
  310.         /* Dispatch a DOMCharacterDataModified event */
  311.         doc = dom_node_get_owner(cdata);
  312.         err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
  313.                         temp, &success);
  314.         if (err != DOM_NO_ERR)
  315.                 return err;
  316.  
  317.         if (c->value != NULL) {
  318.                 dom_string_unref(c->value);
  319.         }
  320.  
  321.         c->value = temp;
  322.  
  323.         success = true;
  324.         return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
  325. }
  326.  
  327. /**
  328.  * Delete data from a character data node's content
  329.  *
  330.  * \param cdata   The node to delete from
  331.  * \param offset  The character offset to start deletion from
  332.  * \param count   The number of characters to delete
  333.  * \return DOM_NO_ERR                      on success,
  334.  *         DOM_INDEX_SIZE_ERR              if ::offset is negative or greater
  335.  *                                         than the number of characters in
  336.  *                                         ::cdata or ::count is negative,
  337.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::cdata is readonly.
  338.  */
  339. dom_exception _dom_characterdata_delete_data(struct dom_characterdata *cdata,
  340.                 uint32_t offset, uint32_t count)
  341. {
  342.         struct dom_node_internal *c = (struct dom_node_internal *) cdata;
  343.         dom_string *temp;
  344.         uint32_t len, end;
  345.         dom_exception err;
  346.         struct dom_document *doc;
  347.         bool success = true;
  348.         dom_string *empty;
  349.  
  350.         if (_dom_node_readonly(c)) {
  351.                 return DOM_NO_MODIFICATION_ALLOWED_ERR;
  352.         }
  353.  
  354.         if ((int32_t) offset < 0 || (int32_t) count < 0) {
  355.                 return DOM_INDEX_SIZE_ERR;
  356.         }
  357.  
  358.         if (c->value != NULL) {
  359.                 len = dom_string_length(c->value);
  360.         } else {
  361.                 len = 0;
  362.         }
  363.  
  364.         if (offset > len) {
  365.                 return DOM_INDEX_SIZE_ERR;
  366.         }
  367.  
  368.         end = (offset + count) >= len ? len : offset + count;
  369.  
  370.         empty = ((struct dom_document *)
  371.                  ((struct dom_node_internal *)c)->owner)->_memo_empty;
  372.  
  373.         err = dom_string_replace(c->value, empty, offset, end, &temp);
  374.         if (err != DOM_NO_ERR) {
  375.                 return err;
  376.         }
  377.  
  378.         /* Dispatch a DOMCharacterDataModified event */
  379.         doc = dom_node_get_owner(cdata);
  380.         err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
  381.                         temp, &success);
  382.         if (err != DOM_NO_ERR)
  383.                 return err;
  384.  
  385.         if (c->value != NULL) {
  386.                 dom_string_unref(c->value);
  387.         }
  388.  
  389.         c->value = temp;
  390.  
  391.         success = true;
  392.         return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
  393. }
  394.  
  395. /**
  396.  * Replace a section of a character data node's content
  397.  *
  398.  * \param cdata   The node to modify
  399.  * \param offset  The character offset of the sequence to replace
  400.  * \param count   The number of characters to replace
  401.  * \param data    The replacement data
  402.  * \return DOM_NO_ERR                      on success,
  403.  *         DOM_INDEX_SIZE_ERR              if ::offset is negative or greater
  404.  *                                         than the number of characters in
  405.  *                                         ::cdata or ::count is negative,
  406.  *         DOM_NO_MODIFICATION_ALLOWED_ERR if ::cdata is readonly.
  407.  */
  408. dom_exception _dom_characterdata_replace_data(struct dom_characterdata *cdata,
  409.                 uint32_t offset, uint32_t count,
  410.                 dom_string *data)
  411. {
  412.         struct dom_node_internal *c = (struct dom_node_internal *) cdata;
  413.         dom_string *temp;
  414.         uint32_t len, end;
  415.         dom_exception err;
  416.         struct dom_document *doc;
  417.         bool success = true;
  418.  
  419.         if (_dom_node_readonly(c)) {
  420.                 return DOM_NO_MODIFICATION_ALLOWED_ERR;
  421.         }
  422.  
  423.         if ((int32_t) offset < 0 || (int32_t) count < 0) {
  424.                 return DOM_INDEX_SIZE_ERR;
  425.         }
  426.  
  427.         if (c->value != NULL) {
  428.                 len = dom_string_length(c->value);
  429.         } else {
  430.                 len = 0;
  431.         }
  432.  
  433.         if (offset > len) {
  434.                 return DOM_INDEX_SIZE_ERR;
  435.         }
  436.  
  437.         end = (offset + count) >= len ? len : offset + count;
  438.  
  439.         err = dom_string_replace(c->value, data, offset, end, &temp);
  440.         if (err != DOM_NO_ERR) {
  441.                 return err;
  442.         }
  443.  
  444.         /* Dispatch a DOMCharacterDataModified event */
  445.         doc = dom_node_get_owner(cdata);
  446.         err = _dom_dispatch_characterdata_modified_event(doc, c, c->value, temp,
  447.                         &success);
  448.         if (err != DOM_NO_ERR)
  449.                 return err;
  450.  
  451.         if (c->value != NULL) {
  452.                 dom_string_unref(c->value);
  453.         }
  454.  
  455.         c->value = temp;
  456.  
  457.         success = true;
  458.         return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
  459. }
  460.  
  461. dom_exception _dom_characterdata_get_text_content(dom_node_internal *node,
  462.                                                   dom_string **result)
  463. {
  464.         dom_characterdata *cdata = (dom_characterdata *)node;
  465.        
  466.         return dom_characterdata_get_data(cdata, result);
  467. }
  468.  
  469. dom_exception _dom_characterdata_set_text_content(dom_node_internal *node,
  470.                                                   dom_string *content)
  471. {
  472.         dom_characterdata *cdata = (dom_characterdata *)node;
  473.        
  474.         return dom_characterdata_set_data(cdata, content);
  475. }
  476.  
  477. /*----------------------------------------------------------------------*/
  478.  
  479. /* The protected virtual functions of Node, see core/node.h for details */
  480. void _dom_characterdata_destroy(struct dom_node_internal *node)
  481. {
  482.         assert("Should never be here" == NULL);
  483.         UNUSED(node);
  484. }
  485.  
  486. /* The copy constructor of this class */
  487. dom_exception _dom_characterdata_copy(dom_node_internal *old,
  488.                 dom_node_internal **copy)
  489. {
  490.         dom_characterdata *new_node;
  491.         dom_exception err;
  492.  
  493.         new_node = malloc(sizeof(dom_characterdata));
  494.         if (new_node == NULL)
  495.                 return DOM_NO_MEM_ERR;
  496.  
  497.         err = dom_characterdata_copy_internal(old, new_node);
  498.         if (err != DOM_NO_ERR) {
  499.                 free(new_node);
  500.                 return err;
  501.         }
  502.  
  503.         *copy = (dom_node_internal *) new_node;
  504.  
  505.         return DOM_NO_ERR;
  506. }
  507.  
  508. dom_exception _dom_characterdata_copy_internal(dom_characterdata *old,
  509.                 dom_characterdata *new)
  510. {
  511.         return dom_node_copy_internal(old, new);
  512. }
  513.  
  514.