michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */
michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0:
michael@0: /*
michael@0: * nsINodeInfo is an interface to node info, such as name, prefix, namespace
michael@0: * ID and possibly other data that is shared between nodes (elements
michael@0: * and attributes) that have the same name, prefix and namespace ID within
michael@0: * the same document.
michael@0: *
michael@0: * nsNodeInfoManager's are internal objects that manage a list of
michael@0: * nsINodeInfo's, every document object should hold a strong reference to
michael@0: * a nsNodeInfoManager and every nsINodeInfo also holds a strong reference
michael@0: * to their owning manager. When a nsINodeInfo is no longer used it will
michael@0: * automatically remove itself from its owner manager, and when all
michael@0: * nsINodeInfo's have been removed from a nsNodeInfoManager and all external
michael@0: * references are released the nsNodeInfoManager deletes itself.
michael@0: *
michael@0: * -- jst@netscape.com
michael@0: */
michael@0:
michael@0: #ifndef nsINodeInfo_h___
michael@0: #define nsINodeInfo_h___
michael@0:
michael@0: #include "nsCOMPtr.h" // for member
michael@0: #include "nsIAtom.h" // for member (in nsCOMPtr)
michael@0: #include "nsISupports.h" // for base class
michael@0: #include "nsNameSpaceManager.h" // for kNameSpaceID_*
michael@0:
michael@0: #ifdef MOZILLA_INTERNAL_API
michael@0: #include "nsDOMString.h"
michael@0: #endif
michael@0:
michael@0: class nsIDocument;
michael@0: class nsIURI;
michael@0: class nsIPrincipal;
michael@0: class nsNodeInfoManager;
michael@0:
michael@0: // IID for the nsINodeInfo interface
michael@0: #define NS_INODEINFO_IID \
michael@0: { 0xc5188ea1, 0x0a9c, 0x43e6, \
michael@0: { 0x95, 0x90, 0xcc, 0x43, 0x6b, 0xe9, 0xcf, 0xa0 } }
michael@0:
michael@0: class nsINodeInfo : public nsISupports
michael@0: {
michael@0: public:
michael@0: NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODEINFO_IID)
michael@0:
michael@0: nsINodeInfo()
michael@0: : mInner(nullptr, nullptr, kNameSpaceID_None, 0, nullptr)
michael@0: {
michael@0: }
michael@0:
michael@0: /*
michael@0: * Get the name from this node as a string, this does not include the prefix.
michael@0: *
michael@0: * For the HTML element "
" this will return "body" and for the XML
michael@0: * element "" this will return "body".
michael@0: */
michael@0: void GetName(nsAString& aName) const
michael@0: {
michael@0: mInner.mName->ToString(aName);
michael@0: }
michael@0:
michael@0: /*
michael@0: * Get the name from this node as an atom, this does not include the prefix.
michael@0: * This function never returns a null atom.
michael@0: *
michael@0: * For the HTML element "" this will return the "body" atom and for
michael@0: * the XML element "" this will return the "body" atom.
michael@0: */
michael@0: nsIAtom* NameAtom() const
michael@0: {
michael@0: return mInner.mName;
michael@0: }
michael@0:
michael@0: /*
michael@0: * Get the qualified name from this node as a string, the qualified name
michael@0: * includes the prefix, if one exists.
michael@0: *
michael@0: * For the HTML element "" this will return "body" and for the XML
michael@0: * element "" this will return "html:body".
michael@0: */
michael@0: const nsString& QualifiedName() const {
michael@0: return mQualifiedName;
michael@0: }
michael@0:
michael@0: /*
michael@0: * Returns the node's nodeName as defined in DOM Core
michael@0: */
michael@0: const nsString& NodeName() const {
michael@0: return mNodeName;
michael@0: }
michael@0:
michael@0: /*
michael@0: * Returns the node's localName as defined in DOM Core
michael@0: */
michael@0: const nsString& LocalName() const {
michael@0: return mLocalName;
michael@0: }
michael@0:
michael@0: #ifdef MOZILLA_INTERNAL_API
michael@0: /*
michael@0: * Get the prefix from this node as a string.
michael@0: *
michael@0: * For the HTML element "" this will return a null string and for
michael@0: * the XML element "" this will return the string "html".
michael@0: */
michael@0: void GetPrefix(nsAString& aPrefix) const
michael@0: {
michael@0: if (mInner.mPrefix) {
michael@0: mInner.mPrefix->ToString(aPrefix);
michael@0: } else {
michael@0: SetDOMStringToNull(aPrefix);
michael@0: }
michael@0: }
michael@0: #endif
michael@0:
michael@0: /*
michael@0: * Get the prefix from this node as an atom.
michael@0: *
michael@0: * For the HTML element "" this will return a null atom and for
michael@0: * the XML element "" this will return the "html" atom.
michael@0: */
michael@0: nsIAtom* GetPrefixAtom() const
michael@0: {
michael@0: return mInner.mPrefix;
michael@0: }
michael@0:
michael@0: /*
michael@0: * Get the namespace URI for a node, if the node has a namespace URI.
michael@0: */
michael@0: virtual void GetNamespaceURI(nsAString& aNameSpaceURI) const = 0;
michael@0:
michael@0: /*
michael@0: * Get the namespace ID for a node if the node has a namespace, if not this
michael@0: * returns kNameSpaceID_None.
michael@0: */
michael@0: int32_t NamespaceID() const
michael@0: {
michael@0: return mInner.mNamespaceID;
michael@0: }
michael@0:
michael@0: /*
michael@0: * Get the nodetype for the node. Returns the values specified in nsIDOMNode
michael@0: * for nsIDOMNode.nodeType
michael@0: */
michael@0: uint16_t NodeType() const
michael@0: {
michael@0: return mInner.mNodeType;
michael@0: }
michael@0:
michael@0: /*
michael@0: * Get the extra name, used by PIs and DocTypes, for the node.
michael@0: */
michael@0: nsIAtom* GetExtraName() const
michael@0: {
michael@0: return mInner.mExtraName;
michael@0: }
michael@0:
michael@0: /*
michael@0: * Get and set the ID attribute atom for this node.
michael@0: * See http://www.w3.org/TR/1998/REC-xml-19980210#sec-attribute-types
michael@0: * for the definition of an ID attribute.
michael@0: *
michael@0: */
michael@0: nsIAtom* GetIDAttributeAtom() const
michael@0: {
michael@0: return mIDAttributeAtom;
michael@0: }
michael@0:
michael@0: void SetIDAttributeAtom(nsIAtom* aID)
michael@0: {
michael@0: mIDAttributeAtom = aID;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Get the owning node info manager. Only to be used inside Gecko, you can't
michael@0: * really do anything with the pointer outside Gecko anyway.
michael@0: */
michael@0: nsNodeInfoManager *NodeInfoManager() const
michael@0: {
michael@0: return mOwnerManager;
michael@0: }
michael@0:
michael@0: /*
michael@0: * Utility functions that can be used to check if a nodeinfo holds a specific
michael@0: * name, name and prefix, name and prefix and namespace ID, or just
michael@0: * namespace ID.
michael@0: */
michael@0: bool Equals(nsINodeInfo *aNodeInfo) const
michael@0: {
michael@0: return aNodeInfo == this || aNodeInfo->Equals(mInner.mName, mInner.mPrefix,
michael@0: mInner.mNamespaceID);
michael@0: }
michael@0:
michael@0: bool NameAndNamespaceEquals(nsINodeInfo *aNodeInfo) const
michael@0: {
michael@0: return aNodeInfo == this || aNodeInfo->Equals(mInner.mName,
michael@0: mInner.mNamespaceID);
michael@0: }
michael@0:
michael@0: bool Equals(nsIAtom *aNameAtom) const
michael@0: {
michael@0: return mInner.mName == aNameAtom;
michael@0: }
michael@0:
michael@0: bool Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom) const
michael@0: {
michael@0: return (mInner.mName == aNameAtom) && (mInner.mPrefix == aPrefixAtom);
michael@0: }
michael@0:
michael@0: bool Equals(nsIAtom *aNameAtom, int32_t aNamespaceID) const
michael@0: {
michael@0: return ((mInner.mName == aNameAtom) &&
michael@0: (mInner.mNamespaceID == aNamespaceID));
michael@0: }
michael@0:
michael@0: bool Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom,
michael@0: int32_t aNamespaceID) const
michael@0: {
michael@0: return ((mInner.mName == aNameAtom) &&
michael@0: (mInner.mPrefix == aPrefixAtom) &&
michael@0: (mInner.mNamespaceID == aNamespaceID));
michael@0: }
michael@0:
michael@0: bool NamespaceEquals(int32_t aNamespaceID) const
michael@0: {
michael@0: return mInner.mNamespaceID == aNamespaceID;
michael@0: }
michael@0:
michael@0: bool Equals(const nsAString& aName) const
michael@0: {
michael@0: return mInner.mName->Equals(aName);
michael@0: }
michael@0:
michael@0: bool Equals(const nsAString& aName, const nsAString& aPrefix) const
michael@0: {
michael@0: return mInner.mName->Equals(aName) &&
michael@0: (mInner.mPrefix ? mInner.mPrefix->Equals(aPrefix) : aPrefix.IsEmpty());
michael@0: }
michael@0:
michael@0: bool Equals(const nsAString& aName, int32_t aNamespaceID) const
michael@0: {
michael@0: return mInner.mNamespaceID == aNamespaceID &&
michael@0: mInner.mName->Equals(aName);
michael@0: }
michael@0:
michael@0: bool Equals(const nsAString& aName, const nsAString& aPrefix,
michael@0: int32_t aNamespaceID) const
michael@0: {
michael@0: return mInner.mName->Equals(aName) && mInner.mNamespaceID == aNamespaceID &&
michael@0: (mInner.mPrefix ? mInner.mPrefix->Equals(aPrefix) : aPrefix.IsEmpty());
michael@0: }
michael@0:
michael@0: virtual bool NamespaceEquals(const nsAString& aNamespaceURI) const = 0;
michael@0:
michael@0: bool QualifiedNameEquals(nsIAtom* aNameAtom) const
michael@0: {
michael@0: NS_PRECONDITION(aNameAtom, "Must have name atom");
michael@0: if (!GetPrefixAtom())
michael@0: return Equals(aNameAtom);
michael@0:
michael@0: return aNameAtom->Equals(mQualifiedName);
michael@0: }
michael@0:
michael@0: bool QualifiedNameEquals(const nsAString& aQualifiedName) const
michael@0: {
michael@0: return mQualifiedName == aQualifiedName;
michael@0: }
michael@0:
michael@0: /*
michael@0: * Retrieve a pointer to the document that owns this node info.
michael@0: */
michael@0: nsIDocument* GetDocument() const
michael@0: {
michael@0: return mDocument;
michael@0: }
michael@0:
michael@0: protected:
michael@0: /*
michael@0: * nsNodeInfoInner is used for two things:
michael@0: *
michael@0: * 1. as a member in nsNodeInfo for holding the name, prefix and
michael@0: * namespace ID
michael@0: * 2. as the hash key in the hash table in nsNodeInfoManager
michael@0: *
michael@0: * nsNodeInfoInner does not do any kind of reference counting,
michael@0: * that's up to the user of this class. Since nsNodeInfoInner is
michael@0: * typically used as a member of nsNodeInfo, the hash table doesn't
michael@0: * need to delete the keys. When the value (nsNodeInfo) is deleted
michael@0: * the key is automatically deleted.
michael@0: */
michael@0:
michael@0: class nsNodeInfoInner
michael@0: {
michael@0: public:
michael@0: nsNodeInfoInner()
michael@0: : mName(nullptr), mPrefix(nullptr), mNamespaceID(kNameSpaceID_Unknown),
michael@0: mNodeType(0), mNameString(nullptr), mExtraName(nullptr)
michael@0: {
michael@0: }
michael@0: nsNodeInfoInner(nsIAtom *aName, nsIAtom *aPrefix, int32_t aNamespaceID,
michael@0: uint16_t aNodeType, nsIAtom* aExtraName)
michael@0: : mName(aName), mPrefix(aPrefix), mNamespaceID(aNamespaceID),
michael@0: mNodeType(aNodeType), mNameString(nullptr), mExtraName(aExtraName)
michael@0: {
michael@0: }
michael@0: nsNodeInfoInner(const nsAString& aTmpName, nsIAtom *aPrefix,
michael@0: int32_t aNamespaceID, uint16_t aNodeType)
michael@0: : mName(nullptr), mPrefix(aPrefix), mNamespaceID(aNamespaceID),
michael@0: mNodeType(aNodeType), mNameString(&aTmpName), mExtraName(nullptr)
michael@0: {
michael@0: }
michael@0:
michael@0: nsIAtom* mName;
michael@0: nsIAtom* mPrefix;
michael@0: int32_t mNamespaceID;
michael@0: uint16_t mNodeType; // As defined by nsIDOMNode.nodeType
michael@0: const nsAString* mNameString;
michael@0: nsIAtom* mExtraName; // Only used by PIs and DocTypes
michael@0: };
michael@0:
michael@0: // nsNodeInfoManager needs to pass mInner to the hash table.
michael@0: friend class nsNodeInfoManager;
michael@0:
michael@0: nsIDocument* mDocument; // Weak. Cache of mOwnerManager->mDocument
michael@0:
michael@0: nsNodeInfoInner mInner;
michael@0:
michael@0: nsCOMPtr mIDAttributeAtom;
michael@0: nsRefPtr mOwnerManager;
michael@0:
michael@0: /*
michael@0: * Members for various functions of mName+mPrefix that we can be
michael@0: * asked to compute.
michael@0: */
michael@0:
michael@0: // Qualified name
michael@0: nsString mQualifiedName;
michael@0:
michael@0: // nodeName for the node.
michael@0: nsString mNodeName;
michael@0:
michael@0: // localName for the node. This is either equal to mInner.mName, or a
michael@0: // void string, depending on mInner.mNodeType.
michael@0: nsString mLocalName;
michael@0: };
michael@0:
michael@0: NS_DEFINE_STATIC_IID_ACCESSOR(nsINodeInfo, NS_INODEINFO_IID)
michael@0:
michael@0: #endif /* nsINodeInfo_h___ */