include/HTMLParser/DOM.hpp

Go to the documentation of this file.
00001 #ifndef hpp_CPP_DOMDeclaration_CPP_hpp
00002 #define hpp_CPP_DOMDeclaration_CPP_hpp
00003 
00004 // We need Strings
00005 #include "../Strings/Strings.hpp"
00006 // We need N-Tree
00007 #include "../Tree/NTree.hpp"
00008 // We need AVL tree too
00009 #include "../Tree/Avl.hpp"
00010 // We need attributes
00011 #include "Attributes.hpp"
00012 
00013 
00014 namespace DOM
00015 {
00016     // Forward declare the node class
00017     struct Node;
00018 }
00019 
00020 namespace HTML
00021 {
00023     typedef Tree::NTree<const DOM::Node *> DOMTree;
00024     namespace Elements
00025     {
00026         class Element;
00027         namespace Allocators
00028         {
00029             class BaseAllocator;
00030         }
00031     }
00032 }
00033 
00036 namespace DOM
00037 {
00038     namespace Exceptions
00039     {
00040         struct DOMException
00041         { 
00042             enum { code = 0 }; 
00043         };
00044 
00045         template <int codeImpl>
00046             struct TypedDOMException { enum { code = codeImpl }; };
00047 
00048         // ExceptionCode
00049         typedef TypedDOMException<1>    IndexSize;
00050         typedef TypedDOMException<2>    StringSize;
00051         typedef TypedDOMException<3>    HierarchyRequest;
00052         typedef TypedDOMException<4>    WrongDocument;
00053         typedef TypedDOMException<5>    InvalidCharacter;
00054         typedef TypedDOMException<6>    NoDataAllowed;
00055         typedef TypedDOMException<7>    NoModificationAllowed;
00056         typedef TypedDOMException<8>    NotFound;
00057         typedef TypedDOMException<9>    NotSupported;
00058         typedef TypedDOMException<10>   AttributeInUse;
00059         typedef TypedDOMException<11>   InvalidState;
00060         typedef TypedDOMException<12>   Syntax;
00061         typedef TypedDOMException<13>   InvalidModification;
00062         typedef TypedDOMException<14>   Namespace;
00063         typedef TypedDOMException<15>   InvalidAccess;
00064     }
00065 
00067     typedef Strings::VerySimpleReadOnlyString DOMString;
00069     typedef HTML::DOMTree DOMTree;
00070 
00071 
00073     struct NodeList
00074     {
00075     private:
00077         DOMTree::Node & parent;
00078 
00079     public:
00081         const uint32 length;
00084         const Node * item(const uint32 index) throw() { if (!length) return 0; DOMTree::Node * child = parent.childAtIndex(index); return child ? child->getData() : 0; }
00085         
00086     public:
00088         NodeList(DOMTree::Node & parentNode) : parent(parentNode), length(parent.getChildrenCount()) {}
00090         NodeList(DOMTree::Node * parentPtr) : parent(*parentPtr), length(parentPtr ? parent.getChildrenCount(): 0) {}
00092         NodeList(const NodeList & copy) : parent(copy.parent), length(copy.length) {}
00093 
00095         virtual ~NodeList() { }
00096     };
00097 
00101     struct NamedNodeMap
00102     {
00103     public:
00104         // The Attribute tree 
00105         typedef Tree::AVL::Tree<const Node *, HTML::GenericAttribute::AttributeID> AttribTree;
00106 
00107     private:
00108         AttribTree attribTree;
00109 
00111         AttribTree::IterT getItemIterFromName(const DOMString & name) const throw();
00112        
00113     public:
00116         inline const Node * getNamedItem(const DOMString & name) const throw();
00120         const Node * setNamedItem(const Node * const arg);
00124         const Node * removeNamedItem(const DOMString & name);
00127         const Node * item(const uint32 index) const throw();
00129         inline const uint32 length() const { return attribTree.getSize(); }
00130 
00131         // Allow cloning thanks to the helpers
00132     public:
00134         inline AttribTree::IterT getFirstIterator() const throw() { return attribTree.getFirstIterator(); }
00136         inline void Append(const Node * attribute, const HTML::GenericAttribute::AttributeID & AID) { attribTree.insertObject(attribute, AID); }
00137         
00138     };
00139 
00140     // Forward declare the document class
00141     class Document;
00142     // Forward declare the document type class
00143     class DocumentType;
00144 
00145 
00146 
00147 
00148 
00150     struct DOMImplementation 
00151     {
00152         // Members
00153     private:
00155         const volatile HTML::Elements::Allocators::BaseAllocator *     allocator;
00156 
00157         // Interface
00158     public:
00163         const bool              hasFeature(const DOMString & feature, const DOMString & version) const throw();
00171         const DocumentType *    createDocumentType(const DOMString & qualifiedName, const DOMString & publicId, const DOMString & systemId) const;
00179         const Document *         createDocument(const DOMString & namespaceURI, const DOMString & qualifiedName, const DocumentType * docType) const;
00180 
00181         // Constructor
00182     public:
00184         DOMImplementation(const volatile HTML::Elements::Allocators::BaseAllocator * _allocator) : allocator(_allocator) {}
00185 
00186         // Accessor
00187     public:
00189         inline void setAllocator(const volatile HTML::Elements::Allocators::BaseAllocator * _allocator) { if (_allocator) allocator = _allocator; }
00190     };
00191 
00193     const DOMImplementation & getCurrentDOMImplementation(const volatile HTML::Elements::Allocators::BaseAllocator * _allocator);
00194 
00196     struct Node
00197     {
00198         // Our private members
00199     private:
00201         DOMTree::Node  *   treeNode;
00202 
00203         
00204     public:
00206         struct NodeType
00207         {
00208             enum Type
00209             {
00210                 Element                 = 1,
00211                 Attribute               = 2,
00212                 Text                    = 3,
00213                 CDATA_Section           = 4,
00214                 EntityReference         = 5,
00215                 Entity                  = 6,
00216                 ProcessingInstruction   = 7,
00217                 Comment                 = 8,
00218                 Document                = 9,
00219                 DocumentType            = 10,
00220                 DocumentFragment        = 11,
00221                 Notation                = 12,
00222             };
00223         };
00224 
00226         const NodeType::Type nodeType;
00227 
00228         // The interface
00229     public:
00232         virtual DOMString nodeName() const          { return DOMString("Unknown"); } 
00235         virtual DOMString nodeValue() const         { return DOMString();         }  
00238         virtual void nodeValue(const DOMString & newValue) { throw Exceptions::NoModificationAllowed(); }
00240         inline const uint16 getNodeType() const     { return (uint16)nodeType; }
00243         virtual DOMString namespaceURI() const      { return DOMString();       }  
00246         virtual DOMString localName()   const       { return DOMString(); }
00249         virtual DOMString prefix()   const          { return DOMString(); }
00252         void prefix(const DOMString &) const        { throw Exceptions::NoModificationAllowed(); }
00253 
00256         inline const Node * parentNode() const          { return treeNode && treeNode->parentNode() ?  treeNode->parentNode()->getData() : 0; }
00259         inline NodeList * childNodes() const            { return new NodeList(*treeNode); }
00262         inline const Node * firstChild() const          { return treeNode && treeNode->firstChild() ? treeNode->firstChild()->getData() : 0; }
00265         inline const Node * lastChild() const           { DOMTree::Node * child = treeNode ? treeNode->lastChild() : 0; return child ? child->getData() : 0; } 
00268         inline const Node * previousSibling() const     { DOMTree::Node * child = treeNode ? treeNode->parentNode() : 0; uint32 index = 0; if (child && ((index = child->findChildIndex(this)) != child->getChildrenCount()) && (child = child->childAtIndex(index - 1))) return child ? child->getData() : 0; return 0;  }
00271         inline const Node * nextSibling() const         { DOMTree::Node * child = treeNode ? treeNode->nextNode() : 0; return child ? child->getData() : 0; }
00272             
00273 
00276         virtual const NamedNodeMap * attributes() const     { return 0; }
00279         inline const DOM::Document * ownerDocument() const       
00280         { 
00281             DOMTree::Node * parent = treeNode ? treeNode->parentNode() : 0; 
00282             if (!parent)   
00283                 return nodeType == NodeType::Document ? (const DOM::Document*)this : 0; 
00284             while (parent->parentNode()) parent = parent->parentNode(); 
00285             if (parent->getData()) 
00286                 return parent->getData()->nodeType == NodeType::Document ? (const DOM::Document*)parent->getData() : 0; 
00287             return 0; 
00288         }
00291         inline bool hasChildNodes() const throw()    { return treeNode ? (treeNode->getChildrenCount() > 0) : false; }
00294         inline bool hasAttributes() const throw()    { return nodeType == NodeType::Element ? (attributes() != 0) : false; }        
00297         inline const uint32 getChildrenCount() const throw() { return treeNode ? treeNode->getChildrenCount() : 0; }
00298          
00299         // Allocator interface
00300     public:    
00303         virtual void returnToAllocator(const volatile HTML::Elements::Allocators::BaseAllocator * allocator);
00304 
00305         // Helpers method (not exported)
00306     private:
00308         inline DOMTree::Node * removeIfAlreadyThere(const Node * node, uint32 & indexOf)   { DOMTree::Node * tNode = 0; uint32 index = treeNode->findChildIndex(node); if (index != treeNode->getChildrenCount()) { tNode = treeNode->forgetChildAtIndex(index); if (indexOf > index) indexOf --; } return tNode; }
00309         
00310         // The child operations
00311     public:
00317         inline const Node * insertBefore(const Node * newNode, const Node * refNode) 
00318         {
00319             // If the new node is invalid, or we are trying to insert a node before itself we are done
00320             if (!newNode || newNode == refNode || !treeNode) return newNode; 
00321             // If the reference node is 0, then append the new node
00322             if (!refNode)  {   DOMTree::Node * node = new DOMTree::Node(newNode, treeNode); newNode->setTreeNode(node); treeNode->appendChild(node); return newNode;   }
00323             // Find the reference node
00324             uint32 index = treeNode->findChildIndex(refNode);
00325             if (index == treeNode->getChildrenCount()) throw Exceptions::NotFound();
00326             // Remove if the node is already here
00327             DOMTree::Node * node = removeIfAlreadyThere(newNode, index);
00328             // Create the tree node if we can't reuse an "already here" node (else reuse it)  
00329             if (!node) { node = new DOMTree::Node(newNode, treeNode); newNode->setTreeNode(node); }
00330             treeNode->insertChildBefore(node, index);
00331             return newNode;
00332         }
00333 
00339         inline const Node * replaceChild(const Node * newNode, const Node * oldNode) 
00340         {
00341             if (!newNode || !oldNode || !treeNode) return 0; 
00342             // If we try to replace a node by itself, well, escape
00343             if (newNode == oldNode)   return oldNode;
00344             // We will try to mutate the node pointer 
00345             uint32 index = treeNode->findChildIndex(oldNode);
00346             if (index == treeNode->getChildrenCount()) throw Exceptions::NotFound();
00347             DOMTree::Node * node = removeIfAlreadyThere(newNode, index);
00348             DOMTree::Node * child = treeNode->childAtIndex(index);
00349             const Node * ret = child->getData();
00350             child->getData() = newNode;
00351             // Need to delete the node
00352             if (node) { node->getData() = 0; node->Suicide(); }
00353             return ret;
00354         }
00355 
00360         inline const Node * removeChild(const Node * oldNode)
00361         {
00362             if (!oldNode) return 0;
00363             uint32 index = 0;
00364             DOMTree::Node * node = removeIfAlreadyThere(oldNode, index);
00365             if (!node) throw Exceptions::NotFound();
00366             const Node * ret = node->getData();
00367             node->getData() = 0; node->Suicide();
00368             return ret;
00369         }
00370 
00374         inline const Node * appendChild(const Node * newNode)                   { return insertBefore(newNode, 0); }
00375 
00381         inline Node * cloneNode(bool deepCloning) const throw()                 { return Clone(deepCloning); } 
00382 
00386         inline void normalize() throw() { }
00387 
00392         static inline bool isSupported(const DOMString & feature, const DOMString & version) { return getCurrentDOMImplementation(0).hasFeature(feature, version); }
00393 
00394 
00395         
00396         // Our implementation specific code is here
00397     public:    
00399         inline void setTreeNode(DOMTree::Node * newTreeNode) const { const_cast<DOMTree::Node *>(treeNode) = newTreeNode; }
00400 
00404         inline const Node * firstChildOfType(const NodeType::Type type) const 
00405         { 
00406             if (treeNode && treeNode->firstChild()) 
00407             { 
00408                 DOMTree::Node * child = treeNode->firstChild();  
00409                 while (child) { if (child->getData() && child->getData()->nodeType == type) return child->getData(); child = child->nextNode(); }
00410             }
00411             return 0;
00412         }
00413 
00417         inline void Suicide() { if (treeNode) treeNode->Suicide(); }
00418 
00419         // Construction and destruction
00420     protected:
00422         Node(const NodeType::Type & type, DOMTree::Node * ref = 0) : nodeType(type), treeNode(ref) {}
00424         inline DOMTree::Node * getTreeNode()                { return treeNode; }
00426         inline const DOMTree::Node * getTreeNode() const    { return treeNode; }
00427     public:    
00429         virtual ~Node() {}
00430         
00431         // Child must implement this interface to fit the standard
00432     protected:    
00434         virtual Node * Clone(bool deepCopy) const throw()
00435         {
00436             //TODO: Use the allocator instead
00437             Node * node = new Node(nodeType);
00438             DOMTree::Node * tNode = new DOMTree::Node(node);
00439             node->setTreeNode(tNode);
00440             if (deepCopy)
00441             {
00442                 const Node * child = firstChild();
00443                 while (child)
00444                 {
00445                     node->appendChild(child->Clone(true));
00446                     child = child->nextSibling();
00447                 }
00448             }
00449             return 0;
00450         }
00451     };
00452 
00453 
00454 
00455 
00457     class CharacterData : public Node
00458     {
00459         // Members
00460     private:
00462         DOMString           sharedData;
00464         Strings::FastString ownedData;
00466         bool                useSharedData;
00467 
00468         // Helpers
00469     private: 
00471         inline void Mutate() throw()             { if (useSharedData) { ownedData = Strings::convert(sharedData); useSharedData = false; } }
00472 
00473         // Allow text to modify us while splitting
00474     protected:
00476         inline void limitTo(uint32 count)         
00477         {
00478             if (useSharedData) 
00479                 if (sharedData.limitTo(count)) return;
00480 
00481             Mutate(); ownedData = ownedData.midString(0, count);
00482         }
00483 
00485         inline bool isShared() const { return useSharedData; }
00486 
00487         // Common Node interface
00488     public:
00491         virtual DOMString nodeValue() const                 { return data(); }
00493         virtual void nodeValue(const DOMString & newValue)  { data(newValue); }
00494 
00495         // CharacterData interface
00496     public:    
00499         inline DOMString    data() const throw() { return useSharedData ? sharedData : DOMString((const char*)ownedData, ownedData.getLength()); }
00502         inline void data(const DOMString newData) { useSharedData = false; ownedData = Strings::convert(newData); }
00503 
00506         inline const uint32 length() const throw()               { return useSharedData ? sharedData.getLength() : ownedData.getLength(); }
00512         inline DOMString   substringData(uint32 offset, uint32 count)   { if ((int)offset < 0 || offset >= length()) throw Exceptions::IndexSize(); count = (length() - offset) < count ? (length() - offset) : count; if (useSharedData) return DOMString(&sharedData.getData()[offset], count); else return DOMString((const char*)ownedData + offset, count); }
00515         inline void        appendData(const DOMString &  arg)           { Mutate(); ownedData += Strings::convert(arg); }
00520         inline void        insertData(uint32 offset, const DOMString &  arg) { if ((int)offset < 0 || offset >= length()) throw Exceptions::IndexSize(); Mutate(); ownedData.Insert(offset, Strings::convert(arg)); }
00525         inline void         deleteData(uint32 offset, uint32 count)     { if ((int)offset < 0 || (int)count < 0 || offset >= length()) throw Exceptions::IndexSize(); Mutate(); ownedData.Remove((int)offset, (int)count); }
00531         inline void         replaceData(uint32 offset, uint32 count, const DOMString &  arg) { deleteData(offset, count); insertData(offset, arg); }
00532 
00533         // Construction
00534     public:    
00536         CharacterData(const NodeType::Type & type, const DOMString & _data, DOMTree::Node * ref = 0) : Node(type, ref), sharedData(_data), useSharedData(true) {}
00538         CharacterData(const NodeType::Type & type, const Strings::FastString & string, DOMTree::Node * ref = 0) : Node(type, ref), ownedData(string), useSharedData(false) {}
00539     };
00540 
00541 
00543     class Text : public CharacterData
00544     {
00545         // The Text interface
00546     public:
00553         inline const Text * splitText(uint32 offset) 
00554         {
00555             uint32 currentLen = length();
00556             DOMString rightString = substringData(offset, currentLen - offset);
00557             // Ok, cut this object
00558             limitTo(offset);
00559 
00560             // And create the new node
00561             Text * text = new Text(rightString);
00562             // Insert the newly created node in the tree
00563             return (Text*)insertBefore(text, nextSibling());
00564         }
00565 
00566         // The Node interface 
00567     public:
00570         virtual DOMString nodeName() const           { return DOMString("#text"); }
00573         virtual Node * Clone(bool deepCopy) const throw() { Node * node = new Text(isShared() ? data() : DOMString()); if (!isShared()) ((Text*)node)->data(data()); DOMTree::Node * tNode = new DOMTree::Node(node); node->setTreeNode(tNode); return node; }         
00574 
00575         // Construction and destruction
00576     public:    
00577         Text(const DOMString & text, DOMTree::Node * ref = 0) : CharacterData(NodeType::Text, text, ref) {}
00578         Text(const Strings::FastString & text, DOMTree::Node * ref = 0) : CharacterData(NodeType::Text, text, ref) {}
00579     };
00580 
00581 
00582     // Forward declare the Element class
00583     class Element;
00584 
00585     class Attr : public Node
00586     {
00587         // Members
00588     private:
00590         HTML::Attributes::Attribute *   attribute;
00592         const DOM::Element *            element;
00594         DOMString                       sharedData;
00596         Strings::FastString             ownedData;
00598         bool                            useSharedData;
00599 
00600         // Helpers
00601     private: 
00603         inline void Mutate() throw()             { if (useSharedData) { ownedData = Strings::convert(sharedData); useSharedData = false; } }
00604 
00605         // The Attr interface
00606     public:
00608         inline DOMString name() const throw()      { return DOMString(attribute->attributeName()); } 
00611         inline bool      specified() const throw() { return false; }
00614         inline DOMString value() const throw()     { return useSharedData ? sharedData : DOMString((const char*)ownedData, ownedData.getLength()); }
00620         inline void value(const DOMString & newValue)   {  Mutate(); ownedData = Strings::convert(newValue);  }
00621 
00624         const DOM::Element * ownerElement() const       { return element; }
00625     
00626         // The Node interface implementation
00627     public: 
00630         virtual DOMString nodeName() const           { return name(); }
00633         virtual DOMString nodeValue() const           { return value(); }
00635         virtual void nodeValue(const DOMString & newValue) { value(newValue); }
00636 
00638         virtual Node * Clone(bool deepCopy) const throw() { return internalClone(deepCopy); } 
00639 
00640         // Allocator interface
00641     public:    
00644         virtual void returnToAllocator(const volatile HTML::Elements::Allocators::BaseAllocator * allocator);
00645 
00646         // Our implementation for cleaning the attribute
00647     public:
00649         inline HTML::Attributes::Attribute * getAttributeDeclaration() { return attribute; }
00650 
00651         // The construction and destruction 
00652     public:  
00653         Attr(HTML::Attributes::Attribute * attrib, const DOMString & value) : Node(Node::NodeType::Attribute), attribute(attrib), sharedData(value), useSharedData(true) {}
00654 
00655     private:
00657         inline Node * internalClone(bool deepCopy, bool setSpecified = true) const throw()
00658         {
00659             //TODO: Use the allocator instead
00660             Attr * attr = new Attr(new HTML::Attributes::Attribute(*attribute), useSharedData ? sharedData : DOMString());
00661             if (!useSharedData) attr->value(value());
00662             DOMTree::Node * tNode = new DOMTree::Node(attr);
00663             attr->setTreeNode(tNode);
00664             if (setSpecified) attr->setSpecified(true);
00665             if (deepCopy)
00666             {
00667                 const Node * child = firstChild();
00668                 while (child)
00669                 {
00670                     attr->appendChild(child->cloneNode(true));
00671                     child = child->nextSibling();
00672                 }
00673             }
00674             return attr;
00675         }
00676 
00679         inline void setSpecified(const bool set) { }
00681         inline void setOwnerElement(const DOM::Element * elem) { element = elem; }
00682 
00683     public:    
00684         // Allow DOM element to clone us specifying us at the same time
00685         friend class DOM::Element;
00686         // Allow DOM document to import us
00687         friend class DOM::Document;
00688         // Allow DOM named node map to access us
00689         friend struct DOM::NamedNodeMap;
00690     };
00691 
00692 
00693 
00694 
00695 
00697     class Element : public Node
00698     {
00699         // Members
00700     private:
00702         HTML::Elements::Element * element;
00704         NamedNodeMap              attributeArray;
00705 
00706         // Our interface
00707     public:
00709         inline HTML::Elements::Element * getElement() const { return element; }
00711         inline void setElement(HTML::Elements::Element * newEl) { element = newEl; }
00713         friend Document;
00714 
00715 
00716         // The Node interface
00717     public:
00720         virtual DOMString nodeName() const                  { return tagName(); }
00723         virtual const NamedNodeMap * attributes() const     { return &attributeArray; }
00725         virtual Node * Clone(bool deepCopy) const throw();
00726         
00727         // The Element interface 
00728     public:    
00730         inline DOMString tagName() const;
00734         inline const Attr * getAttributeNode(const DOMString & name) const { return checkConv(attributeArray.getNamedItem(name)); }
00738         inline DOMString getAttribute(const DOMString & name) const { const Attr * attrib = getAttributeNode(name); if (!attrib) return DOMString(); return attrib->value(); }
00742         inline const Attr * setAttributeNode(const Attr * node) { if (node) const_cast<DOM::Attr*>(node)->setOwnerElement(this); return checkConv(attributeArray.setNamedItem(node)); }
00747         inline void setAttribute(const DOMString & name, const DOMString & value);
00751         inline void removeAttribute(const DOMString & name) { const Node * node = attributeArray.removeNamedItem(name); delete const_cast<Attr*>((const Attr*)node); }
00756         inline const Attr * removeAttributeNode(const Attr * node) { return checkConv(attributeArray.removeNamedItem(node->name())); }
00760         NodeList * getElementsByTagName(const DOMString & name) const throw();
00764         inline bool hasAttribute(const DOMString & name) const throw() { return getAttributeNode(name) != 0; }
00765 
00766         // Our interface 
00767     public:
00772         NodeList *      getChildrenByTag(const HTML::GenericElement::ElementID tag) const throw();
00776         const Element * getParentOfFirstChildOfType(const HTML::GenericElement::ElementID tag) const throw();
00780         const Element * getFirstParentOfType(const HTML::GenericElement::ElementID tag) const throw();
00781 
00782 
00783         // Allocator interface
00784     public:    
00787         virtual void returnToAllocator(const volatile HTML::Elements::Allocators::BaseAllocator * allocator);
00788 
00789     public:
00791         Element(HTML::Elements::Element * el) : Node(Node::NodeType::Element), element(el) {} 
00792 
00793         // Helpers
00794     private:
00796         inline const Attr * checkConv(const Node * attr) const { return attr && attr->nodeType == Node::NodeType::Attribute ? (const Attr*)attr : 0; }
00800         struct MatchElementByTag : public NodeList
00801         {
00803             DOMTree::Node root;
00805             const HTML::GenericElement::ElementID &   elementID; 
00807             int          continueSearching;
00808 
00810             int searchMethod(const DOM::Node * node);
00812             int removeDataLinks(const DOMTree::Node * node);
00813             
00815             MatchElementByTag(const HTML::GenericElement::ElementID & id, const int contSearch = 0) : elementID(id), root(0), NodeList(root), continueSearching(contSearch) { const_cast<uint32 &>(length) = 0; }
00817             ~MatchElementByTag() 
00818             {
00819                 // Before the list of node get destroyed, mutate the data to 0
00820                 // This is useless if using the default allocator that is not going to delete the NTree::Node's data
00821                 // But for any other allocator, we don't want it to delete data that might still be in use elsewhere
00822                 root.applyOnChildrenNode(*this, &MatchElementByTag::removeDataLinks, true);
00823             }
00824         };
00825     };
00826 
00827 
00828 
00830     class DocumentType : public Node 
00831     {
00832         // Our members
00833     private:
00835         DOMString              typeName;
00837         DOMString              publicID;
00839         DOMString              systemID;
00840 
00841 
00842         // The Node interface
00843     public:
00846         virtual DOMString nodeName() const                  { return name(); }
00847 
00848     public:
00851         inline const DOMString  &     name() const                 { return typeName; }
00854         inline const NamedNodeMap *   entities() const             { return 0; }
00857         inline const NamedNodeMap *   notations() const            { return 0; }
00860         inline const DOMString  &     publicId() const             { return publicID; }
00863         inline const DOMString  &     systemId() const             { return systemID; }
00866         inline const DOMString        internalSubset() const       { return DOMString(); }
00867 
00868         // Construction
00869     public:
00871         DocumentType(const DOMString & input) : Node(Node::NodeType::DocumentType), typeName(extractTypeNameFrom(input)), publicID(extractPublicIDFrom(input)), systemID(extractSystemIDFrom(input)) {}
00873         DocumentType(const DOMString & name, const DOMString & pubID, const DOMString & sysID) : Node(Node::NodeType::DocumentType), typeName(name), publicID(pubID), systemID(sysID) {}
00874 
00875         // Helpers method
00876     private:
00877         DOMString extractItemFrom(const DOMString & input, const tchar * NameToSearch) const
00878         {
00879             DOMString ret;
00880             Strings::FastString xString = Strings::convert(input);
00881             int pos = 0;
00882             while (pos < xString.getLength())
00883             {
00884                 Strings::FastString xItem = xString.extractToken(' ', pos);
00885                 if (xItem.caselessEqual(NameToSearch))
00886                 {
00887                     int startPos = pos;
00888                     if (pos == xString.getLength()) break;
00889                     if (xString[pos] != '"')
00890                     {
00891                         // Get the type name (in the next item)
00892                         xItem = xString.extractToken(' ', pos);
00893                     } else
00894                     {
00895                         // Get the type name (in the next item)
00896                         ++pos;
00897                         xItem = xString.extractToken('"', pos);
00898                     }
00899 
00900                     return DOMString(&input.getData()[startPos], pos - startPos - 1);
00901                 }
00902             }
00903             return DOMString();
00904 
00905         }
00906         
00907         inline DOMString extractTypeNameFrom(const DOMString & input) const { return extractItemFrom(input, "DOCTYPE"); }
00908         inline DOMString extractPublicIDFrom(const DOMString & input) const { return extractItemFrom(input, "PUBLIC"); }
00909 
00910         DOMString extractSystemIDFrom(const DOMString & input) const
00911         {
00912             DOMString ret = extractItemFrom(input, "SYSTEM");
00913             if (ret.getLength()) return ret;
00914             Strings::FastString xString = Strings::convert(input);
00915             int pos = 0;
00916             while (pos < xString.getLength())
00917             {
00918                 Strings::FastString xItem = xString.extractToken(' ', pos);
00919                 if (xItem.caselessEqual("PUBLIC"))
00920                 {
00921                     // Get the type name (in the next item)
00922                     // Ignore the public item
00923                     if (pos == xString.getLength()) break;
00924                     if (xString[pos] != '"')
00925                     {
00926                         // Get the type name (in the next item)
00927                         xItem = xString.extractToken(' ', pos);
00928                     } else
00929                     {
00930                         // Get the type name (in the next item)
00931                         ++pos;
00932                         xItem = xString.extractToken('"', pos);
00933                         ++pos;
00934                     }
00935 
00936                     int startPos = pos;
00937                     if (pos == xString.getLength()) break;
00938                     if (xString[pos] != '"') break;
00939                     ++pos; 
00940                     if (pos == xString.getLength()) break;
00941                     xItem = xString.extractToken('"', pos);
00942 
00943                     return DOMString(&input.getData()[startPos], pos - startPos - 1);
00944                 }
00945             }
00946             return DOMString();
00947         }
00948     };
00949 
00950 
00952     struct ProcessingInstruction {};
00954     struct DocumentFragment : public Node { DocumentFragment() : Node(NodeType::DocumentFragment) {}  };
00956     struct CDATASection : public Text {};
00958     struct EntityReference : public Node {};
00959     
00960     
00961     
00963     struct Comment : public CharacterData 
00964     {
00965         // The node interface 
00966     public:  
00969         virtual DOMString nodeName() const           { return DOMString("#comment"); }
00970 
00973         virtual Node * Clone(bool deepCopy) const throw() { Node * node = new Comment(data()); DOMTree::Node * tNode = new DOMTree::Node(node); node->setTreeNode(tNode); return node; }   
00974        
00975         // Construction and destruction
00976     public:
00977         Comment(const DOMString & data, DOMTree::Node * ref = 0) : CharacterData(NodeType::Comment, data, ref) {}
00978         Comment(const Strings::FastString & data, DOMTree::Node * ref = 0) : CharacterData(NodeType::Comment, data, ref) {}
00979     };
00980 
00981 
00983     class Document : public Node
00984     {
00985         // Members
00986     private:
00988         const DocumentType  *  documentType;
00990         const Element       *  element;
00992         const volatile HTML::Elements::Allocators::BaseAllocator *     allocator;
00993 
00994         // The Node interface
00995     public:
00998         virtual DOMString nodeName() const                  { return DOMString("#document"); }
00999 
01000         // The Document interface
01001     public:
01004         inline const DocumentType * const  doctype() const throw() { return documentType; }
01007         inline const DOMImplementation * const  implementation() const throw() { return &getCurrentDOMImplementation(allocator);}
01010         inline const Element * const            documentElement() const throw() { return element;}
01011 
01017         Element  *                      createElement(const DOMString & tagName) const;
01022         inline DocumentFragment *       createDocumentFragment() const                  { return 0; }
01026         Text *                          createTextNode(const DOMString &  data) const throw();
01030         Comment *                       createComment(const DOMString &  data) const throw();
01036         inline CDATASection *           createCDATASection(const DOMString &  data) const { throw Exceptions::NotSupported(); }
01043         inline ProcessingInstruction *  createProcessingInstruction(const DOMString & target, const DOMString & data) const { throw Exceptions::NotSupported(); }
01049         Attr *                          createAttribute(const DOMString &  name) const;
01056         inline EntityReference  *       createEntityReference(const DOMString &  name) const  { throw Exceptions::NotSupported(); }
01060         NodeList *                      getElementsByTagName(const DOMString &  tagName) const throw();
01067         const Node  *                   importNode(const Node * importedNode, bool deep);
01070         inline Element *                createElementNS(const DOMString &  namespaceURI, const DOMString &  qualifiedName) const { return 0; }
01073         inline Attr    *                createAttributeNS(const DOMString &  namespaceURI, const DOMString &  qualifiedName) const { return 0; }
01076         inline NodeList *               getElementsByTagNameNS(const DOMString &  namespaceURI, const DOMString &  localName) const { return 0; }
01080         const Element *                 getElementById(const DOMString &  elementId) const;  
01081 
01082         // Allocator interface
01083     public:    
01086         virtual void returnToAllocator(const volatile HTML::Elements::Allocators::BaseAllocator * allocator);
01087 
01088         // Construction and destruction
01089     public:
01091         Document(const DOMString & namespaceURI, const DOMString & qualifiedName, const DocumentType * docType, const volatile HTML::Elements::Allocators::BaseAllocator * _allocator, DOMTree::Node * ref = 0, const Element * htmlElement = 0) 
01092             : Node(NodeType::Document, ref), element(htmlElement), documentType(docType), allocator(_allocator) 
01093                                                                                                 { }
01094 
01098         inline bool setHTMLElement(const Element * htmlElement) { if (element || !htmlElement || htmlElement->tagName() != DOMString("HTML")) return false; element = htmlElement; element->setTreeNode(getTreeNode()); return true; }
01099 
01100     private:
01104         struct MatchElementByTag : public NodeList
01105         {
01107             DOMTree::Node root;
01109             const HTML::GenericElement::ElementID &   elementID; 
01110 
01112             int searchMethod(const DOM::Node * node);
01114             int removeDataLinks(const DOMTree::Node * node);
01115             
01117             MatchElementByTag(const HTML::GenericElement::ElementID & id) : elementID(id), root(0), NodeList(root) { const_cast<uint32 &>(length) = 0; }
01119             ~MatchElementByTag() 
01120             {
01121                 // Before the list of node get destroyed, mutate the data to 0
01122                 // This is useless if using the default allocator that is not going to delete the NTree::Node's data
01123                 // But for any other allocator, we don't want it to delete data that might still be in use elsewhere
01124                 root.applyOnChildrenNode(*this, &MatchElementByTag::removeDataLinks, true);
01125             }
01126         };
01127 
01131         struct MatchElementById : public NodeList
01132         {
01134             DOMTree::Node root;
01136             const DOMString & ID; 
01137 
01139             int searchMethod(const DOM::Node * node);
01141             int removeDataLinks(const DOMTree::Node * node);
01142             
01144             MatchElementById(const DOMString & id) : ID(id), root(0), NodeList(root) {}
01146             ~MatchElementById() 
01147             {
01148                 // Before the list of node get destroyed, mutate the data to 0
01149                 // This is useless if using the default allocator that is not going to delete the NTree::Node's data
01150                 // But for any other allocator, we don't want it to delete data that might still be in use elsewhere
01151                 root.applyOnChildrenNode(*this, &MatchElementById::removeDataLinks, true);
01152             }
01153         };
01154     };
01155 
01157     struct NodeDeleter : public Tree::DeleterObject<const DOM::Node *>
01158     {
01159         typedef Tree::NTree<const DOM::Node *> BaseTree;
01160         typedef BaseTree::Node Node;
01161 
01162         const volatile HTML::Elements::Allocators::BaseAllocator & allocatorRef;
01163         inline void deleteNode(Node * node) const;
01164 
01166         NodeDeleter(const volatile HTML::Elements::Allocators::BaseAllocator & _allocatorRef) : allocatorRef(_allocatorRef) {}
01167     };
01168 
01170     static NodeDeleter & getDefaultNodeDeleter(const volatile HTML::Elements::Allocators::BaseAllocator & allocator);
01171 
01172 }
01173 
01174 #endif

(C) An X-Ryl669 project 2007

This document describes Unlimited Zooming Interface source code. UZI stands for Unlimited Zooming Interface, and source code license is