/* * Copyright (c) 2004, Stefan Walter * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * * The names of contributors to this software may not be * used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * * CONTRIBUTORS * Stef Walter * */ // TODO: UPDATE these comments once done // DOMC C++ WRAPPER // // Everything is in the DOM namespace. // #ifndef __DOMCXX_H__ #define __DOMCXX_H__ #include #include #include namespace DOM { extern "C" { #define this _this #include "dom.h" #undef this } #ifdef ASSERT #define DOM_ASSERT ASSERT #else #include #define ASSERT assert #endif typedef std::basic_string data_str; typedef std::basic_string dom_str; #define ASSERT_VALID() \ ASSERT(isValid()); #define ASSERT_VALID_NODE(node) \ ASSERT(node.isValid()); #define ASSERT_TYPE(t) \ ASSERT(getNodeType() == t) #define ASSERT_NODE_TYPE(n, t) \ ASSERT(n.getNodeType() == t) #define RESET_ERR() \ DOM_Exception = 0; #define CHECK_ERR() \ if(DOM_Exception != 0) throw DOMException(DOM_Exception); #define NO_REFCNT 0xFFFFFFFF #define FROM_D(s) \ ((DOM_String*)((s).c_str())) #define FROM_V(s) \ ((DOM_String*)((s).c_str())) class DOMException { public: DOMException(int e) { ASSERT(e != 0); m_code = e; } typedef enum { INDEX_SIZE_ERR = 1, DOMSTRING_SIZE_ERR = 2, HIERARCHY_REQUEST_ERR = 3, WRONG_DOCUMENT_ERR = 4, INVALID_CHARACTER_ERR = 5, NO_DATA_ALLOWED_ERR = 6, NO_MODIFICATION_ALLOWED_ERR = 7, NOT_FOUND_ERR = 8, NOT_SUPPORTED_ERR = 9, INUSE_ATTRIBUTE_ERR = 10 } CODES; short getCode() { return (short)m_code; } const char* getMessage() { return msgno_msg(m_code); } void getDetails(short* code, const char** message, const char** documentUri, int* fileLine) { *code = (short)m_code; *message = msgno_msg(m_code); *documentUri = NULL; *fileLine = 0; } protected: int m_code; }; class NodeList; class NamedNodeMap; class Element; class Document; class DOMImplementation; /* Checks whether an element is part of the tree */ #define LOOSE_NODE(n) \ ((n) && ((n)->nodeType == DOM_ATTRIBUTE_NODE ? \ (n)->u.Attr.ownerElement == NULL : \ (n)->parentNode == NULL)) \ /* We only perform ref counting on nodes outside the tree */ #define INC_NODE_REF(n) \ if(n) incref(n) #define DEC_NODE_REF(n) \ if(n) decref(n) /** * Thin wrapper class for a DOM Node */ class Node { public: enum TYPES { ELEMENT_NODE = DOM_ELEMENT_NODE, ATTRIBUTE_NODE = DOM_ATTRIBUTE_NODE, TEXT_NODE = DOM_TEXT_NODE, CDATA_SECTION_NODE = DOM_CDATA_SECTION_NODE, ENTITY_REFERENCE_NODE = DOM_ENTITY_REFERENCE_NODE, ENTITY_NODE = DOM_ENTITY_NODE, PROCESSING_INSTRUCTION_NODE = DOM_PROCESSING_INSTRUCTION_NODE, COMMENT_NODE = DOM_COMMENT_NODE, DOCUMENT_NODE = DOM_DOCUMENT_NODE, DOCUMENT_TYPE_NODE = DOM_DOCUMENT_TYPE_NODE, DOCUMENT_FRAGMENT_NODE = DOM_DOCUMENT_FRAGMENT_NODE, NOTATION_NODE = DOM_NOTATION_NODE }; Node() { m_node = NULL; } Node(const Node& node) { INC_NODE_REF(node.m_node); m_node = node.m_node; } Node& operator=(const Node& other) { INC_NODE_REF(other.m_node); DEC_NODE_REF(m_node); m_node = other.m_node; return *this; } Node& operator=(const void* null) { ASSERT(null == NULL); DEC_NODE_REF(m_node); m_node = NULL; return *this; } ~Node() { DEC_NODE_REF(m_node); } bool operator==(const Node& other) const { return m_node == other.m_node; } bool operator==(const void* null) const { ASSERT(null == NULL); return m_node == NULL; } bool operator!=(const Node& other) const { return !operator==(other); } bool operator!=(const void* null) const { return !operator==(null); } const Node* operator->() const { return (const Node*)this; } Node* operator->() { return this; } dom_str getNodeName() const throw(DOMException) { ASSERT_VALID(); DOM_String* name = m_node->nodeName; return dom_str(name); } data_str getNodeValue() const throw(DOMException) { ASSERT_VALID(); // TODO: Check on memory management DOM_String* value = DOM_Node_getNodeValue(m_node); return data_str(value); } void setNodeValue(const data_str& value) throw(DOMException) { ASSERT_VALID(); RESET_ERR(); DOM_Node_setNodeValue(m_node, FROM_V(value)); CHECK_ERR(); } short getNodeType() const throw(DOMException) { ASSERT_VALID(); return (short)(m_node->nodeType); } Node getParentNode() const throw(DOMException) { ASSERT_VALID(); return Node(m_node->parentNode); } NodeList getChildNodes() const throw(DOMException); Node getFirstChild() const throw(DOMException) { ASSERT_VALID(); return Node(m_node->firstChild); } Node getLastChild() const throw(DOMException) { ASSERT_VALID(); return Node(m_node->lastChild); } Node getPreviousSibling() const throw(DOMException) { ASSERT_VALID(); return Node(m_node->previousSibling); } Node getNextSibling() const throw(DOMException) { ASSERT_VALID(); return Node(m_node->nextSibling); } NamedNodeMap getAttributes() const throw(DOMException); Document getOwnerDocument() const throw(DOMException); Node insertBefore(const Node& newChild, const Node& refChild) throw(DOMException) { ASSERT_VALID(); ASSERT_VALID_NODE(newChild); ASSERT_VALID_NODE(refChild); RESET_ERR(); Node node(DOM_Node_insertBefore(m_node, newChild.m_node, refChild.m_node)); CHECK_ERR(); return node; } Node replaceChild(const Node& newChild, const Node& refChild) throw(DOMException) { ASSERT_VALID(); ASSERT_VALID_NODE(newChild); ASSERT_VALID_NODE(refChild); RESET_ERR(); Node node(DOM_Node_replaceChild(m_node, newChild.m_node, refChild.m_node)); CHECK_ERR(); return node; } Node removeChild(const Node& oldChild) throw(DOMException) { ASSERT_VALID(); ASSERT_VALID_NODE(oldChild); RESET_ERR(); Node node(DOM_Node_removeChild(m_node, oldChild.m_node)); CHECK_ERR(); return node; } Node appendChild(const Node& newChild) throw(DOMException) { ASSERT_VALID(); ASSERT_VALID_NODE(newChild); RESET_ERR(); Node node(DOM_Node_appendChild(m_node, newChild.m_node)); CHECK_ERR(); return node; } bool hasChildNodes() const throw(DOMException) { ASSERT_VALID(); return DOM_Node_hasChildNodes(m_node) ? true : false; } Node cloneNode(bool deep) const throw(DOMException) { ASSERT_VALID(); RESET_ERR(); Node node(DOM_Node_cloneNode(m_node, deep ? 1 : 0)); CHECK_ERR(); return node; } void normalize() throw(DOMException) { ASSERT_VALID(); if(m_node->nodeType == DOM_ELEMENT_NODE) { RESET_ERR(); DOM_Element_normalize(m_node); CHECK_ERR(); } } bool isSupported(const dom_str& feature, const dom_str& version) const { ASSERT_VALID(); return false; } #if INCOMPLETE dom_str getNamespaceURI() const throw(DOMException) { } dom_str getPrefix() const throw(DOMException) { } void setPrefix(const dom_str& prefix) throw(DOMException) { } dom_str getLocalName() const throw(DOMException) { } #endif bool hasAttributes() const throw (DOMException) { ASSERT_VALID(); if(getNodeType() != ELEMENT_NODE) return false; return m_node->attributes != NULL && m_node->attributes->length > 0; } void setUserData(void* data) throw(DOMException) { ASSERT_VALID(); m_node->userData = data; } void* getUserData() const throw(DOMException) { ASSERT_VALID(); return m_node->userData; } bool isValid() const { return m_node != NULL; } protected: Node(DOM_Node* node) { m_node = node; INC_NODE_REF(m_node); } protected: DOM_Node* m_node; friend class Document; friend class NodeList; friend class NamedNodeMap; private: inline void incref(DOM_Node* node) { ASSERT(node); ++(node->rtfxRefCount); } inline void decref(DOM_Node* node) { ASSERT(node); --(node->rtfxRefCount); if(LOOSE_NODE(node)) { ASSERT(node->parentNode == NULL); if(node->rtfxRefCount <= 0) { ASSERT(node->nodeType == DOM_DOCUMENT_NODE || node->ownerDocument); DOM_Document_destroyNode(node->nodeType == DOM_DOCUMENT_NODE ? node : node->ownerDocument, node); } } } }; class Attr : public Node { public: Attr() { } Attr(const Attr& node) : Node(node) { } Attr& operator=(const Attr& other) { Node::operator=(other); return *this; } Attr& operator=(const void* null) { Node::operator=(null); return *this; } const Attr* operator->() const { return (const Attr*)this; } Attr* operator->() { return this; } dom_str getName() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ATTRIBUTE_NODE); return getNodeName(); } Element getOwnerElement() const throw(DOMException); bool getSpecified() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ATTRIBUTE_NODE); return true; } data_str getValue() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ATTRIBUTE_NODE); return getNodeValue(); } void setValue(const data_str& value) throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ATTRIBUTE_NODE); setNodeValue(value); } protected: Attr(DOM_Node* node) : Node(node) { } friend class Element; friend class Document; }; /** * This wrapper class for an element */ class Element : public Node { public: Element() { } Element(const Element& node) : Node(node) {} Element& operator=(const Node& other) { Node::operator=(other); return *this; } Element& operator=(const Element& other) { Node::operator=(other); return *this; } Element& operator=(const void* null) { Node::operator=(null); return *this; } const Element* operator->() const { return (const Element*)this; } Element* operator->() { return this; } dom_str getTagName() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ELEMENT_NODE); return getNodeName(); } data_str getAttribute(const dom_str& name) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ELEMENT_NODE); RESET_ERR(); // TODO: Check on memory management DOM_String* value = DOM_Element_getAttribute(m_node, FROM_D(name)); CHECK_ERR(); return data_str(value); } void setAttribute(const dom_str& name, const data_str& value) throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ELEMENT_NODE); RESET_ERR(); DOM_Element_setAttribute(m_node, FROM_D(name), FROM_V(value)); CHECK_ERR(); } void removeAttribute(const dom_str& name) throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ELEMENT_NODE); RESET_ERR(); DOM_Element_removeAttribute(m_node, FROM_D(name)); CHECK_ERR(); } Attr getAttributeNode(const dom_str& name) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ELEMENT_NODE); RESET_ERR(); Attr attr(DOM_Element_getAttributeNode(m_node, FROM_D(name))); CHECK_ERR(); return attr; } Attr setAttributeNode(const Attr& attr) throw(DOMException) { ASSERT_VALID(); ASSERT_VALID_NODE(attr); ASSERT_TYPE(ELEMENT_NODE); RESET_ERR(); Attr att(DOM_Element_setAttributeNode(m_node, attr.m_node)); CHECK_ERR(); return att; } Attr removeAttributeNode(const Attr& attr) throw(DOMException) { ASSERT_VALID(); ASSERT_VALID_NODE(attr); ASSERT_TYPE(ELEMENT_NODE); RESET_ERR(); Attr att(DOM_Element_removeAttributeNode(m_node, attr.m_node)); CHECK_ERR(); return att; } NodeList getElementsByTagName(const dom_str& name) const throw(DOMException); #ifdef INCOMPLETE data_str getAttributeNS(const dom_str& uri, const dom_str& name) const throw(DOMException) { } void setAttributeNS(const dom_str& uri, const dom_str& name, const data_str& value) throw(DOMException) { } void removeAttributeNS(const dom_str& uri, const dom_str& name) throw(DOMException) { } Attr getAttributeNodeNS(const dom_str& uri, const dom_str& name) const throw(DOMException) { } Attr setAttributeNodeNS(const Attr& attr) throw(DOMException) { } NodeList getElementsByTagNameNS(const dom_str& uri, const dom_str& name) const throw(DOMException); #endif bool hasAttribute(const dom_str& name) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ELEMENT_NODE); RESET_ERR(); bool ret = (DOM_Element_getAttributeNode(m_node, FROM_D(name)) != NULL); CHECK_ERR(); return ret; } #ifdef INCOMPLETE bool hasAttributeNS(const dom_str& uri, const dom_str& name) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ELEMENT_NODE); return getAttributeNodeNS(uri, name) != NULL; } #endif protected: Element(DOM_Node* node) : Node(node) { } friend class Attr; friend class Document; }; class CharacterData : public Node { public: CharacterData() { } CharacterData(const Node& node) : Node(node) { } CharacterData& operator=(const Node& other) { Node::operator=(other); return *this; } CharacterData& operator=(const CharacterData& other) { Node::operator=(other); return *this; } CharacterData& operator=(const void* null) { Node::operator=(null); return *this; } const CharacterData* operator->() const { return (const CharacterData*)this; } CharacterData* operator->() { return this; } void appendData(const data_str& data) throw(DOMException) { ASSERT_VALID(); ASSERT(getNodeType() == TEXT_NODE || getNodeType() == CDATA_SECTION_NODE || getNodeType() == COMMENT_NODE); RESET_ERR(); DOM_CharacterData_appendData(m_node, FROM_D(data)); CHECK_ERR(); } void deleteData(int offset, int count) throw(DOMException) { ASSERT_VALID(); ASSERT(getNodeType() == TEXT_NODE || getNodeType() == CDATA_SECTION_NODE || getNodeType() == COMMENT_NODE); RESET_ERR(); DOM_CharacterData_deleteData(m_node, offset, count); CHECK_ERR(); } data_str getData() const throw(DOMException) { ASSERT_VALID(); ASSERT(getNodeType() == TEXT_NODE || getNodeType() == CDATA_SECTION_NODE || getNodeType() == COMMENT_NODE); return getNodeValue(); } int getLength() const throw(DOMException) { ASSERT_VALID(); ASSERT(getNodeType() == TEXT_NODE || getNodeType() == CDATA_SECTION_NODE || getNodeType() == COMMENT_NODE); RESET_ERR(); int len = DOM_CharacterData_getLength(m_node); CHECK_ERR(); return len; } void insertData(int offset, const data_str& data) throw(DOMException) { ASSERT_VALID(); ASSERT(getNodeType() == TEXT_NODE || getNodeType() == CDATA_SECTION_NODE || getNodeType() == COMMENT_NODE); RESET_ERR(); DOM_CharacterData_insertData(m_node, offset, FROM_V(data)); CHECK_ERR(); } void replaceData(int offset, int count, const data_str& data) throw(DOMException) { ASSERT_VALID(); ASSERT(getNodeType() == TEXT_NODE || getNodeType() == CDATA_SECTION_NODE || getNodeType() == COMMENT_NODE); RESET_ERR(); DOM_CharacterData_replaceData(m_node, offset, count, FROM_V(data)); CHECK_ERR(); } void setData(const data_str& data) throw(DOMException) { ASSERT_VALID(); ASSERT(getNodeType() == TEXT_NODE || getNodeType() == CDATA_SECTION_NODE || getNodeType() == COMMENT_NODE); setNodeValue(data); } data_str substringData(int offset, int count) const throw(DOMException) { ASSERT_VALID(); ASSERT(getNodeType() == TEXT_NODE || getNodeType() == CDATA_SECTION_NODE || getNodeType() == COMMENT_NODE); RESET_ERR(); DOM_String* value = DOM_CharacterData_substringData(m_node, offset, count); CHECK_ERR(); return data_str(value); } protected: CharacterData(DOM_Node* node) : Node(node) { } }; class Text : public CharacterData { public: Text() { } Text(const Node& node) : CharacterData(node) { } Text& operator=(const Text& other) { CharacterData::operator=(other); return *this; } Text& operator=(const void* null) { CharacterData::operator=(null); return *this; } const Text* operator->() const { return (const Text*)this; } Text* operator->() { return this; } Text splitText(int offset) throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(TEXT_NODE); RESET_ERR(); Text text(DOM_Text_splitText(m_node, offset)); CHECK_ERR(); return text; } protected: Text(DOM_Node* node) : CharacterData(node) { } friend class Document; }; class CDATASection : public Text { public: CDATASection() { } CDATASection(const CDATASection& node) : Text(node) { } CDATASection& operator=(const CDATASection& other) { Text::operator=(other); return *this; } CDATASection& operator=(void* null) { Text::operator=(null); return *this; } const CDATASection* operator->() const { return (const CDATASection*)this; } CDATASection* operator->() { return this; } protected: CDATASection(DOM_Node* node) : Text(node) { } friend class Document; }; class Comment : public CharacterData { public: Comment() { } Comment(const Comment& node) : CharacterData(node) { } Comment& operator=(const Node& other) { Node::operator=(other); return *this; } Comment& operator=(const Comment& other) { CharacterData::operator=(other); return *this; } Comment& operator=(void* null) { CharacterData::operator=(null); return *this; } const Comment* operator->() const { return (const Comment*)this; } Comment* operator->() { return this; } protected: Comment(DOM_Node* node) : CharacterData(node) { } friend class Document; }; class ProcessingInstruction : public Node { public: ProcessingInstruction() { } ProcessingInstruction(const ProcessingInstruction& node) : Node(node) { } ProcessingInstruction& operator=(const Node& other) { Node::operator=(other); return *this; } ProcessingInstruction& operator=(const ProcessingInstruction& other) { Node::operator=(other); return *this; } ProcessingInstruction& operator=(void* null) { Node::operator=(null); return *this; } const ProcessingInstruction* operator->() const { return (const ProcessingInstruction*)this; } ProcessingInstruction* operator->() { return this; } data_str getData() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(PROCESSING_INSTRUCTION_NODE); return getNodeValue(); } dom_str getTarget() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(PROCESSING_INSTRUCTION_NODE); return getNodeName(); } void setData(const data_str& data) throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(PROCESSING_INSTRUCTION_NODE); setNodeValue(data); } protected: ProcessingInstruction(DOM_Node* node) : Node(node) { } friend class Document; }; class DocumentFragment : public Node { public: DocumentFragment() { } DocumentFragment(const DocumentFragment& node) : Node(node) { } DocumentFragment& operator=(const Node& other) { Node::operator=(other); return *this; } DocumentFragment& operator=(const DocumentFragment& other) { Node::operator=(other); return *this; } DocumentFragment& operator=(void* null) { Node::operator=(null); return *this; } const DocumentFragment* operator->() const { return (const DocumentFragment*)this; } DocumentFragment* operator->() { return this; } protected: DocumentFragment(DOM_Node* node) : Node(node) { } friend class Document; }; class Entity : public Node { public: Entity() { } Entity(const Entity& node) : Node(node) { } Entity& operator=(const Node& other) { Node::operator=(other); return *this; } Entity& operator=(const Entity& other) { Node::operator=(other); return *this; } Entity& operator=(void* null) { Node::operator=(null); return *this; } const Entity* operator->() const { return (const Entity*)this; } Entity* operator->() { return this; } dom_str getNotationName() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ENTITY_NODE); return getNodeName(); } dom_str getPublicId() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ENTITY_NODE); return dom_str(m_node->u.Entity.publicId); } dom_str getSystemId() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ENTITY_NODE); return dom_str(m_node->u.Entity.systemId); } protected: Entity(DOM_Node* node) : Node(node) { } friend class DocumentType; }; class EntityReference : public Node { public: EntityReference() { } EntityReference(const EntityReference& node) : Node(node) { } EntityReference& operator=(const Node& other) { Node::operator=(other); return *this; } EntityReference& operator=(const EntityReference& other) { Node::operator=(other); return *this; } EntityReference& operator=(void* null) { Node::operator=(null); return *this; } const EntityReference* operator->() const { return (const EntityReference*)this; } EntityReference* operator->() { return this; } protected: EntityReference(DOM_Node* node) : Node(node) { } friend class DocumentType; friend class Document; }; class Notation : public Node { public: Notation() { } Notation(const Notation& node) : Node(node) { } Notation& operator=(const Node& other) { Node::operator=(other); return *this; } Notation& operator=(const Notation& other) { Node::operator=(other); return *this; } Notation& operator=(void* null) { Node::operator=(null); return *this; } const Notation* operator->() const { return (const Notation*)this; } Notation* operator->() { return this; } dom_str getPublicId() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(NOTATION_NODE); return dom_str(m_node->u.Notation.publicId); } dom_str getSystemId() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(NOTATION_NODE); return dom_str(m_node->u.Notation.systemId); } protected: Notation(DOM_Node* node) : Node(node) { } friend class DocumentType; }; class DocumentType : public Node { public: DocumentType() { } DocumentType(const DocumentType& node) : Node(node) { } DocumentType& operator=(const Node& other) { Node::operator=(other); return *this; } DocumentType& operator=(const DocumentType& other) { Node::operator=(other); return *this; } DocumentType& operator=(void* null) { Node::operator=(null); return *this; } const DocumentType* operator->() const { return (const DocumentType*)this; } DocumentType* operator->() { return this; } NamedNodeMap getEntities() const throw(DOMException); NamedNodeMap getNotations() const throw(DOMException); dom_str getInternalSubset() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_TYPE_NODE); return dom_str(m_node->u.DocumentType.internalSubset); } dom_str getName() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_TYPE_NODE); return getNodeName(); } protected: DocumentType(DOM_Node* node) : Node(node) { } friend class Document; friend class DOMImplementation; }; class Document : public Node { public: Document() { } Document(const Document& doc) : Node(doc) { } Document& operator=(const Document& other) { Node::operator=(other); return *this; } Document& operator=(void* null) { Node::operator=(null); return *this; } const Document* operator->() const { return (const Document*)this; } Document* operator->() { return this; } DocumentType getDocType() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); DocumentType dt(DOM_Document_getDoctype(m_node)); CHECK_ERR(); return dt; } DOMImplementation getImplementation() const throw(DOMException); Element getDocumentElement() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); Element el(DOM_Document_getDocumentElement(m_node)); CHECK_ERR(); return el; } Element createElement(const dom_str& tag) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); Element el(DOM_Document_createElement(m_node, FROM_D(tag))); CHECK_ERR(); return el; } DocumentFragment createDocumentFragment() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); DocumentFragment df(DOM_Document_createDocumentFragment(m_node)); CHECK_ERR(); return df; } Text createTextNode(const data_str& data) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); Text text(DOM_Document_createTextNode(m_node, FROM_V(data))); CHECK_ERR(); return text; } Comment createComment(const data_str& data) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); Comment comment(DOM_Document_createComment(m_node, FROM_V(data))); CHECK_ERR(); return comment; } CDATASection createCDATASection(const data_str& data) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); CDATASection cdata(DOM_Document_createCDATASection(m_node, FROM_V(data))); CHECK_ERR(); return cdata; } ProcessingInstruction createProcessingInstruction(const dom_str& targ, const data_str& data) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); ProcessingInstruction pi(DOM_Document_createProcessingInstruction (m_node, FROM_D(targ), FROM_V(data))); CHECK_ERR(); return pi; } Attr createAttribute(const dom_str& name) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); Attr attr(DOM_Document_createAttribute(m_node, FROM_D(name))); CHECK_ERR(); return attr; } EntityReference createEntityReference(const dom_str& name) throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); EntityReference er(DOM_Document_createEntityReference(m_node, FROM_D(name))); CHECK_ERR(); return er; } NodeList getElementsByTagName(const dom_str& name) const throw(DOMException); #ifdef INCOMPLETE Node importNode(const Node& import, bool deep) const throw(DOMException) { } Element createElementNS(const dom_str& uri, const dom_str& tag) const throw(DOMException) { } Attr createAttributeNS(const dom_str& uri, const dom_str& name) const throw(DOMException) { } NodeList getElementsByTagNameNS(const dom_str& uri, const dom_str& name) const throw(DOMException); Element getElementById(const dom_str& id) const throw(DOMException) { } #endif void serialize(FILE* f) throw(DOMException) { ASSERT_VALID(); RESET_ERR(); DOM_DocumentLS_fwrite(m_node, f); CHECK_ERR(); } protected: Document(DOM_Document* doc) : Node(doc) { } friend class Node; friend class DOMImplementation; }; class DOMImplementation { public: DOMImplementation() { } DOMImplementation(const DOMImplementation& impl) { } DOMImplementation& operator=(const DOMImplementation& other) { return *this; } DOMImplementation& operator=(void* null) { return *this; } const DOMImplementation* operator->() const { return (const DOMImplementation*)this; } DOMImplementation* operator->() { return this; } Document createDocument(const dom_str& uri, const dom_str& qname, const DocumentType& type) const throw(DOMException) { RESET_ERR(); Document doc(DOM_Implementation_createDocument (FROM_D(uri), FROM_D(qname), type.m_node)); CHECK_ERR(); return doc; } DocumentType createDocumentType(const dom_str& qname, const dom_str& publicId, const dom_str& systemId) const throw(DOMException) { RESET_ERR(); DocumentType doctype(DOM_Implementation_createDocumentType (FROM_D(qname), FROM_D(publicId), FROM_D(systemId))); CHECK_ERR(); return doctype; } bool hasFeature(const dom_str& feature, const dom_str& version) const throw(DOMException) { RESET_ERR(); int ret = DOM_Implementation_hasFeature(FROM_D(feature), FROM_D(version)); CHECK_ERR(); return ret == 0 ? false : true; } }; /* We only perform ref counting on lists marked that way */ #define INC_NODELIST_REF(l) \ if((l).m_list != NULL && ((l).m_list->rtfxRefCount) != NO_REFCNT) incref((l).m_list) #define DEC_NODELIST_REF(l) \ if((l).m_list != NULL && ((l).m_list->rtfxRefCount) != NO_REFCNT) decref((l).m_list) class NodeList { public: NodeList() { m_list = NULL; } NodeList(const NodeList& list) { INC_NODELIST_REF(list); m_list = list.m_list; } NodeList& operator=(const NodeList& other) { INC_NODELIST_REF(other); DEC_NODELIST_REF(*this); m_list = other.m_list; return *this; } NodeList& operator=(const void* null) { ASSERT(null == NULL); DEC_NODELIST_REF(*this); m_list = NULL; return *this; } virtual ~NodeList() { DEC_NODELIST_REF(*this); } bool operator==(const NodeList& other) const { return m_list == other.m_list; } bool operator==(const void* null) const { ASSERT(null == NULL); return m_list == NULL; } bool operator!=(const NodeList& other) const { return !operator==(other); } bool operator!=(const void* null) const { return !operator==(null); } const NodeList* operator->() const { return (const NodeList*)this; } NodeList* operator->() { return this; } #ifdef COMPARE_REF bool operator==(const NodeList& other) const { return m_list == ((NodeList&)other).m_list; } #endif virtual int getLength() const throw(DOMException) { ASSERT_VALID(); return m_list->length; } virtual Node item(int index) const throw(DOMException) { ASSERT_VALID(); RESET_ERR(); Node node(DOM_NodeList_item(m_list, index)); CHECK_ERR(); return node; } protected: NodeList(DOM_NodeList* list, bool refcnt) { m_list = list; if(m_list != NULL) { if(refcnt) INC_NODELIST_REF(*this); else m_list->rtfxRefCount = NO_REFCNT; } } bool isValid() const { return m_list != NULL; } protected: DOM_NodeList* m_list; friend class Element; friend class Document; private: inline void incref(DOM_NodeList* list) { ASSERT(list && (list->rtfxRefCount) != NO_REFCNT); ++(list->rtfxRefCount); } inline void decref(DOM_NodeList* list) { ASSERT(list->rtfxRefCount != NO_REFCNT); --(list->rtfxRefCount); if(list->rtfxRefCount <= 0) { ASSERT(list->_ownerDocument != NULL); DOM_Document_destroyNodeList(list->_ownerDocument, list, 0); } } friend class Node; }; class NamedNodeMap : public NodeList { public: NamedNodeMap() { } NamedNodeMap(const NamedNodeMap& list) : NodeList(list) { } virtual ~NamedNodeMap() {} NamedNodeMap& operator=(const NamedNodeMap& other) { NodeList::operator=(other); return *this; } NamedNodeMap& operator=(void* null) { NodeList::operator=(null); return *this; } const NamedNodeMap* operator->() const { return (const NamedNodeMap*)this; } NamedNodeMap* operator->() { return this; } virtual int getLength() const throw(DOMException) { ASSERT_VALID(); return NodeList::getLength(); } virtual Node getNamedItem(const dom_str& name) const throw(DOMException) { ASSERT_VALID(); RESET_ERR(); Node node(DOM_NamedNodeMap_getNamedItem(m_list, FROM_D(name))); CHECK_ERR(); return node; } #ifdef INCOMPLETE virtual Node getNamedItemNS(const dom_str& uri, const dom_str& name) const throw(DOMException) { } #endif virtual Node item(int index) const throw(DOMException) { ASSERT_VALID(); RESET_ERR(); Node node(DOM_NodeList_item(m_list, index)); CHECK_ERR(); return node; } Node removeNamedItem(const dom_str& name) throw(DOMException) { ASSERT_VALID(); RESET_ERR(); Node node(DOM_NamedNodeMap_removeNamedItem(m_list, FROM_D(name))); CHECK_ERR(); return node; } #ifdef INCOMPLETE virtual Node removeNamedItemNS(const dom_str& uri, const dom_str& name) throw(DOMException) { ASSERT_VALID(); _try_(S::SDOM_NOT_SUPPORTED_ERR); return Node(); } #endif Node setNamedItem(const Node& arg) throw(DOMException) { ASSERT_VALID(); ASSERT_VALID_NODE(arg); RESET_ERR(); Node node(DOM_NamedNodeMap_setNamedItem(m_list, arg.m_node)); CHECK_ERR(); return node; } #ifdef INCOMPLETE virtual Node setNamedItemNS(const Node& arg) throw(DOMException) { ASSERT_VALID(); ASSERT_VALID_NODE(arg); _try_(S::SDOM_NOT_SUPPORTED_ERR); return Node(); } #endif protected: NamedNodeMap(DOM_NodeList* list, bool refcnt) : NodeList(list, refcnt) { } friend class Node; friend class DocumentType; }; inline NodeList Node::getChildNodes() const throw(DOMException) { ASSERT_VALID(); return NodeList(m_node->childNodes, false); } inline NamedNodeMap Node::getAttributes() const throw(DOMException) { ASSERT_VALID(); if(getNodeType() != ELEMENT_NODE) return NamedNodeMap(); return NamedNodeMap(m_node->attributes, false); } inline Document Node::getOwnerDocument() const throw(DOMException) { ASSERT_VALID(); return Document(m_node->ownerDocument); } inline Element Attr::getOwnerElement() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ATTRIBUTE_NODE); return Element(m_node->u.Attr.ownerElement); } inline NodeList Element::getElementsByTagName(const dom_str& name) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(ELEMENT_NODE); RESET_ERR(); NodeList list(DOM_Element_getElementsByTagName(m_node, FROM_D(name)), true); CHECK_ERR(); return list; } #ifdef INCOMPLETE inline NodeList Element::getElementsByTagNameNS(const dom_str& uri, const dom_str& name) const throw(DOMException) { } #endif inline NodeList Document::getElementsByTagName(const dom_str& name) const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); RESET_ERR(); NodeList list(DOM_Document_getElementsByTagName(m_node, FROM_D(name)), true); CHECK_ERR(); return list; } #ifdef INCOMPLETE inline NodeList Document::getElementsByTagNameNS(const dom_str& uri, const dom_str& name) const throw(DOMException) { } #endif inline DOMImplementation Document::getImplementation() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_NODE); return DOMImplementation(); } inline NamedNodeMap DocumentType::getEntities() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_TYPE_NODE); return NamedNodeMap(m_node->u.DocumentType.entities, false); } inline NamedNodeMap DocumentType::getNotations() const throw(DOMException) { ASSERT_VALID(); ASSERT_TYPE(DOCUMENT_TYPE_NODE); return NamedNodeMap(m_node->u.DocumentType.notations, false); } }; // namespace DOM #endif //__DOMCXX_H__