summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bindings/hubbub/parser.c2
-rw-r--r--include/dom/core/string.h8
-rw-r--r--src/core/document.c3
-rw-r--r--src/core/node.c2
-rw-r--r--src/core/string.c116
-rw-r--r--src/html/html_document.c91
-rw-r--r--src/html/html_document.h2
-rw-r--r--src/html/html_element.c67
-rw-r--r--src/html/html_element.h34
9 files changed, 271 insertions, 54 deletions
diff --git a/bindings/hubbub/parser.c b/bindings/hubbub/parser.c
index 9117c20..cc98335 100644
--- a/bindings/hubbub/parser.c
+++ b/bindings/hubbub/parser.c
@@ -459,8 +459,6 @@ static hubbub_error has_children(void *parser, void *node, bool *result)
dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser;
dom_exception err;
- UNUSED(parser);
-
err = dom_node_has_child_nodes((struct dom_node *) node, result);
if (err != DOM_NO_ERR) {
dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx,
diff --git a/include/dom/core/string.h b/include/dom/core/string.h
index b9b41a9..f2a6122 100644
--- a/include/dom/core/string.h
+++ b/include/dom/core/string.h
@@ -102,6 +102,14 @@ dom_exception dom_string_replace(dom_string *target,
dom_string *source, uint32_t i1, uint32_t i2,
dom_string **result);
+/* Generate an uppercase version of the given string */
+dom_exception dom_string_toupper(dom_string *source, bool ascii_only,
+ dom_string **upper);
+
+/* Generate an lowercase version of the given string */
+dom_exception dom_string_tolower(dom_string *source, bool ascii_only,
+ dom_string **lower);
+
/* Calculate a hash value from a dom string */
uint32_t dom_string_hash(dom_string *str);
diff --git a/src/core/document.c b/src/core/document.c
index c43f0bc..456d906 100644
--- a/src/core/document.c
+++ b/src/core/document.c
@@ -143,7 +143,7 @@ dom_exception _dom_document_initialise(dom_document *doc,
/* Intern the empty string. The use of a space in the constant
* is to prevent the compiler warning about an empty string.
*/
- err = dom_string_create_interned((const uint8_t *) ' ', 0,
+ err = dom_string_create_interned((const uint8_t *) " ", 0,
&doc->_memo_empty);
if (err != DOM_NO_ERR) {
dom_string_unref(doc->class_string);
@@ -184,6 +184,7 @@ bool _dom_document_finalise(dom_document *doc)
dom_string_unref(doc->id_name);
dom_string_unref(doc->class_string);
+ dom_string_unref(doc->_memo_empty);
_dom_document_event_internal_finalise(doc, &doc->dei);
diff --git a/src/core/node.c b/src/core/node.c
index 628c7c6..9ddac0c 100644
--- a/src/core/node.c
+++ b/src/core/node.c
@@ -1666,8 +1666,6 @@ dom_exception _dom_node_get_feature(dom_node_internal *node,
{
bool has;
- UNUSED(node);
-
dom_implementation_has_feature(dom_string_data(feature),
dom_string_data(version), &has);
diff --git a/src/core/string.c b/src/core/string.c
index aa046ad..0cadd77 100644
--- a/src/core/string.c
+++ b/src/core/string.c
@@ -890,7 +890,7 @@ const char *dom_string_data(const dom_string *str)
}
}
-/* Get the byte length of this dom_string
+/** Get the byte length of this dom_string
*
* \param str The dom_string object
*/
@@ -904,3 +904,117 @@ size_t dom_string_byte_length(const dom_string *str)
}
}
+/** Convert the given string to uppercase
+ *
+ * \param source
+ * \param ascii_only Whether to only convert [a-z] to [A-Z]
+ * \param upper Result pointer for uppercase string. Caller owns ref
+ *
+ * \return DOM_NO_ERR on success.
+ *
+ * \note Right now, will return DOM_NOT_SUPPORTED_ERR if ascii_only is false.
+ */
+dom_exception
+dom_string_toupper(dom_string *source, bool ascii_only, dom_string **upper)
+{
+ const uint8_t *orig_s = (const uint8_t *) dom_string_data(source);
+ const size_t nbytes = dom_string_byte_length(source);
+ uint8_t *copy_s;
+ size_t index = 0, clen;
+ parserutils_error err;
+ dom_exception exc;
+
+ if (ascii_only == false)
+ return DOM_NOT_SUPPORTED_ERR;
+
+ copy_s = malloc(nbytes);
+ if (copy_s == NULL)
+ return DOM_NO_MEM_ERR;
+ memcpy(copy_s, orig_s, nbytes);
+
+ while (index < nbytes) {
+ err = parserutils_charset_utf8_char_byte_length(orig_s + index,
+ &clen);
+ if (err != PARSERUTILS_OK) {
+ free(copy_s);
+ /** \todo Find a better exception */
+ return DOM_NO_MEM_ERR;
+ }
+
+ if (clen == 1) {
+ if (orig_s[index] >= 'a' &&
+ orig_s[index] <= 'z')
+ copy_s[index] -= 'a' - 'A';
+ }
+
+ index += clen;
+ }
+
+ if (((dom_string_internal*)source)->type == DOM_STRING_CDATA) {
+ exc = dom_string_create(copy_s, nbytes, upper);
+ } else {
+ exc = dom_string_create_interned(copy_s, nbytes, upper);
+ }
+
+ free(copy_s);
+
+ return exc;
+}
+
+/** Convert the given string to lowercase
+ *
+ * \param source
+ * \param ascii_only Whether to only convert [a-z] to [A-Z]
+ * \param lower Result pointer for lowercase string. Caller owns ref
+ *
+ * \return DOM_NO_ERR on success.
+ *
+ * \note Right now, will return DOM_NOT_SUPPORTED_ERR if ascii_only is false.
+ */
+dom_exception
+dom_string_tolower(dom_string *source, bool ascii_only, dom_string **lower)
+{
+ const uint8_t *orig_s = (const uint8_t *) dom_string_data(source);
+ const size_t nbytes = dom_string_byte_length(source);
+ uint8_t *copy_s;
+ size_t index = 0, clen;
+ parserutils_error err;
+ dom_exception exc;
+
+ if (ascii_only == false)
+ return DOM_NOT_SUPPORTED_ERR;
+
+ copy_s = malloc(nbytes);
+ if (copy_s == NULL)
+ return DOM_NO_MEM_ERR;
+ memcpy(copy_s, orig_s, nbytes);
+
+ while (index < nbytes) {
+ err = parserutils_charset_utf8_char_byte_length(orig_s + index,
+ &clen);
+ if (err != PARSERUTILS_OK) {
+ free(copy_s);
+ /** \todo Find a better exception */
+ return DOM_NO_MEM_ERR;
+ }
+
+ if (clen == 1) {
+ if (orig_s[index] >= 'A' &&
+ orig_s[index] <= 'Z')
+ copy_s[index] += 'a' - 'A';
+ }
+
+ index += clen;
+ }
+
+ if (((dom_string_internal*)source)->type == DOM_STRING_CDATA) {
+ exc = dom_string_create(copy_s, nbytes, lower);
+ } else {
+ exc = dom_string_create_interned(copy_s, nbytes, lower);
+ }
+
+ free(copy_s);
+
+ return exc;
+}
+
diff --git a/src/html/html_document.c b/src/html/html_document.c
index a2a7ed5..7644fde 100644
--- a/src/html/html_document.c
+++ b/src/html/html_document.c
@@ -116,15 +116,20 @@ out:
}
/* Finalise a HTMLDocument */
-void _dom_html_document_finalise(dom_html_document *doc)
+bool _dom_html_document_finalise(dom_html_document *doc)
{
int sidx;
- dom_string_unref(doc->cookie);
- dom_string_unref(doc->url);
- dom_string_unref(doc->domain);
- dom_string_unref(doc->referrer);
- dom_string_unref(doc->title);
+ if (doc->cookie != NULL)
+ dom_string_unref(doc->cookie);
+ if (doc->url != NULL)
+ dom_string_unref(doc->url);
+ if (doc->domain != NULL)
+ dom_string_unref(doc->domain);
+ if (doc->referrer != NULL)
+ dom_string_unref(doc->referrer);
+ if (doc->title != NULL)
+ dom_string_unref(doc->title);
if (doc->memoised != NULL) {
for(sidx = 0; sidx < hds_COUNT; ++sidx) {
@@ -136,7 +141,7 @@ void _dom_html_document_finalise(dom_html_document *doc)
doc->memoised = NULL;
}
- _dom_document_finalise(&doc->base);
+ return _dom_document_finalise(&doc->base);
}
/* Destroy a HTMLDocument */
@@ -144,9 +149,8 @@ void _dom_html_document_destroy(dom_node_internal *node)
{
dom_html_document *doc = (dom_html_document *) node;
- _dom_html_document_finalise(doc);
-
- free(doc);
+ if (_dom_html_document_finalise(doc) == true)
+ free(doc);
}
dom_exception _dom_html_document_copy(dom_node_internal *old,
@@ -163,58 +167,53 @@ dom_exception _dom_html_document_copy(dom_node_internal *old,
/** Internal method to support both kinds of create method */
static dom_exception
_dom_html_document_create_element_internal(dom_html_document *html,
- dom_string *tag_name,
+ dom_string *in_tag_name,
dom_string *namespace,
dom_string *prefix,
dom_html_element **result)
{
+ dom_exception exc;
+ dom_string *tag_name;
+
+ exc = dom_string_toupper(in_tag_name, true, &tag_name);
+ if (exc != DOM_NO_ERR)
+ return exc;
+
if (dom_string_caseless_isequal(tag_name, html->memoised[hds_HTML])) {
- return _dom_html_html_element_create(html, namespace, prefix,
+ exc = _dom_html_html_element_create(html, namespace, prefix,
(dom_html_html_element **) result);
- }
-
- if (dom_string_caseless_isequal(tag_name, html->memoised[hds_HEAD])) {
- return _dom_html_head_element_create(html, namespace, prefix,
+ } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_HEAD])) {
+ exc = _dom_html_head_element_create(html, namespace, prefix,
(dom_html_head_element **) result);
- }
-
- if (dom_string_caseless_isequal(tag_name, html->memoised[hds_TITLE])) {
- return _dom_html_title_element_create(html, namespace, prefix,
+ } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_TITLE])) {
+ exc = _dom_html_title_element_create(html, namespace, prefix,
(dom_html_title_element **) result);
- }
-
- if (dom_string_caseless_isequal(tag_name, html->memoised[hds_FORM])) {
- return _dom_html_form_element_create(html, namespace, prefix,
+ } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_FORM])) {
+ exc = _dom_html_form_element_create(html, namespace, prefix,
(dom_html_form_element **) result);
- }
-
- if (dom_string_caseless_isequal(tag_name, html->memoised[hds_LINK])) {
- return _dom_html_link_element_create(html, namespace, prefix,
+ } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_LINK])) {
+ exc = _dom_html_link_element_create(html, namespace, prefix,
(dom_html_link_element **) result);
- }
-
- if (dom_string_caseless_isequal(tag_name, html->memoised[hds_BUTTON])) {
- return _dom_html_button_element_create(html, namespace, prefix,
+ } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_BUTTON])) {
+ exc = _dom_html_button_element_create(html, namespace, prefix,
(dom_html_button_element **) result);
- }
-
- if (dom_string_caseless_isequal(tag_name, html->memoised[hds_INPUT])) {
- return _dom_html_input_element_create(html, namespace, prefix,
+ } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_INPUT])) {
+ exc = _dom_html_input_element_create(html, namespace, prefix,
(dom_html_input_element **) result);
- }
-
- if (dom_string_caseless_isequal(tag_name, html->memoised[hds_TEXTAREA])) {
- return _dom_html_text_area_element_create(html, namespace, prefix,
+ } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_TEXTAREA])) {
+ exc = _dom_html_text_area_element_create(html, namespace, prefix,
(dom_html_text_area_element **) result);
- }
-
- if (dom_string_caseless_isequal(tag_name, html->memoised[hds_OPTGROUP])) {
- return _dom_html_opt_group_element_create(html, namespace, prefix,
+ } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_OPTGROUP])) {
+ exc = _dom_html_opt_group_element_create(html, namespace, prefix,
(dom_html_opt_group_element **) result);
+ } else {
+ exc = _dom_html_element_create(html, tag_name, namespace,
+ prefix, result);
}
- return _dom_html_element_create(html, tag_name, namespace, prefix,
- result);
+ dom_string_unref(tag_name);
+
+ return exc;
}
dom_exception _dom_html_document_create_element(dom_document *doc,
diff --git a/src/html/html_document.h b/src/html/html_document.h
index fbe7155..bb1a0d2 100644
--- a/src/html/html_document.h
+++ b/src/html/html_document.h
@@ -38,7 +38,7 @@ dom_exception _dom_html_document_create(
dom_exception _dom_html_document_initialise(dom_html_document *doc,
dom_events_default_action_fetcher daf);
/* Finalise a HTMLDocument */
-void _dom_html_document_finalise(dom_html_document *doc);
+bool _dom_html_document_finalise(dom_html_document *doc);
void _dom_html_document_destroy(dom_node_internal *node);
dom_exception _dom_html_document_copy(dom_node_internal *old,
diff --git a/src/html/html_element.c b/src/html/html_element.c
index 21f3d1e..c2a4899 100644
--- a/src/html/html_element.c
+++ b/src/html/html_element.c
@@ -26,7 +26,7 @@ struct dom_html_element_vtable _dom_html_element_vtable = {
},
DOM_NODE_VTABLE_ELEMENT,
},
- DOM_ELEMENT_VTABLE
+ DOM_ELEMENT_VTABLE_HTML_ELEMENT,
},
DOM_HTML_ELEMENT_VTABLE
};
@@ -142,6 +142,71 @@ SIMPLE_GET_SET(lang,lang)
SIMPLE_GET_SET(dir,dir)
SIMPLE_GET_SET(class_name,class)
+/**
+ * Retrieve a list of descendant elements of an element which match a given
+ * tag name (caselessly)
+ *
+ * \param element The root of the subtree to search
+ * \param name The tag name to match (or "*" for all tags)
+ * \param result Pointer to location to receive result
+ * \return DOM_NO_ERR.
+ *
+ * The returned nodelist will have its reference count increased. It is
+ * the responsibility of the caller to unref the nodelist once it has
+ * finished with it.
+ */
+dom_exception _dom_html_element_get_elements_by_tag_name(
+ struct dom_element *element, dom_string *name,
+ struct dom_nodelist **result)
+{
+ dom_exception err;
+ dom_node_internal *base = (dom_node_internal *) element;
+
+ assert(base->owner != NULL);
+
+ err = _dom_document_get_nodelist(base->owner,
+ DOM_NODELIST_BY_NAME_CASELESS,
+ (struct dom_node_internal *) element, name, NULL,
+ NULL, result);
+
+ return err;
+}
+
+/**
+ * Retrieve a list of descendant elements of an element which match a given
+ * namespace/localname pair, caselessly.
+ *
+ * \param element The root of the subtree to search
+ * \param namespace The namespace URI to match (or "*" for all)
+ * \param localname The local name to match (or "*" for all)
+ * \param result Pointer to location to receive result
+ * \return DOM_NO_ERR on success,
+ * DOM_NOT_SUPPORTED_ERR if the implementation does not support
+ * the feature "XML" and the language exposed
+ * through the Document does not support
+ * Namespaces.
+ *
+ * The returned nodelist will have its reference count increased. It is
+ * the responsibility of the caller to unref the nodelist once it has
+ * finished with it.
+ */
+dom_exception _dom_html_element_get_elements_by_tag_name_ns(
+ struct dom_element *element, dom_string *namespace,
+ dom_string *localname, struct dom_nodelist **result)
+{
+ dom_exception err;
+
+ /** \todo ensure XML feature is supported */
+
+ err = _dom_document_get_nodelist(element->base.owner,
+ DOM_NODELIST_BY_NAMESPACE_CASELESS,
+ (struct dom_node_internal *) element, NULL,
+ namespace, localname,
+ result);
+
+ return err;
+}
+
/*-----------------------------------------------------------------------*/
/* Common functions */
diff --git a/src/html/html_element.h b/src/html/html_element.h
index ebf47ba..2ac4b17 100644
--- a/src/html/html_element.h
+++ b/src/html/html_element.h
@@ -33,11 +33,45 @@ dom_exception _dom_html_element_initialise(struct dom_html_document *doc,
void _dom_html_element_finalise(struct dom_html_element *ele);
+/* Virtual functions */
+dom_exception _dom_html_element_get_elements_by_tag_name(
+ struct dom_element *element, dom_string *name,
+ struct dom_nodelist **result);
+
+dom_exception _dom_html_element_get_elements_by_tag_name_ns(
+ struct dom_element *element, dom_string *namespace,
+ dom_string *localname, struct dom_nodelist **result);
+
+
/* The protected virtual functions */
void _dom_html_element_destroy(dom_node_internal *node);
dom_exception _dom_html_element_copy(dom_node_internal *old,
dom_node_internal **copy);
+#define DOM_ELEMENT_VTABLE_HTML_ELEMENT \
+ _dom_element_get_tag_name, \
+ _dom_element_get_attribute, \
+ _dom_element_set_attribute, \
+ _dom_element_remove_attribute, \
+ _dom_element_get_attribute_node, \
+ _dom_element_set_attribute_node, \
+ _dom_element_remove_attribute_node, \
+ _dom_html_element_get_elements_by_tag_name, \
+ _dom_element_get_attribute_ns, \
+ _dom_element_set_attribute_ns, \
+ _dom_element_remove_attribute_ns, \
+ _dom_element_get_attribute_node_ns, \
+ _dom_element_set_attribute_node_ns, \
+ _dom_html_element_get_elements_by_tag_name_ns, \
+ _dom_element_has_attribute, \
+ _dom_element_has_attribute_ns, \
+ _dom_element_get_schema_type_info, \
+ _dom_element_set_id_attribute, \
+ _dom_element_set_id_attribute_ns, \
+ _dom_element_set_id_attribute_node, \
+ _dom_element_get_classes, \
+ _dom_element_has_class
+
#define DOM_HTML_ELEMENT_PROTECT_VTABLE \
_dom_html_element_destroy, \
_dom_html_element_copy