summaryrefslogtreecommitdiff
path: root/src/core/attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/attr.c')
-rw-r--r--src/core/attr.c342
1 files changed, 270 insertions, 72 deletions
diff --git a/src/core/attr.c b/src/core/attr.c
index 9fbb06f..df95482 100644
--- a/src/core/attr.c
+++ b/src/core/attr.c
@@ -3,10 +3,12 @@
* Licensed under the MIT License,
* http://www.opensource.org/licenses/mit-license.php
* Copyright 2007 John-Mark Bell <jmb@netsurf-browser.org>
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
*/
#include <stddef.h>
#include <string.h>
+#include <assert.h>
#include <dom/core/attr.h>
#include <dom/core/document.h>
@@ -25,24 +27,34 @@ struct dom_element;
* DOM node attribute
*/
struct dom_attr {
- struct dom_node_internal base; /**< Base node */
+ struct dom_node_internal base; /**< Base node */
- bool specified; /**< Whether attribute was specified
- * or defaulted */
+ bool specified; /**< Whether the attribute is specified
+ * or default */
struct dom_type_info *schema_type_info; /**< Type information */
- bool is_id; /**< Attribute is of type ID */
+ bool is_id; /**< Whether this attribute is a ID attribute */
};
-/* The vtable for dom attr node */
+/* The vtable for dom_attr node */
static struct dom_attr_vtable attr_vtable = {
{
- DOM_NODE_VTABLE
+ DOM_NODE_VTABLE_ATTR
},
DOM_ATTR_VTABLE
};
+/* The protected vtable for dom_attr */
+static struct dom_node_protect_vtable attr_protect_vtable = {
+ DOM_ATTR_PROTECT_VTABLE
+};
+
+
+/* -------------------------------------------------------------------- */
+
+/* Constructor and destructor */
+
/**
* Create an attribute node
*
@@ -50,43 +62,69 @@ static struct dom_attr_vtable attr_vtable = {
* \param name The (local) name of the node to create
* \param namespace The namespace URI of the attribute, or NULL
* \param prefix The namespace prefix of the attribute, or NULL
+ * \param specified Whtether this attribute is specified
* \param result Pointer to location to receive created attribute
* \return DOM_NO_ERR on success,
- * DOM_INVALID_CHARACTER_ERR if ::name is invalid,
* DOM_NO_MEM_ERR on memory exhaustion.
*
- * ::doc and ::name will have their reference counts increased.
+ * ::doc and ::name will have their reference counts increased. The
+ * caller should make sure that ::name is a valid NCName here.
*
* The returned attribute will already be referenced.
*/
-dom_exception dom_attr_create(struct dom_document *doc,
- struct dom_string *name, struct dom_string *namespace,
- struct dom_string *prefix, struct dom_attr **result)
+dom_exception _dom_attr_create(struct dom_document *doc,
+ struct lwc_string_s *name, struct lwc_string_s *namespace,
+ struct lwc_string_s *prefix, bool specified,
+ struct dom_attr **result)
{
struct dom_attr *a;
dom_exception err;
- /** \todo Sanity check the attribute name */
-
- /* Allocate the element */
- a = dom_document_alloc(doc, NULL, sizeof(struct dom_attr));
+ /* Allocate the attribute node */
+ a = _dom_document_alloc(doc, NULL, sizeof(struct dom_attr));
if (a == NULL)
return DOM_NO_MEM_ERR;
/* Initialise the vtable */
a->base.base.vtable = &attr_vtable;
- a->base.destroy = _dom_attr_destroy;
+ a->base.vtable = &attr_protect_vtable;
+
+ /* Initialise the class */
+ err = _dom_attr_initialise(a, doc, name, namespace, prefix, specified,
+ result);
+ if (err != DOM_NO_ERR) {
+ _dom_document_alloc(doc, a, 0);
+ return err;
+ }
+ return DOM_NO_ERR;
+}
+
+/**
+ * Initialise a dom_attr
+ *
+ * \param a The dom_attr
+ * \param doc The document
+ * \param name The name of this attribute node
+ * \param namespace The namespace of this attribute
+ * \param prefix The prefix
+ * \param specified Whether this node is a specified one
+ * \param result The returned node
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
+ */
+dom_exception _dom_attr_initialise(dom_attr *a,
+ struct dom_document *doc, struct lwc_string_s *name,
+ struct lwc_string_s *namespace, struct lwc_string_s *prefix,
+ bool specified, struct dom_attr **result)
+{
+ dom_exception err;
- /* Initialise the base class */
- err = dom_node_initialise(&a->base, doc, DOM_ATTRIBUTE_NODE,
+ err = _dom_node_initialise(&a->base, doc, DOM_ATTRIBUTE_NODE,
name, NULL, namespace, prefix);
if (err != DOM_NO_ERR) {
- dom_document_alloc(doc, a, 0);
return err;
}
- /* Perform our type-specific initialisation */
- a->specified = false;
+ a->specified = specified;
a->schema_type_info = NULL;
a->is_id = false;
@@ -96,61 +134,48 @@ dom_exception dom_attr_create(struct dom_document *doc,
}
/**
- * Destroy an attribute node
+ * The destructor of dom_attr
*
- * \param doc The owning document
- * \param attr The attribute to destroy
- *
- * The contents of ::attr will be destroyed and ::attr will be freed
+ * \param doc The owner document
+ * \param attr The attribute
*/
-void dom_attr_destroy(struct dom_document *doc, struct dom_attr *attr)
+void _dom_attr_finalise(dom_document *doc, dom_attr *attr)
{
- struct dom_node_internal *c, *d;
-
- /* Destroy children of this node */
- for (c = attr->base.first_child; c != NULL; c = d) {
- d = c->next;
-
- /* Detach child */
- c->parent = NULL;
-
- if (c->refcnt > 0) {
- /* Something is using this child */
-
- /** \todo add to list of nodes pending deletion */
-
- continue;
- }
-
- /* Detach from sibling list */
- c->previous = NULL;
- c->next = NULL;
-
- dom_node_destroy(c);
- }
-
/* Now, clean up this node and destroy it */
if (attr->schema_type_info != NULL) {
/** \todo destroy schema type info */
}
- dom_node_finalise(doc, &attr->base);
-
- dom_document_alloc(doc, attr, 0);
+ _dom_node_finalise(doc, &attr->base);
}
-void _dom_attr_destroy(dom_node_internal *node)
+/**
+ * Destroy an attribute node
+ *
+ * \param doc The owning document
+ * \param attr The attribute to destroy
+ *
+ * The contents of ::attr will be destroyed and ::attr will be freed
+ */
+void _dom_attr_destroy(struct dom_document *doc, struct dom_attr *attr)
{
- UNUSED(node);
+ _dom_attr_finalise(doc, attr);
+
+ _dom_document_alloc(doc, attr, 0);
}
+
+/* -------------------------------------------------------------------- */
+
+/* The public virtual functions */
+
/**
* Retrieve an attribute's name
*
* \param attr Attribute to retrieve name from
* \param result Pointer to location to receive result
- * \return DOM_NO_ERR.
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure
*
* The returned string will have its reference count increased. It is
* the responsibility of the caller to unref the string once it has
@@ -164,7 +189,7 @@ dom_exception _dom_attr_get_name(struct dom_attr *attr,
}
/**
- * Determine if attribute was specified or defaulted
+ * Determine if attribute was specified or default
*
* \param attr Attribute to inspect
* \param result Pointer to location to receive result
@@ -182,7 +207,7 @@ dom_exception _dom_attr_get_specified(struct dom_attr *attr, bool *result)
*
* \param attr Attribute to retrieve value from
* \param result Pointer to location to receive result
- * \return DOM_NO_ERR.
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure
*
* The returned string will have its reference count increased. It is
* the responsibility of the caller to unref the string once it has
@@ -196,8 +221,8 @@ dom_exception _dom_attr_get_value(struct dom_attr *attr,
struct dom_string *value, *temp;
dom_exception err;
- err = dom_document_create_string(a->owner,
- (const uint8_t *) "", SLEN(""), &value);
+ err = _dom_document_create_string(a->owner,
+ NULL, 0, &value);
if (err != DOM_NO_ERR) {
return err;
}
@@ -221,7 +246,7 @@ dom_exception _dom_attr_get_value(struct dom_attr *attr,
struct dom_string *tr;
/* Get textual representation of entity */
- err = dom_entity_reference_get_textual_representation(
+ err = _dom_entity_reference_get_textual_representation(
(struct dom_entity_reference *) c,
&tr);
if (err != DOM_NO_ERR) {
@@ -285,24 +310,21 @@ dom_exception _dom_attr_set_value(struct dom_attr *attr,
/* Detach child */
c->parent = NULL;
- if (c->refcnt > 0) {
- /* Something is using this child */
-
- /** \todo add to list of nodes pending deletion */
-
- continue;
- }
-
/* Detach from sibling list */
c->previous = NULL;
c->next = NULL;
- dom_node_destroy(c);
+ dom_node_try_destroy(c);
}
/* And insert the text node as the value */
((struct dom_node_internal *) text)->parent = a;
a->first_child = a->last_child = (struct dom_node_internal *) text;
+ dom_node_unref(text);
+ dom_node_remove_pending(text);
+
+ /* Now the attribute node is specified */
+ attr->specified = true;
return DOM_NO_ERR;
}
@@ -336,7 +358,7 @@ dom_exception _dom_attr_get_owner(struct dom_attr *attr,
*
* \param attr The attribute to extract type information from
* \param result Pointer to location to receive result
- * \return DOM_NO_ERR.
+ * \return DOM_NOT_SUPPORTED_ERR, we don't support this API now.
*
* The returned type info will have its reference count increased. The caller
* should unref it once it has finished with it.
@@ -363,3 +385,179 @@ dom_exception _dom_attr_is_id(struct dom_attr *attr, bool *result)
return DOM_NO_ERR;
}
+
+/*------------- The overload virtual functions ------------------------*/
+
+/* Overload function of Node, please refer node.c for the detail of this
+ * function. */
+dom_exception _dom_attr_get_node_value(dom_node_internal *node,
+ struct dom_string **result)
+{
+ dom_attr *attr = (dom_attr *) node;
+
+ return _dom_attr_get_value(attr, result);
+}
+
+/* Overload function of Node, please refer node.c for the detail of this
+ * function. */
+dom_exception _dom_attr_clone_node(dom_node_internal *node, bool deep,
+ dom_node_internal **result)
+{
+ dom_exception err;
+ dom_attr *attr;
+
+ /* Discard the warnings */
+ UNUSED(deep);
+
+ /* Clone an Attr always clone all its children */
+ err = _dom_node_clone_node(node, true, result);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ attr = (dom_attr *) *result;
+ /* Clone an Attr always result a specified Attr,
+ * see DOM Level 3 Node.cloneNode */
+ attr->specified = true;
+
+ return DOM_NO_ERR;
+}
+
+/* Overload function of Node, please refer node.c for the detail of this
+ * function. */
+dom_exception _dom_attr_set_prefix(dom_node_internal *node,
+ struct dom_string *prefix)
+{
+ /* Really I don't know whether there should something
+ * special to do here */
+ return _dom_node_set_prefix(node, prefix);
+}
+
+/* Overload function of Node, please refer node.c for the detail of this
+ * function. */
+dom_exception _dom_attr_lookup_prefix(dom_node_internal *node,
+ struct dom_string *namespace, struct dom_string **result)
+{
+ struct dom_element *owner;
+ dom_exception err;
+
+ err = dom_attr_get_owner_element(node, &owner);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ if (owner == NULL) {
+ *result = NULL;
+ return DOM_NO_ERR;
+ }
+
+ return dom_node_lookup_prefix(owner, namespace, result);
+}
+
+/* Overload function of Node, please refer node.c for the detail of this
+ * function. */
+dom_exception _dom_attr_is_default_namespace(dom_node_internal *node,
+ struct dom_string *namespace, bool *result)
+{
+ struct dom_element *owner;
+ dom_exception err;
+
+ err = dom_attr_get_owner_element(node, &owner);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ if (owner == NULL) {
+ *result = false;
+ return DOM_NO_ERR;
+ }
+
+ return dom_node_is_default_namespace(owner, namespace, result);
+}
+
+/* Overload function of Node, please refer node.c for the detail of this
+ * function. */
+dom_exception _dom_attr_lookup_namespace(dom_node_internal *node,
+ struct dom_string *prefix, struct dom_string **result)
+{
+ struct dom_element *owner;
+ dom_exception err;
+
+ err = dom_attr_get_owner_element(node, &owner);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ if (owner == NULL) {
+ *result = NULL;
+ return DOM_NO_ERR;
+ }
+
+ return dom_node_lookup_namespace(owner, prefix, result);
+}
+
+
+/*----------------------------------------------------------------------*/
+
+/* The protected virtual functions */
+
+/* The virtual destroy function of this class */
+void __dom_attr_destroy(dom_node_internal *node)
+{
+ dom_document *doc = node->owner;
+
+ assert(doc != NULL);
+ _dom_attr_destroy(doc, (dom_attr *) node);
+}
+
+/* The memory allocator of this class */
+dom_exception _dom_attr_alloc(struct dom_document *doc,
+ struct dom_node_internal *n, struct dom_node_internal **ret)
+{
+ UNUSED(n);
+ dom_attr *a;
+
+ a = _dom_document_alloc(doc, NULL, sizeof(struct dom_attr));
+ if (a == NULL)
+ return DOM_NO_MEM_ERR;
+
+ *ret = (dom_node_internal *) a;
+ dom_node_set_owner(*ret, doc);
+
+ return DOM_NO_ERR;
+}
+
+/* The copy constructor of this class */
+dom_exception _dom_attr_copy(struct dom_node_internal *new,
+ struct dom_node_internal *old)
+{
+ dom_attr *na = (dom_attr *) new;
+ dom_attr *oa = (dom_attr *) old;
+
+ na->specified = oa->specified;
+ na->is_id = oa->is_id;
+
+ /* TODO: deal with dom_type_info, it get no definition ! */
+
+ return _dom_node_copy(new, old);
+}
+
+
+/**
+ * Set/Unset whether this attribute is a ID attribute
+ *
+ * \param attr The attribute
+ * \param is_id Whether it is a ID attribute
+ */
+void _dom_attr_set_isid(struct dom_attr *attr, bool is_id)
+{
+ attr->is_id = is_id;
+}
+
+/**
+ * Set/Unset whether the attribute is a specified one.
+ *
+ * \param attr The attribute node
+ * \param specified Whether this attribute is a specified one
+ */
+void _dom_attr_set_specified(struct dom_attr *attr, bool specified)
+{
+ attr->specified = specified;
+}
+