/* * This file is part of libdom. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell * Copyright 2009 Bo Yang */ #include #include #include #include #include #include "core/document.h" #include "core/element.h" #include "core/namednodemap.h" #include "core/node.h" #include "utils/utils.h" /** * DOM named node map */ struct dom_namednodemap { dom_document *owner; /**< Owning document */ void *priv; /**< Private data */ struct nnm_operation *opt; /**< The underlaid operation * implementations */ uint32_t refcnt; /**< Reference count */ }; /** * Create a namednodemap * * \param doc The owning document * \param priv The private data of this dom_namednodemap * \param opt The operation function pointer * \param map Pointer to location to receive created map * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion * * ::head must be a node owned by ::doc and must be either an Element or * DocumentType node. * * If ::head is of type Element, ::type must be DOM_ATTRIBUTE_NODE * If ::head is of type DocumentType, ::type may be either * DOM_ENTITY_NODE or DOM_NOTATION_NODE. * * The returned map will already be referenced, so the client need not * explicitly reference it. The client must unref the map once it is * finished with it. */ dom_exception _dom_namednodemap_create(dom_document *doc, void *priv, struct nnm_operation *opt, dom_namednodemap **map) { dom_namednodemap *m; m = malloc(sizeof(dom_namednodemap)); if (m == NULL) return DOM_NO_MEM_ERR; m->owner = doc; m->priv = priv; m->opt = opt; m->refcnt = 1; *map = m; return DOM_NO_ERR; } /** * Claim a reference on a DOM named node map * * \param map The map to claim a reference on */ void dom_namednodemap_ref(dom_namednodemap *map) { assert(map != NULL); map->refcnt++; } /** * Release a reference on a DOM named node map * * \param map The map to release the reference from * * If the reference count reaches zero, any memory claimed by the * map will be released */ void dom_namednodemap_unref(dom_namednodemap *map) { if (map == NULL) return; if (--map->refcnt == 0) { /* Call the implementation specific destroy */ map->opt->namednodemap_destroy(map->priv); /* Destroy the map object */ free(map); } } /** * Retrieve the length of a named node map * * \param map Map to retrieve length of * \param length Pointer to location to receive length * \return DOM_NO_ERR. */ dom_exception dom_namednodemap_get_length(dom_namednodemap *map, unsigned long *length) { assert(map->opt != NULL); return map->opt->namednodemap_get_length(map->priv, length); } /** * Retrieve an item by name from a named node map * * \param map The map to retrieve the item from * \param name The name of the item to retrieve * \param node Pointer to location to receive item * \return DOM_NO_ERR. * * The returned node will have had its reference count increased. The client * should unref the node once it has finished with it. */ dom_exception _dom_namednodemap_get_named_item(dom_namednodemap *map, dom_string *name, dom_node **node) { assert(map->opt != NULL); return map->opt->namednodemap_get_named_item(map->priv, name, node); } /** * Add a node to a named node map, replacing any matching existing node * * \param map The map to add to * \param arg The node to add * \param node Pointer to location to receive replaced node * \return DOM_NO_ERR on success, * DOM_WRONG_DOCUMENT_ERR if ::arg was created from a * different document than ::map, * DOM_NO_MODIFICATION_ALLOWED_ERR if ::map is readonly, * DOM_INUSE_ATTRIBUTE_ERR if ::arg is an Attr that is * already an attribute on another * Element, * DOM_HIERARCHY_REQUEST_ERR if the type of ::arg is not * permitted as a member of ::map. * * ::arg's nodeName attribute will be used to store it in ::map. It will * be accessible using the nodeName attribute as the key for lookup. * * Replacing a node by itself has no effect. * * The returned node will have had its reference count increased. The client * should unref the node once it has finished with it. */ dom_exception _dom_namednodemap_set_named_item(dom_namednodemap *map, dom_node *arg, dom_node **node) { assert(map->opt != NULL); return map->opt->namednodemap_set_named_item(map->priv, arg, node); } /** * Remove an item by name from a named node map * * \param map The map to remove from * \param name The name of the item to remove * \param node Pointer to location to receive removed item * \return DOM_NO_ERR on success, * DOM_NOT_FOUND_ERR if there is no node named ::name * in ::map, * DOM_NO_MODIFICATION_ALLOWED_ERR if ::map is readonly. * * The returned node will have had its reference count increased. The client * should unref the node once it has finished with it. */ dom_exception _dom_namednodemap_remove_named_item( dom_namednodemap *map, dom_string *name, dom_node **node) { assert(map->opt != NULL); return map->opt->namednodemap_remove_named_item(map->priv, name, node); } /** * Retrieve an item from a named node map * * \param map The map to retrieve the item from * \param index The map index to retrieve * \param node Pointer to location to receive item * \return DOM_NO_ERR. * * ::index is a zero-based index into ::map. * ::index lies in the range [0, length-1] * * The returned node will have had its reference count increased. The client * should unref the node once it has finished with it. */ dom_exception _dom_namednodemap_item(dom_namednodemap *map, unsigned long index, dom_node **node) { assert(map->opt != NULL); return map->opt->namednodemap_item(map->priv, index, node); } /** * Retrieve an item by namespace/localname from a named node map * * \param map The map to retrieve the item from * \param namespace The namespace URI of the item to retrieve * \param localname The local name of the node to retrieve * \param node Pointer to location to receive item * \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 node will have had its reference count increased. The client * should unref the node once it has finished with it. */ dom_exception _dom_namednodemap_get_named_item_ns( dom_namednodemap *map, dom_string *namespace, dom_string *localname, dom_node **node) { assert(map->opt != NULL); return map->opt->namednodemap_get_named_item_ns(map->priv, namespace, localname, node); } /** * Add a node to a named node map, replacing any matching existing node * * \param map The map to add to * \param arg The node to add * \param node Pointer to location to receive replaced node * \return DOM_NO_ERR on success, * DOM_WRONG_DOCUMENT_ERR if ::arg was created from a * different document than ::map, * DOM_NO_MODIFICATION_ALLOWED_ERR if ::map is readonly, * DOM_INUSE_ATTRIBUTE_ERR if ::arg is an Attr that is * already an attribute on another * Element, * DOM_HIERARCHY_REQUEST_ERR if the type of ::arg is not * permitted as a member of ::map. * DOM_NOT_SUPPORTED_ERR if the implementation does not support the * feature "XML" and the language exposed * through the Document does not support * Namespaces. * * ::arg's namespaceURI and localName attributes will be used to store it in * ::map. It will be accessible using the namespaceURI and localName * attributes as the keys for lookup. * * Replacing a node by itself has no effect. * * The returned node will have had its reference count increased. The client * should unref the node once it has finished with it. */ dom_exception _dom_namednodemap_set_named_item_ns( dom_namednodemap *map, dom_node *arg, dom_node **node) { assert(map->opt != NULL); return map->opt->namednodemap_set_named_item_ns(map->priv, arg, node); } /** * Remove an item by namespace/localname from a named node map * * \param map The map to remove from * \param namespace The namespace URI of the item to remove * \param localname The local name of the item to remove * \param node Pointer to location to receive removed item * \return DOM_NO_ERR on success, * DOM_NOT_FOUND_ERR if there is no node named ::name * in ::map, * DOM_NO_MODIFICATION_ALLOWED_ERR if ::map is readonly. * 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 node will have had its reference count increased. The client * should unref the node once it has finished with it. */ dom_exception _dom_namednodemap_remove_named_item_ns( dom_namednodemap *map, dom_string *namespace, dom_string *localname, dom_node **node) { assert(map->opt != NULL); return map->opt->namednodemap_remove_named_item_ns(map->priv, namespace, localname, node); } /** * Compare whether two NamedNodeMap are equal. * */ bool _dom_namednodemap_equal(dom_namednodemap *m1, dom_namednodemap *m2) { assert(m1->opt != NULL); return (m1->opt == m2->opt && m1->opt->namednodemap_equal(m1->priv, m2->priv)); } /** * Update the dom_namednodemap to make it as a proxy of another object * * \param map The dom_namednodemap * \param priv The private data to change to */ void _dom_namednodemap_update(dom_namednodemap *map, void *priv) { map->priv = priv; }