diff options
Diffstat (limited to 'src/core/attr.c')
-rw-r--r-- | src/core/attr.c | 266 |
1 files changed, 263 insertions, 3 deletions
diff --git a/src/core/attr.c b/src/core/attr.c index f1c4f54..4cd9e76 100644 --- a/src/core/attr.c +++ b/src/core/attr.c @@ -19,12 +19,13 @@ #include "core/document.h" #include "core/entity_ref.h" #include "core/node.h" +#include "core/element.h" #include "utils/utils.h" struct dom_element; /** - * DOM node attribute + * DOM attribute node */ struct dom_attr { struct dom_node_internal base; /**< Base node */ @@ -35,6 +36,16 @@ struct dom_attr { struct dom_type_info *schema_type_info; /**< Type information */ bool is_id; /**< Whether this attribute is a ID attribute */ + + dom_attr_type type; /**< The type of this attribute */ + + union { + unsigned long lvalue; + unsigned short svalue; + bool bvalue; + } value; /**< The special type value of this attribute */ + + bool read_only; /**< Whether this attribute is readonly */ }; /* The vtable for dom_attr node */ @@ -62,7 +73,7 @@ static struct dom_node_protect_vtable attr_protect_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 specified Whether this attribute is specified * \param result Pointer to location to receive created attribute * \return DOM_NO_ERR on success, * DOM_NO_MEM_ERR on memory exhaustion. @@ -127,6 +138,9 @@ dom_exception _dom_attr_initialise(dom_attr *a, a->specified = specified; a->schema_type_info = NULL; a->is_id = false; + /* The attribute type is unset when it is created */ + a->type = DOM_ATTR_UNSET; + a->read_only = false; *result = a; @@ -165,6 +179,206 @@ void _dom_attr_destroy(struct dom_document *doc, struct dom_attr *attr) _dom_document_alloc(doc, attr, 0); } +/*-----------------------------------------------------------------------*/ +/* Following are our implementation specific APIs */ + +/** + * Get the Attr Node type + * + * \param a The attribute node + * \return the type + */ +dom_attr_type dom_attr_get_type(dom_attr *a) +{ + return a->type; +} + +/** + * Get the integer value of this attribute + * + * \param a The attribute object + * \param value The returned value + * \return DOM_NO_ERR on success, + * DOM_ATTR_WRONG_TYPE_ERR if the attribute node is not a integer + * attribute + */ +dom_exception dom_attr_get_integer(dom_attr *a, unsigned long *value) +{ + if (a->type != DOM_ATTR_INTEGER) + return DOM_ATTR_WRONG_TYPE_ERR; + + *value = a->value.lvalue; + + return DOM_NO_ERR; +} + +/** + * Set the integer value of this attribute + * + * \param a The attribute object + * \param value The new value + * \return DOM_NO_ERR on success, + * DOM_ATTR_WRONG_TYPE_ERR if the attribute node is not a integer + * attribute + */ +dom_exception dom_attr_set_integer(dom_attr *a, unsigned long value) +{ + /* If this is the first set method, we should fix this attribute + * type */ + if (a->type == DOM_ATTR_UNSET) + a->type = DOM_ATTR_INTEGER; + + if (a->type != DOM_ATTR_INTEGER) + return DOM_ATTR_WRONG_TYPE_ERR; + + if (a->value.lvalue == value) + return DOM_NO_ERR; + + a->value.lvalue = value; + + struct dom_document *doc = dom_node_get_owner(a); + struct dom_node_internal *ele = dom_node_get_parent(a); + bool success = true; + dom_exception err; + err = _dom_dispatch_attr_modified_event(doc, ele, NULL, NULL, + (dom_event_target *) a, NULL, + DOM_MUTATION_MODIFICATION, &success); + if (err != DOM_NO_ERR) + return err; + + success = true; + err = _dom_dispatch_subtree_modified_event(doc, + (dom_event_target *) a, &success); + return err; +} + +/** + * Get the short value of this attribute + * + * \param a The attribute object + * \param value The returned value + * \return DOM_NO_ERR on success, + * DOM_ATTR_WRONG_TYPE_ERR if the attribute node is not a short + * attribute + */ +dom_exception dom_attr_get_short(dom_attr *a, unsigned short *value) +{ + if (a->type != DOM_ATTR_SHORT) + return DOM_ATTR_WRONG_TYPE_ERR; + + *value = a->value.svalue; + + return DOM_NO_ERR; +} + +/** + * Set the short value of this attribute + * + * \param a The attribute object + * \param value The new value + * \return DOM_NO_ERR on success, + * DOM_ATTR_WRONG_TYPE_ERR if the attribute node is not a short + * attribute + */ +dom_exception dom_attr_set_short(dom_attr *a, unsigned short value) +{ + /* If this is the first set method, we should fix this attribute + * type */ + if (a->type == DOM_ATTR_UNSET) + a->type = DOM_ATTR_SHORT; + + if (a->type != DOM_ATTR_SHORT) + return DOM_ATTR_WRONG_TYPE_ERR; + + if (a->value.svalue == value) + return DOM_NO_ERR; + + a->value.svalue = value; + + struct dom_document *doc = dom_node_get_owner(a); + struct dom_node_internal *ele = dom_node_get_parent(a); + bool success = true; + dom_exception err; + err = _dom_dispatch_attr_modified_event(doc, ele, NULL, NULL, + (dom_event_target *) a, NULL, + DOM_MUTATION_MODIFICATION, &success); + if (err != DOM_NO_ERR) + return err; + + success = true; + err = _dom_dispatch_subtree_modified_event(doc, + (dom_event_target *) a, &success); + return err; +} + +/** + * Get the bool value of this attribute + * + * \param a The attribute object + * \param value The returned value + * \return DOM_NO_ERR on success, + * DOM_ATTR_WRONG_TYPE_ERR if the attribute node is not a bool + * attribute + */ +dom_exception dom_attr_get_bool(dom_attr *a, bool *value) +{ + if (a->type != DOM_ATTR_BOOL) + return DOM_ATTR_WRONG_TYPE_ERR; + + *value = a->value.bvalue; + + return DOM_NO_ERR; +} + +/** + * Set the bool value of this attribute + * + * \param a The attribute object + * \param value The new value + * \return DOM_NO_ERR on success, + * DOM_ATTR_WRONG_TYPE_ERR if the attribute node is not a bool + * attribute + */ +dom_exception dom_attr_set_bool(dom_attr *a, bool value) +{ + /* If this is the first set method, we should fix this attribute + * type */ + if (a->type == DOM_ATTR_UNSET) + a->type = DOM_ATTR_BOOL; + + if (a->type != DOM_ATTR_BOOL) + return DOM_ATTR_WRONG_TYPE_ERR; + + if (a->value.bvalue == value) + return DOM_NO_ERR; + + a->value.bvalue = value; + + struct dom_document *doc = dom_node_get_owner(a); + struct dom_node_internal *ele = dom_node_get_parent(a); + bool success = true; + dom_exception err; + err = _dom_dispatch_attr_modified_event(doc, ele, NULL, NULL, + (dom_event_target *) a, NULL, + DOM_MUTATION_MODIFICATION, &success); + if (err != DOM_NO_ERR) + return err; + + success = true; + err = _dom_dispatch_subtree_modified_event(doc, + (dom_event_target *) a, &success); + return err; +} + +/** + * Set the node as a readonly attribute + * + * \param a The attribute + */ +void dom_attr_mark_readonly(dom_attr *a) +{ + a->read_only = true; +} /* -------------------------------------------------------------------- */ @@ -227,6 +441,18 @@ dom_exception _dom_attr_get_value(struct dom_attr *attr, return err; } + /* Force unknown types to strings, if necessary */ + if (attr->type == DOM_ATTR_UNSET && a->first_child != NULL) { + attr->type = DOM_ATTR_STRING; + } + + /* If this attribute node is not a string one, we just return an empty + * string */ + if (attr->type != DOM_ATTR_STRING) { + *result = value; + return DOM_NO_ERR; + } + /* Traverse children, building a string representation as we go */ for (c = a->first_child; c != NULL; c = c->next) { if (c->type == DOM_TEXT_NODE && c->value != NULL) { @@ -298,10 +524,33 @@ dom_exception _dom_attr_set_value(struct dom_attr *attr, if (_dom_node_readonly(a)) return DOM_NO_MODIFICATION_ALLOWED_ERR; + /* If this is the first set method, we should fix this attribute + * type */ + if (attr->type == DOM_ATTR_UNSET) + attr->type = DOM_ATTR_STRING; + + if (attr->type != DOM_ATTR_STRING) + return DOM_ATTR_WRONG_TYPE_ERR; + + dom_string *name = NULL; + + err = _dom_attr_get_name(attr, &name); + if (err != DOM_NO_ERR) + return err; + + dom_string *parsed = NULL; + err = dom_element_parse_attribute(a->parent, name, value, &parsed); + if (err != DOM_NO_ERR) { + dom_string_unref(name); + return err; + } + /* Create text node containing new value */ - err = dom_document_create_text_node(a->owner, value, &text); + err = dom_document_create_text_node(a->owner, parsed, &text); if (err != DOM_NO_ERR) return err; + + dom_string_unref(parsed); /* Destroy children of this node */ for (c = a->first_child; c != NULL; c = d) { @@ -561,3 +810,14 @@ void _dom_attr_set_specified(struct dom_attr *attr, bool specified) attr->specified = specified; } +/** + * Whether this attribute node is readonly + * + * \param a The node + * \return true if this Attr is readonly, false otherwise + */ +bool _dom_attr_readonly(const dom_attr *a) +{ + return a->read_only; +} + |