Checking in new files for (the not yet checked in) shared node info code. Not part of the build yet. r=buster@netscape.com

This commit is contained in:
jst%netscape.com 2000-05-08 14:29:44 +00:00
Родитель 0e7b35b9e4
Коммит c855b6a512
10 изменённых файлов: 1952 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,209 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* nsINodeInfo is an interface to node info, such as name, prefix, namespace
* ID and possibly other data that is shared shared between nodes (elements
* and attributes) that have the same name, prefix and namespace ID within
* the same document.
*
* nsINodeInfoManager is an interface to an object that manages a list of
* nsINodeInfo's, every document object should hold a strong reference to
* a nsINodeInfoManager and every nsINodeInfo also holds a string reference
* to their owning manager. When a nsINodeInfo is no longer used it will
* automatically remove itself from its owner manager, and when all
* nsINodeInfo's have been removed from a nsINodeInfoManager and all external
* references are released the nsINodeInfoManager deletes itself.
*
* -- jst@netscape.com
*/
#ifndef nsINodeInfo_h___
#define nsINodeInfo_h___
#include "nsISupports.h"
// Forward declarations
class nsIAtom;
class nsINodeInfoManager;
class nsINameSpaceManager;
class nsString;
// IID for the nsINodeInfo interface
#define NS_INODEINFO_IID \
{ 0x93dbfd8c, 0x2fb3, 0x4ef5, \
{0xa2, 0xa0, 0xcf, 0xf2, 0x69, 0x6f, 0x07, 0x88} }
// IID for the nsINodeInfoManager interface
#define NS_INODEINFOMANAGER_IID \
{ 0xb622469b, 0x4dcf, 0x45c4, \
{0xb0, 0xb9, 0xa7, 0x32, 0xbc, 0xee, 0xa5, 0xcc} }
#define NS_NODEINFOMANAGER_PROGID "component://netscape/layout/nodeinfomanager"
class nsINodeInfo : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_INODEINFO_IID)
/*
* Get the name from this node as a string, this does not include the prefix.
*
* For the HTML element "<body>" this will return "body" and for the XML
* element "<html:body>" this will return "body".
*/
NS_IMETHOD GetName(nsString& aName) = 0;
/*
* Get the name from this node as an atom, this does not include the prefix.
* This function never returns a null atom.
*
* For the HTML element "<body>" this will return the "body" atom and for
* the XML element "<html:body>" this will return the "body" atom.
*/
NS_IMETHOD GetNameAtom(nsIAtom*& aAtom) = 0;
/*
* Get the qualified name from this node as a string, the qualified name
* includes the prefix, if one exists.
*
* For the HTML element "<body>" this will return "body" and for the XML
* element "<html:body>" this will return "html:body".
*/
NS_IMETHOD GetQualifiedName(nsString& aQualifiedName) = 0;
/*
* Get the local name from this node as a string, GetLocalName() gets the
* same string as GetName() but only if the node has a prefix and/or a
* namespace URI. If the node has neither a prefix nor a namespace URI the
* local name is a null string.
*
* For the HTML element "<body>" in a HTML document this will return a null
* string and for the XML element "<html:body>" this will return "body".
*/
NS_IMETHOD GetLocalName(nsString& aLocalName) = 0;
/*
* Get the prefix from this node as a string.
*
* For the HTML element "<body>" this will return a null string and for
* the XML element "<html:body>" this will return the string "html".
*/
NS_IMETHOD GetPrefix(nsString& aPrefix) = 0;
/*
* Get the prefix from this node as an atom.
*
* For the HTML element "<body>" this will return a null atom and for
* the XML element "<html:body>" this will return the "html" atom.
*/
NS_IMETHOD GetPrefixAtom(nsIAtom*& aAtom) = 0;
/*
* Get the namespace URI for a node, if the node has a namespace URI.
*
* For the HTML element "<body>" in a HTML document this will return a null
* string and for the XML element "<html:body>" (assuming that this element,
* or one of it's ancestors has an
* xmlns:html='http://www.w3.org/TR/REC-html40' attribute) this will return
* the string "http://www.w3.org/TR/REC-html40".
*/
NS_IMETHOD GetNamespaceURI(nsString& aNameSpaceURI) = 0;
/*
* Get the namespace ID for a node if the node has a namespace, if not this
* returns kNameSpaceID_None.
*
* For the HTML element "<body>" in a HTML document this will return
* kNameSpaceID_None and for the XML element "<html:body>" (assuming that
* this element, or one of it's ancestors has an
* xmlns:html='http://www.w3.org/TR/REC-html40' attribute) this will return
* the namespace ID for "http://www.w3.org/TR/REC-html40".
*/
NS_IMETHOD GetNamespaceID(PRInt32& aResult) = 0;
/*
* Get the owning node info manager, this will never return null.
*/
NS_IMETHOD GetNodeInfoManager(nsINodeInfoManager*& aNodeInfoManager) = 0;
/*
* Utility functions that can be used to check if a nodeinfo holds a spcific
* name, name and prefix, name and prefix and namespace ID, or just
* namespace ID.
*/
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom) = 0;
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom) = 0;
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, PRInt32 aNamespaceID) = 0;
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom,
PRInt32 aNamespaceID) = 0;
NS_IMETHOD_(PRBool) NamespaceEquals(PRInt32 aNamespaceID) = 0;
/*
* This is a convinience method that creates a new nsINodeInfo that differs
* only by name from the one this is called on.
*/
NS_IMETHOD NameChanged(nsIAtom *aName, nsINodeInfo*& aResult) = 0;
/*
* This is a convinience method that creates a new nsINodeInfo that differs
* only by prefix from the one this is called on.
*/
NS_IMETHOD PrefixChanged(nsIAtom *aPrefix, nsINodeInfo*& aResult) = 0;
};
class nsINodeInfoManager : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_INODEINFOMANAGER_IID)
/*
* Initialize the nodeinfo manager with a namespace manager, this should
* allways be done.
*/
NS_IMETHOD Init(nsINameSpaceManager *aNameSpaceManager) = 0;
/*
* Methods for creating nodeinfo's from atoms and/or strings.
*/
NS_IMETHOD GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo) = 0;
NS_IMETHOD GetNodeInfo(const nsString& aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo) = 0;
NS_IMETHOD GetNodeInfo(const nsString& aName, const nsString& aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo) = 0;
NS_IMETHOD GetNodeInfo(const nsString& aName, const nsString& aPrefix,
const nsString& aNamespaceURI,
nsINodeInfo*& aNodeInfo) = 0;
/*
* Getter for the namespace manager used by this nodeinfo manager.
*/
NS_IMETHOD GetNamespaceManager(nsINameSpaceManager*& aNameSpaceManager) = 0;
};
extern nsresult NS_NewNodeInfoManager(nsINodeInfoManager** aResult);
#endif /* nsINodeInfo_h___ */

Просмотреть файл

@ -0,0 +1,307 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsNodeInfo.h"
#include "nsNodeInfoManager.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIAtom.h"
#include "nsINameSpaceManager.h"
nsNodeInfo::nsNodeInfo()
: mInner(), mOwnerManager(nsnull)
{
NS_INIT_REFCNT();
}
nsNodeInfo::~nsNodeInfo()
{
if (mOwnerManager) {
mOwnerManager->RemoveNodeInfo(this);
NS_RELEASE(mOwnerManager);
}
NS_IF_RELEASE(mInner.mName);
NS_IF_RELEASE(mInner.mPrefix);
}
nsresult
nsNodeInfo::Init(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
nsNodeInfoManager *aOwnerManager)
{
NS_ENSURE_TRUE(!mInner.mName && !mInner.mPrefix && !mOwnerManager,
NS_ERROR_ALREADY_INITIALIZED);
NS_ENSURE_ARG_POINTER(aName);
NS_ENSURE_ARG_POINTER(aOwnerManager);
mInner.mName = aName;
NS_ADDREF(mInner.mName);
mInner.mPrefix = aPrefix;
NS_IF_ADDREF(mInner.mPrefix);
mInner.mNamespaceID = aNamespaceID;
mOwnerManager = aOwnerManager;
NS_ADDREF(mOwnerManager);
return NS_OK;
}
// nsISupports
NS_IMPL_THREADSAFE_ISUPPORTS(nsNodeInfo, NS_GET_IID(nsINodeInfo));
// nsINodeInfo
NS_IMETHODIMP
nsNodeInfo::GetName(nsString& aName)
{
NS_ENSURE_TRUE(mInner.mName, NS_ERROR_NOT_INITIALIZED);
return mInner.mName->ToString(aName);
}
NS_IMETHODIMP
nsNodeInfo::GetNameAtom(nsIAtom*& aAtom)
{
NS_ABORT_IF_FALSE(mInner.mName, "nsNodeInfo not initialized!");
aAtom = mInner.mName;
NS_IF_ADDREF(aAtom);
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetQualifiedName(nsString& aQualifiedName)
{
NS_ENSURE_TRUE(mInner.mName, NS_ERROR_NOT_INITIALIZED);
#ifdef MOZILLA_IS_READY_FOR_THIS
if (mInner.mPrefix) {
mInner.mPrefix->ToString(aQualifiedName);
aQualifiedName.Append(':');
}
nsAutoString tmp;
mInner.mName->ToString(tmp);
aQualifiedName.Append(tmp);
#else
mInner.mName->ToString(aQualifiedName);
#endif
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetLocalName(nsString& aLocalName)
{
NS_ENSURE_TRUE(mInner.mName, NS_ERROR_NOT_INITIALIZED);
if (mInner.mNamespaceID > 0) {
return mInner.mName->ToString(aLocalName);
}
aLocalName.Truncate();
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetPrefix(nsString& aPrefix)
{
if (mInner.mPrefix) {
mInner.mPrefix->ToString(aPrefix);
} else {
aPrefix.Truncate();
}
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetPrefixAtom(nsIAtom*& aAtom)
{
aAtom = mInner.mPrefix;
NS_IF_ADDREF(aAtom);
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetNamespaceURI(nsString& aNameSpaceURI)
{
NS_ENSURE_TRUE(mOwnerManager, NS_ERROR_NOT_INITIALIZED);
nsresult rv = NS_OK;
if (mInner.mNamespaceID > 0) {
nsCOMPtr<nsINameSpaceManager> nsm;
mOwnerManager->GetNamespaceManager(*getter_AddRefs(nsm));
NS_ENSURE_TRUE(nsm, NS_ERROR_NOT_INITIALIZED);
rv = nsm->GetNameSpaceURI(mInner.mNamespaceID, aNameSpaceURI);
} else {
aNameSpaceURI.Truncate();
}
return rv;
}
NS_IMETHODIMP
nsNodeInfo::GetNamespaceID(PRInt32& aResult)
{
aResult = mInner.mNamespaceID;
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetNodeInfoManager(nsINodeInfoManager*& aNodeInfoManager)
{
NS_ENSURE_TRUE(mOwnerManager, NS_ERROR_NOT_INITIALIZED);
aNodeInfoManager = mOwnerManager;
NS_ADDREF(aNodeInfoManager);
return NS_OK;
}
NS_IMETHODIMP_(PRBool)
nsNodeInfo::Equals(nsIAtom *aNameAtom)
{
return mInner.mName == aNameAtom;
}
NS_IMETHODIMP_(PRBool)
nsNodeInfo::Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom)
{
return (mInner.mName == aNameAtom) && (mInner.mPrefix == aPrefixAtom);
}
NS_IMETHODIMP_(PRBool)
nsNodeInfo::Equals(nsIAtom *aNameAtom, PRInt32 aNamespaceID)
{
return (mInner.mName == aNameAtom) && (mInner.mNamespaceID == aNamespaceID);
}
NS_IMETHODIMP_(PRBool)
nsNodeInfo::Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom,
PRInt32 aNamespaceID)
{
return (mInner.mName == aNameAtom) &&
(mInner.mPrefix == aPrefixAtom) &&
(mInner.mNamespaceID == aNamespaceID);
}
NS_IMETHODIMP_(PRBool)
nsNodeInfo::NamespaceEquals(PRInt32 aNamespaceID)
{
return mInner.mNamespaceID == aNamespaceID;
}
NS_IMETHODIMP
nsNodeInfo::NameChanged(nsIAtom *aName, nsINodeInfo*& aResult)
{
NS_ENSURE_TRUE(mOwnerManager, NS_ERROR_NOT_INITIALIZED);
return mOwnerManager->GetNodeInfo(aName, mInner.mPrefix, mInner.mNamespaceID,
aResult);
}
NS_IMETHODIMP
nsNodeInfo::PrefixChanged(nsIAtom *aPrefix, nsINodeInfo*& aResult)
{
NS_ENSURE_TRUE(mOwnerManager, NS_ERROR_NOT_INITIALIZED);
return mOwnerManager->GetNodeInfo(mInner.mName, aPrefix, mInner.mNamespaceID,
aResult);
}
PLHashNumber
nsNodeInfoInner::GetHashValue(const void *key)
{
#ifdef NS_DEBUG // Just to shut down a compiler warning
NS_WARN_IF_FALSE(key, "Null key passed to nsNodeInfo::GetHashValue!");
#endif
if (key) {
const nsNodeInfoInner *node = (const nsNodeInfoInner *)key;
// Is this an acceptable has value?
return (((PLHashNumber)node->mName) & 0xffff) >> 8;
}
return 0;
}
PRIntn
nsNodeInfoInner::KeyCompare(const void *key1, const void *key2)
{
#ifdef NS_DEBUG // Just to shut down a compiler warning
NS_WARN_IF_FALSE(key1 && key2, "Null key passed to nsNodeInfo::KeyCompare!");
#endif
if (!key1 || !key2) {
return PR_FALSE;
}
const nsNodeInfoInner *node1 = (const nsNodeInfoInner *)key1;
const nsNodeInfoInner *node2 = (const nsNodeInfoInner *)key2;
if (node1->mName == node2->mName &&
node1->mPrefix == node2->mPrefix &&
node1->mNamespaceID == node2->mNamespaceID) {
return PR_TRUE;
}
return PR_FALSE;
}

Просмотреть файл

@ -0,0 +1,108 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsNodeInfo_h___
#define nsNodeInfo_h___
#include "nsINodeInfo.h"
#include "nsINameSpaceManager.h"
#include "plhash.h"
/*
* nsNodeInfoInner is used for two things:
*
* 1. as a member in nsNodeInfo for holding the name, prefix and
* namespace ID
* 2. as the hash key in the hash table in nsNodeInfoManager
*
* nsNodeInfoInner does not do any kind of reference counting, that's up
* to the user of this class, since nsNodeInfoInner is a member of
* nsNodeInfo the hash table doesn't need to delete the keys, when the
* value (nsNodeInfo) the key is automatically deleted.
*/
struct nsNodeInfoInner
{
nsNodeInfoInner(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID)
: mName(aName), mPrefix(aPrefix), mNamespaceID(aNamespaceID) {}
nsNodeInfoInner()
: mName(nsnull), mPrefix(nsnull), mNamespaceID(kNameSpaceID_None) {}
static PR_CALLBACK PRIntn KeyCompare(const void *key1, const void *key2);
static PR_CALLBACK PLHashNumber GetHashValue(const void *key);
nsIAtom* mName;
nsIAtom* mPrefix;
PRInt32 mNamespaceID;
};
class nsNodeInfoManager;
class nsNodeInfo : public nsINodeInfo
{
public:
NS_DECL_ISUPPORTS
// nsINodeInfo
NS_IMETHOD GetName(nsString& aName);
NS_IMETHOD GetNameAtom(nsIAtom*& aAtom);
NS_IMETHOD GetQualifiedName(nsString& aQualifiedName);
NS_IMETHOD GetLocalName(nsString& aLocalName);
NS_IMETHOD GetPrefix(nsString& aPrefix);
NS_IMETHOD GetPrefixAtom(nsIAtom*& aAtom);
NS_IMETHOD GetNamespaceURI(nsString& aNameSpaceURI);
NS_IMETHOD GetNamespaceID(PRInt32& aResult);
NS_IMETHOD GetNodeInfoManager(nsINodeInfoManager*& aNodeInfoManager);
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom);
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom);
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, PRInt32 aNamespaceID);
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom,
PRInt32 aNamespaceID);
NS_IMETHOD_(PRBool) NamespaceEquals(PRInt32 aNamespaceID);
NS_IMETHOD NameChanged(nsIAtom *aName, nsINodeInfo*& aResult);
NS_IMETHOD PrefixChanged(nsIAtom *aPrefix, nsINodeInfo*& aResult);
// nsNodeInfo
nsNodeInfo();
virtual ~nsNodeInfo();
/*
* Note! Init() must be called exactly once on every nsNodeInfo before
* the object is used, if Init() returns an error code the nsNodeInfo
* should not be used.
*
* aName and aOwnerManager may not be null.
*/
nsresult Init(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
nsNodeInfoManager *aOwnerManager);
protected:
friend class nsNodeInfoManager; // The NodeInfoManager needs to pass this
// to the hash table.
nsNodeInfoInner mInner;
nsNodeInfoManager* mOwnerManager; // Strong reference!
};
#endif /* nsNodeInfo_h___ */

Просмотреть файл

@ -0,0 +1,272 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsNodeInfoManager.h"
#include "nsNodeInfo.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIAtom.h"
nsNodeInfoManager* nsNodeInfoManager::gAnonymousNodeInfoManager = nsnull;
PRUint32 nsNodeInfoManager::gNodeManagerCount = 0;
nsresult NS_NewNodeInfoManager(nsINodeInfoManager** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = new nsNodeInfoManager;
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult);
return NS_OK;
}
nsNodeInfoManager::nsNodeInfoManager()
: mNameSpaceManager(nsnull)
{
NS_INIT_REFCNT();
if (gNodeManagerCount == 1 && gAnonymousNodeInfoManager) {
/*
* If we get here the global nodeinfo manager was the first one created,
* in that case we're not holding a strong reference to the global nodeinfo
* manager. Now we're creating one more nodeinfo manager so we'll grab
* a strong reference to the global nodeinfo manager so that it's
* lifetime will be longer than the lifetime of the other node managers.
*/
NS_ADDREF(gAnonymousNodeInfoManager);
}
gNodeManagerCount++;
mNodeInfoHash = PL_NewHashTable(32, nsNodeInfoInner::GetHashValue,
nsNodeInfoInner::KeyCompare,
PL_CompareValues, nsnull, nsnull);
#ifdef DEBUG_jst
printf ("Creating NodeInfoManager, gcount = %d\n", gNodeManagerCount);
#endif
}
nsNodeInfoManager::~nsNodeInfoManager()
{
gNodeManagerCount--;
if (gNodeManagerCount == 1 && gAnonymousNodeInfoManager) {
NS_RELEASE(gAnonymousNodeInfoManager);
} else if (!gNodeManagerCount) {
/*
* Here we just make sure that we don't leave a dangling pointer to
* the global nodeinfo manager after it's deleted.
*/
gAnonymousNodeInfoManager = nsnull;
}
if (mNodeInfoHash)
PL_HashTableDestroy(mNodeInfoHash);
#ifdef DEBUG_jst
printf ("Removing NodeInfoManager, gcount = %d\n", gNodeManagerCount);
#endif
}
NS_IMPL_THREADSAFE_ISUPPORTS(nsNodeInfoManager,
NS_GET_IID(nsINodeInfoManager));
// nsINodeInfoManager
NS_IMETHODIMP
nsNodeInfoManager::Init(nsINameSpaceManager *aNameSpaceManager)
{
NS_ENSURE_ARG_POINTER(aNameSpaceManager);
NS_ENSURE_TRUE(mNodeInfoHash, NS_ERROR_OUT_OF_MEMORY);
mNameSpaceManager = aNameSpaceManager;
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo)
{
NS_ENSURE_ARG_POINTER(aName);
nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID);
void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
if (node) {
aNodeInfo = NS_STATIC_CAST(nsINodeInfo *, node);
NS_ADDREF(aNodeInfo);
return NS_OK;
}
nsNodeInfo *newNodeInfo = new nsNodeInfo();
NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(newNodeInfo);
nsresult rv = newNodeInfo->Init(aName, aPrefix, aNamespaceID, this);
NS_ENSURE_SUCCESS(rv, rv);
PLHashEntry *he;
he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
NS_ENSURE_TRUE(he, NS_ERROR_OUT_OF_MEMORY);
aNodeInfo = newNodeInfo;
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfoManager::GetNodeInfo(const nsString& aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo)
{
NS_ENSURE_ARG(aName.Length());
nsCOMPtr<nsIAtom> name(dont_AddRef(NS_NewAtom(aName)));
NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
return GetNodeInfo(name, aPrefix, aNamespaceID, aNodeInfo);
}
NS_IMETHODIMP
nsNodeInfoManager::GetNodeInfo(const nsString& aName, const nsString& aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo)
{
NS_ENSURE_ARG(aName.Length());
nsCOMPtr<nsIAtom> name(dont_AddRef(NS_NewAtom(aName)));
NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIAtom> prefix;
if (aPrefix.Length()) {
prefix = dont_AddRef(NS_NewAtom(aPrefix));
NS_ENSURE_TRUE(prefix, NS_ERROR_OUT_OF_MEMORY);
}
return GetNodeInfo(name, prefix, aNamespaceID, aNodeInfo);
}
NS_IMETHODIMP
nsNodeInfoManager::GetNodeInfo(const nsString& aName, const nsString& aPrefix,
const nsString& aNamespaceURI,
nsINodeInfo*& aNodeInfo)
{
NS_ENSURE_ARG(aName.Length());
nsCOMPtr<nsIAtom> name(dont_AddRef(NS_NewAtom(aName)));
NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIAtom> prefix;
if (aPrefix.Length()) {
prefix = dont_AddRef(NS_NewAtom(aPrefix));
NS_ENSURE_TRUE(prefix, NS_ERROR_OUT_OF_MEMORY);
}
PRInt32 nsid = kNameSpaceID_None;
if (aNamespaceURI.Length()) {
if (!mNameSpaceManager) {
return NS_ERROR_NOT_INITIALIZED;
}
mNameSpaceManager->GetNameSpaceID(aNamespaceURI, nsid);
}
return GetNodeInfo(name, prefix, nsid, aNodeInfo);
}
NS_IMETHODIMP
nsNodeInfoManager::GetNamespaceManager(nsINameSpaceManager*& aNameSpaceManager)
{
aNameSpaceManager = mNameSpaceManager;
NS_IF_ADDREF(aNameSpaceManager);
return NS_OK;
}
void
nsNodeInfoManager::RemoveNodeInfo(nsNodeInfo *aNodeInfo)
{
NS_WARN_IF_FALSE(aNodeInfo, "Trying to remove null nodeinfo from manager!");
if (aNodeInfo) {
PRBool ret = PL_HashTableRemove(mNodeInfoHash, aNodeInfo);
NS_WARN_IF_FALSE(!ret, "Can't find nsINodeInfo to remove!!!");
}
}
nsresult
nsNodeInfoManager::GetAnonymousManager(nsINodeInfoManager*& aNodeInfoManager)
{
if (!gAnonymousNodeInfoManager) {
gAnonymousNodeInfoManager = new nsNodeInfoManager;
if (!gAnonymousNodeInfoManager)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(gAnonymousNodeInfoManager);
nsresult rv = NS_NewNameSpaceManager(getter_AddRefs(gAnonymousNodeInfoManager->mNameSpaceManager));
if (NS_FAILED(rv)) {
NS_RELEASE(gAnonymousNodeInfoManager);
return rv;
}
}
aNodeInfoManager = gAnonymousNodeInfoManager;
/*
* If the only nodeinfo manager is the global one we don't hold a ref
* since the global nodeinfo manager should be destroyed when it's released,
* even if it's the last one arround.
*/
if (gNodeManagerCount > 1) {
NS_ADDREF(aNodeInfoManager);
}
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsNodeInfoManager_h___
#define nsNodeInfoManager_h___
#include "nsINodeInfo.h"
#include "nsINameSpaceManager.h"
#include "nsCOMPtr.h"
#include "plhash.h"
class nsNodeInfo;
class nsNodeInfoManager : public nsINodeInfoManager
{
public:
NS_DECL_ISUPPORTS
// nsINodeInfoManager
NS_IMETHOD Init(nsINameSpaceManager *aNameSpaceManager);
NS_IMETHOD GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo);
NS_IMETHOD GetNodeInfo(const nsString& aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo);
NS_IMETHOD GetNodeInfo(const nsString& aName, const nsString& aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo);
NS_IMETHOD GetNodeInfo(const nsString& aName, const nsString& aPrefix,
const nsString& aNamespaceURI,
nsINodeInfo*& aNodeInfo);
NS_IMETHOD GetNamespaceManager(nsINameSpaceManager*& aNameSpaceManager);
// nsNodeInfoManager
nsNodeInfoManager();
virtual ~nsNodeInfoManager();
void RemoveNodeInfo(nsNodeInfo *aNodeInfo);
static nsresult GetAnonymousManager(nsINodeInfoManager*& aNodeInfoManager);
private:
PLHashTable *mNodeInfoHash;
nsCOMPtr<nsINameSpaceManager> mNameSpaceManager;
/*
* gAnonymousNodeInfoManager is a global nodeinfo manager used for nodes
* that are no longer part of a document and for nodes that are created
* where no document is accessible.
*
* gAnonymousNodeInfoManager is allocated when requested for the first time
* and once the last nodeinfo manager (appart from gAnonymousNodeInfoManager)
* is destroyed gAnonymousNodeInfoManager is destroyed. If the global
* nodeinfo manager is the only nodeinfo manager used it can be deleted
* and later reallocated if all users of the nodeinfo manager drops the
* referernces to it.
*/
static nsNodeInfoManager *gAnonymousNodeInfoManager;
static PRUint32 gNodeManagerCount;
};
#endif /* nsNodeInfoManager_h___ */

Просмотреть файл

@ -0,0 +1,209 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* nsINodeInfo is an interface to node info, such as name, prefix, namespace
* ID and possibly other data that is shared shared between nodes (elements
* and attributes) that have the same name, prefix and namespace ID within
* the same document.
*
* nsINodeInfoManager is an interface to an object that manages a list of
* nsINodeInfo's, every document object should hold a strong reference to
* a nsINodeInfoManager and every nsINodeInfo also holds a string reference
* to their owning manager. When a nsINodeInfo is no longer used it will
* automatically remove itself from its owner manager, and when all
* nsINodeInfo's have been removed from a nsINodeInfoManager and all external
* references are released the nsINodeInfoManager deletes itself.
*
* -- jst@netscape.com
*/
#ifndef nsINodeInfo_h___
#define nsINodeInfo_h___
#include "nsISupports.h"
// Forward declarations
class nsIAtom;
class nsINodeInfoManager;
class nsINameSpaceManager;
class nsString;
// IID for the nsINodeInfo interface
#define NS_INODEINFO_IID \
{ 0x93dbfd8c, 0x2fb3, 0x4ef5, \
{0xa2, 0xa0, 0xcf, 0xf2, 0x69, 0x6f, 0x07, 0x88} }
// IID for the nsINodeInfoManager interface
#define NS_INODEINFOMANAGER_IID \
{ 0xb622469b, 0x4dcf, 0x45c4, \
{0xb0, 0xb9, 0xa7, 0x32, 0xbc, 0xee, 0xa5, 0xcc} }
#define NS_NODEINFOMANAGER_PROGID "component://netscape/layout/nodeinfomanager"
class nsINodeInfo : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_INODEINFO_IID)
/*
* Get the name from this node as a string, this does not include the prefix.
*
* For the HTML element "<body>" this will return "body" and for the XML
* element "<html:body>" this will return "body".
*/
NS_IMETHOD GetName(nsString& aName) = 0;
/*
* Get the name from this node as an atom, this does not include the prefix.
* This function never returns a null atom.
*
* For the HTML element "<body>" this will return the "body" atom and for
* the XML element "<html:body>" this will return the "body" atom.
*/
NS_IMETHOD GetNameAtom(nsIAtom*& aAtom) = 0;
/*
* Get the qualified name from this node as a string, the qualified name
* includes the prefix, if one exists.
*
* For the HTML element "<body>" this will return "body" and for the XML
* element "<html:body>" this will return "html:body".
*/
NS_IMETHOD GetQualifiedName(nsString& aQualifiedName) = 0;
/*
* Get the local name from this node as a string, GetLocalName() gets the
* same string as GetName() but only if the node has a prefix and/or a
* namespace URI. If the node has neither a prefix nor a namespace URI the
* local name is a null string.
*
* For the HTML element "<body>" in a HTML document this will return a null
* string and for the XML element "<html:body>" this will return "body".
*/
NS_IMETHOD GetLocalName(nsString& aLocalName) = 0;
/*
* Get the prefix from this node as a string.
*
* For the HTML element "<body>" this will return a null string and for
* the XML element "<html:body>" this will return the string "html".
*/
NS_IMETHOD GetPrefix(nsString& aPrefix) = 0;
/*
* Get the prefix from this node as an atom.
*
* For the HTML element "<body>" this will return a null atom and for
* the XML element "<html:body>" this will return the "html" atom.
*/
NS_IMETHOD GetPrefixAtom(nsIAtom*& aAtom) = 0;
/*
* Get the namespace URI for a node, if the node has a namespace URI.
*
* For the HTML element "<body>" in a HTML document this will return a null
* string and for the XML element "<html:body>" (assuming that this element,
* or one of it's ancestors has an
* xmlns:html='http://www.w3.org/TR/REC-html40' attribute) this will return
* the string "http://www.w3.org/TR/REC-html40".
*/
NS_IMETHOD GetNamespaceURI(nsString& aNameSpaceURI) = 0;
/*
* Get the namespace ID for a node if the node has a namespace, if not this
* returns kNameSpaceID_None.
*
* For the HTML element "<body>" in a HTML document this will return
* kNameSpaceID_None and for the XML element "<html:body>" (assuming that
* this element, or one of it's ancestors has an
* xmlns:html='http://www.w3.org/TR/REC-html40' attribute) this will return
* the namespace ID for "http://www.w3.org/TR/REC-html40".
*/
NS_IMETHOD GetNamespaceID(PRInt32& aResult) = 0;
/*
* Get the owning node info manager, this will never return null.
*/
NS_IMETHOD GetNodeInfoManager(nsINodeInfoManager*& aNodeInfoManager) = 0;
/*
* Utility functions that can be used to check if a nodeinfo holds a spcific
* name, name and prefix, name and prefix and namespace ID, or just
* namespace ID.
*/
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom) = 0;
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom) = 0;
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, PRInt32 aNamespaceID) = 0;
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom,
PRInt32 aNamespaceID) = 0;
NS_IMETHOD_(PRBool) NamespaceEquals(PRInt32 aNamespaceID) = 0;
/*
* This is a convinience method that creates a new nsINodeInfo that differs
* only by name from the one this is called on.
*/
NS_IMETHOD NameChanged(nsIAtom *aName, nsINodeInfo*& aResult) = 0;
/*
* This is a convinience method that creates a new nsINodeInfo that differs
* only by prefix from the one this is called on.
*/
NS_IMETHOD PrefixChanged(nsIAtom *aPrefix, nsINodeInfo*& aResult) = 0;
};
class nsINodeInfoManager : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_INODEINFOMANAGER_IID)
/*
* Initialize the nodeinfo manager with a namespace manager, this should
* allways be done.
*/
NS_IMETHOD Init(nsINameSpaceManager *aNameSpaceManager) = 0;
/*
* Methods for creating nodeinfo's from atoms and/or strings.
*/
NS_IMETHOD GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo) = 0;
NS_IMETHOD GetNodeInfo(const nsString& aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo) = 0;
NS_IMETHOD GetNodeInfo(const nsString& aName, const nsString& aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo) = 0;
NS_IMETHOD GetNodeInfo(const nsString& aName, const nsString& aPrefix,
const nsString& aNamespaceURI,
nsINodeInfo*& aNodeInfo) = 0;
/*
* Getter for the namespace manager used by this nodeinfo manager.
*/
NS_IMETHOD GetNamespaceManager(nsINameSpaceManager*& aNameSpaceManager) = 0;
};
extern nsresult NS_NewNodeInfoManager(nsINodeInfoManager** aResult);
#endif /* nsINodeInfo_h___ */

Просмотреть файл

@ -0,0 +1,307 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsNodeInfo.h"
#include "nsNodeInfoManager.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIAtom.h"
#include "nsINameSpaceManager.h"
nsNodeInfo::nsNodeInfo()
: mInner(), mOwnerManager(nsnull)
{
NS_INIT_REFCNT();
}
nsNodeInfo::~nsNodeInfo()
{
if (mOwnerManager) {
mOwnerManager->RemoveNodeInfo(this);
NS_RELEASE(mOwnerManager);
}
NS_IF_RELEASE(mInner.mName);
NS_IF_RELEASE(mInner.mPrefix);
}
nsresult
nsNodeInfo::Init(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
nsNodeInfoManager *aOwnerManager)
{
NS_ENSURE_TRUE(!mInner.mName && !mInner.mPrefix && !mOwnerManager,
NS_ERROR_ALREADY_INITIALIZED);
NS_ENSURE_ARG_POINTER(aName);
NS_ENSURE_ARG_POINTER(aOwnerManager);
mInner.mName = aName;
NS_ADDREF(mInner.mName);
mInner.mPrefix = aPrefix;
NS_IF_ADDREF(mInner.mPrefix);
mInner.mNamespaceID = aNamespaceID;
mOwnerManager = aOwnerManager;
NS_ADDREF(mOwnerManager);
return NS_OK;
}
// nsISupports
NS_IMPL_THREADSAFE_ISUPPORTS(nsNodeInfo, NS_GET_IID(nsINodeInfo));
// nsINodeInfo
NS_IMETHODIMP
nsNodeInfo::GetName(nsString& aName)
{
NS_ENSURE_TRUE(mInner.mName, NS_ERROR_NOT_INITIALIZED);
return mInner.mName->ToString(aName);
}
NS_IMETHODIMP
nsNodeInfo::GetNameAtom(nsIAtom*& aAtom)
{
NS_ABORT_IF_FALSE(mInner.mName, "nsNodeInfo not initialized!");
aAtom = mInner.mName;
NS_IF_ADDREF(aAtom);
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetQualifiedName(nsString& aQualifiedName)
{
NS_ENSURE_TRUE(mInner.mName, NS_ERROR_NOT_INITIALIZED);
#ifdef MOZILLA_IS_READY_FOR_THIS
if (mInner.mPrefix) {
mInner.mPrefix->ToString(aQualifiedName);
aQualifiedName.Append(':');
}
nsAutoString tmp;
mInner.mName->ToString(tmp);
aQualifiedName.Append(tmp);
#else
mInner.mName->ToString(aQualifiedName);
#endif
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetLocalName(nsString& aLocalName)
{
NS_ENSURE_TRUE(mInner.mName, NS_ERROR_NOT_INITIALIZED);
if (mInner.mNamespaceID > 0) {
return mInner.mName->ToString(aLocalName);
}
aLocalName.Truncate();
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetPrefix(nsString& aPrefix)
{
if (mInner.mPrefix) {
mInner.mPrefix->ToString(aPrefix);
} else {
aPrefix.Truncate();
}
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetPrefixAtom(nsIAtom*& aAtom)
{
aAtom = mInner.mPrefix;
NS_IF_ADDREF(aAtom);
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetNamespaceURI(nsString& aNameSpaceURI)
{
NS_ENSURE_TRUE(mOwnerManager, NS_ERROR_NOT_INITIALIZED);
nsresult rv = NS_OK;
if (mInner.mNamespaceID > 0) {
nsCOMPtr<nsINameSpaceManager> nsm;
mOwnerManager->GetNamespaceManager(*getter_AddRefs(nsm));
NS_ENSURE_TRUE(nsm, NS_ERROR_NOT_INITIALIZED);
rv = nsm->GetNameSpaceURI(mInner.mNamespaceID, aNameSpaceURI);
} else {
aNameSpaceURI.Truncate();
}
return rv;
}
NS_IMETHODIMP
nsNodeInfo::GetNamespaceID(PRInt32& aResult)
{
aResult = mInner.mNamespaceID;
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfo::GetNodeInfoManager(nsINodeInfoManager*& aNodeInfoManager)
{
NS_ENSURE_TRUE(mOwnerManager, NS_ERROR_NOT_INITIALIZED);
aNodeInfoManager = mOwnerManager;
NS_ADDREF(aNodeInfoManager);
return NS_OK;
}
NS_IMETHODIMP_(PRBool)
nsNodeInfo::Equals(nsIAtom *aNameAtom)
{
return mInner.mName == aNameAtom;
}
NS_IMETHODIMP_(PRBool)
nsNodeInfo::Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom)
{
return (mInner.mName == aNameAtom) && (mInner.mPrefix == aPrefixAtom);
}
NS_IMETHODIMP_(PRBool)
nsNodeInfo::Equals(nsIAtom *aNameAtom, PRInt32 aNamespaceID)
{
return (mInner.mName == aNameAtom) && (mInner.mNamespaceID == aNamespaceID);
}
NS_IMETHODIMP_(PRBool)
nsNodeInfo::Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom,
PRInt32 aNamespaceID)
{
return (mInner.mName == aNameAtom) &&
(mInner.mPrefix == aPrefixAtom) &&
(mInner.mNamespaceID == aNamespaceID);
}
NS_IMETHODIMP_(PRBool)
nsNodeInfo::NamespaceEquals(PRInt32 aNamespaceID)
{
return mInner.mNamespaceID == aNamespaceID;
}
NS_IMETHODIMP
nsNodeInfo::NameChanged(nsIAtom *aName, nsINodeInfo*& aResult)
{
NS_ENSURE_TRUE(mOwnerManager, NS_ERROR_NOT_INITIALIZED);
return mOwnerManager->GetNodeInfo(aName, mInner.mPrefix, mInner.mNamespaceID,
aResult);
}
NS_IMETHODIMP
nsNodeInfo::PrefixChanged(nsIAtom *aPrefix, nsINodeInfo*& aResult)
{
NS_ENSURE_TRUE(mOwnerManager, NS_ERROR_NOT_INITIALIZED);
return mOwnerManager->GetNodeInfo(mInner.mName, aPrefix, mInner.mNamespaceID,
aResult);
}
PLHashNumber
nsNodeInfoInner::GetHashValue(const void *key)
{
#ifdef NS_DEBUG // Just to shut down a compiler warning
NS_WARN_IF_FALSE(key, "Null key passed to nsNodeInfo::GetHashValue!");
#endif
if (key) {
const nsNodeInfoInner *node = (const nsNodeInfoInner *)key;
// Is this an acceptable has value?
return (((PLHashNumber)node->mName) & 0xffff) >> 8;
}
return 0;
}
PRIntn
nsNodeInfoInner::KeyCompare(const void *key1, const void *key2)
{
#ifdef NS_DEBUG // Just to shut down a compiler warning
NS_WARN_IF_FALSE(key1 && key2, "Null key passed to nsNodeInfo::KeyCompare!");
#endif
if (!key1 || !key2) {
return PR_FALSE;
}
const nsNodeInfoInner *node1 = (const nsNodeInfoInner *)key1;
const nsNodeInfoInner *node2 = (const nsNodeInfoInner *)key2;
if (node1->mName == node2->mName &&
node1->mPrefix == node2->mPrefix &&
node1->mNamespaceID == node2->mNamespaceID) {
return PR_TRUE;
}
return PR_FALSE;
}

Просмотреть файл

@ -0,0 +1,108 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsNodeInfo_h___
#define nsNodeInfo_h___
#include "nsINodeInfo.h"
#include "nsINameSpaceManager.h"
#include "plhash.h"
/*
* nsNodeInfoInner is used for two things:
*
* 1. as a member in nsNodeInfo for holding the name, prefix and
* namespace ID
* 2. as the hash key in the hash table in nsNodeInfoManager
*
* nsNodeInfoInner does not do any kind of reference counting, that's up
* to the user of this class, since nsNodeInfoInner is a member of
* nsNodeInfo the hash table doesn't need to delete the keys, when the
* value (nsNodeInfo) the key is automatically deleted.
*/
struct nsNodeInfoInner
{
nsNodeInfoInner(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID)
: mName(aName), mPrefix(aPrefix), mNamespaceID(aNamespaceID) {}
nsNodeInfoInner()
: mName(nsnull), mPrefix(nsnull), mNamespaceID(kNameSpaceID_None) {}
static PR_CALLBACK PRIntn KeyCompare(const void *key1, const void *key2);
static PR_CALLBACK PLHashNumber GetHashValue(const void *key);
nsIAtom* mName;
nsIAtom* mPrefix;
PRInt32 mNamespaceID;
};
class nsNodeInfoManager;
class nsNodeInfo : public nsINodeInfo
{
public:
NS_DECL_ISUPPORTS
// nsINodeInfo
NS_IMETHOD GetName(nsString& aName);
NS_IMETHOD GetNameAtom(nsIAtom*& aAtom);
NS_IMETHOD GetQualifiedName(nsString& aQualifiedName);
NS_IMETHOD GetLocalName(nsString& aLocalName);
NS_IMETHOD GetPrefix(nsString& aPrefix);
NS_IMETHOD GetPrefixAtom(nsIAtom*& aAtom);
NS_IMETHOD GetNamespaceURI(nsString& aNameSpaceURI);
NS_IMETHOD GetNamespaceID(PRInt32& aResult);
NS_IMETHOD GetNodeInfoManager(nsINodeInfoManager*& aNodeInfoManager);
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom);
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom);
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, PRInt32 aNamespaceID);
NS_IMETHOD_(PRBool) Equals(nsIAtom *aNameAtom, nsIAtom *aPrefixAtom,
PRInt32 aNamespaceID);
NS_IMETHOD_(PRBool) NamespaceEquals(PRInt32 aNamespaceID);
NS_IMETHOD NameChanged(nsIAtom *aName, nsINodeInfo*& aResult);
NS_IMETHOD PrefixChanged(nsIAtom *aPrefix, nsINodeInfo*& aResult);
// nsNodeInfo
nsNodeInfo();
virtual ~nsNodeInfo();
/*
* Note! Init() must be called exactly once on every nsNodeInfo before
* the object is used, if Init() returns an error code the nsNodeInfo
* should not be used.
*
* aName and aOwnerManager may not be null.
*/
nsresult Init(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
nsNodeInfoManager *aOwnerManager);
protected:
friend class nsNodeInfoManager; // The NodeInfoManager needs to pass this
// to the hash table.
nsNodeInfoInner mInner;
nsNodeInfoManager* mOwnerManager; // Strong reference!
};
#endif /* nsNodeInfo_h___ */

Просмотреть файл

@ -0,0 +1,272 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsNodeInfoManager.h"
#include "nsNodeInfo.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIAtom.h"
nsNodeInfoManager* nsNodeInfoManager::gAnonymousNodeInfoManager = nsnull;
PRUint32 nsNodeInfoManager::gNodeManagerCount = 0;
nsresult NS_NewNodeInfoManager(nsINodeInfoManager** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = new nsNodeInfoManager;
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult);
return NS_OK;
}
nsNodeInfoManager::nsNodeInfoManager()
: mNameSpaceManager(nsnull)
{
NS_INIT_REFCNT();
if (gNodeManagerCount == 1 && gAnonymousNodeInfoManager) {
/*
* If we get here the global nodeinfo manager was the first one created,
* in that case we're not holding a strong reference to the global nodeinfo
* manager. Now we're creating one more nodeinfo manager so we'll grab
* a strong reference to the global nodeinfo manager so that it's
* lifetime will be longer than the lifetime of the other node managers.
*/
NS_ADDREF(gAnonymousNodeInfoManager);
}
gNodeManagerCount++;
mNodeInfoHash = PL_NewHashTable(32, nsNodeInfoInner::GetHashValue,
nsNodeInfoInner::KeyCompare,
PL_CompareValues, nsnull, nsnull);
#ifdef DEBUG_jst
printf ("Creating NodeInfoManager, gcount = %d\n", gNodeManagerCount);
#endif
}
nsNodeInfoManager::~nsNodeInfoManager()
{
gNodeManagerCount--;
if (gNodeManagerCount == 1 && gAnonymousNodeInfoManager) {
NS_RELEASE(gAnonymousNodeInfoManager);
} else if (!gNodeManagerCount) {
/*
* Here we just make sure that we don't leave a dangling pointer to
* the global nodeinfo manager after it's deleted.
*/
gAnonymousNodeInfoManager = nsnull;
}
if (mNodeInfoHash)
PL_HashTableDestroy(mNodeInfoHash);
#ifdef DEBUG_jst
printf ("Removing NodeInfoManager, gcount = %d\n", gNodeManagerCount);
#endif
}
NS_IMPL_THREADSAFE_ISUPPORTS(nsNodeInfoManager,
NS_GET_IID(nsINodeInfoManager));
// nsINodeInfoManager
NS_IMETHODIMP
nsNodeInfoManager::Init(nsINameSpaceManager *aNameSpaceManager)
{
NS_ENSURE_ARG_POINTER(aNameSpaceManager);
NS_ENSURE_TRUE(mNodeInfoHash, NS_ERROR_OUT_OF_MEMORY);
mNameSpaceManager = aNameSpaceManager;
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo)
{
NS_ENSURE_ARG_POINTER(aName);
nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID);
void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
if (node) {
aNodeInfo = NS_STATIC_CAST(nsINodeInfo *, node);
NS_ADDREF(aNodeInfo);
return NS_OK;
}
nsNodeInfo *newNodeInfo = new nsNodeInfo();
NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(newNodeInfo);
nsresult rv = newNodeInfo->Init(aName, aPrefix, aNamespaceID, this);
NS_ENSURE_SUCCESS(rv, rv);
PLHashEntry *he;
he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
NS_ENSURE_TRUE(he, NS_ERROR_OUT_OF_MEMORY);
aNodeInfo = newNodeInfo;
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfoManager::GetNodeInfo(const nsString& aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo)
{
NS_ENSURE_ARG(aName.Length());
nsCOMPtr<nsIAtom> name(dont_AddRef(NS_NewAtom(aName)));
NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
return GetNodeInfo(name, aPrefix, aNamespaceID, aNodeInfo);
}
NS_IMETHODIMP
nsNodeInfoManager::GetNodeInfo(const nsString& aName, const nsString& aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo)
{
NS_ENSURE_ARG(aName.Length());
nsCOMPtr<nsIAtom> name(dont_AddRef(NS_NewAtom(aName)));
NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIAtom> prefix;
if (aPrefix.Length()) {
prefix = dont_AddRef(NS_NewAtom(aPrefix));
NS_ENSURE_TRUE(prefix, NS_ERROR_OUT_OF_MEMORY);
}
return GetNodeInfo(name, prefix, aNamespaceID, aNodeInfo);
}
NS_IMETHODIMP
nsNodeInfoManager::GetNodeInfo(const nsString& aName, const nsString& aPrefix,
const nsString& aNamespaceURI,
nsINodeInfo*& aNodeInfo)
{
NS_ENSURE_ARG(aName.Length());
nsCOMPtr<nsIAtom> name(dont_AddRef(NS_NewAtom(aName)));
NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIAtom> prefix;
if (aPrefix.Length()) {
prefix = dont_AddRef(NS_NewAtom(aPrefix));
NS_ENSURE_TRUE(prefix, NS_ERROR_OUT_OF_MEMORY);
}
PRInt32 nsid = kNameSpaceID_None;
if (aNamespaceURI.Length()) {
if (!mNameSpaceManager) {
return NS_ERROR_NOT_INITIALIZED;
}
mNameSpaceManager->GetNameSpaceID(aNamespaceURI, nsid);
}
return GetNodeInfo(name, prefix, nsid, aNodeInfo);
}
NS_IMETHODIMP
nsNodeInfoManager::GetNamespaceManager(nsINameSpaceManager*& aNameSpaceManager)
{
aNameSpaceManager = mNameSpaceManager;
NS_IF_ADDREF(aNameSpaceManager);
return NS_OK;
}
void
nsNodeInfoManager::RemoveNodeInfo(nsNodeInfo *aNodeInfo)
{
NS_WARN_IF_FALSE(aNodeInfo, "Trying to remove null nodeinfo from manager!");
if (aNodeInfo) {
PRBool ret = PL_HashTableRemove(mNodeInfoHash, aNodeInfo);
NS_WARN_IF_FALSE(!ret, "Can't find nsINodeInfo to remove!!!");
}
}
nsresult
nsNodeInfoManager::GetAnonymousManager(nsINodeInfoManager*& aNodeInfoManager)
{
if (!gAnonymousNodeInfoManager) {
gAnonymousNodeInfoManager = new nsNodeInfoManager;
if (!gAnonymousNodeInfoManager)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(gAnonymousNodeInfoManager);
nsresult rv = NS_NewNameSpaceManager(getter_AddRefs(gAnonymousNodeInfoManager->mNameSpaceManager));
if (NS_FAILED(rv)) {
NS_RELEASE(gAnonymousNodeInfoManager);
return rv;
}
}
aNodeInfoManager = gAnonymousNodeInfoManager;
/*
* If the only nodeinfo manager is the global one we don't hold a ref
* since the global nodeinfo manager should be destroyed when it's released,
* even if it's the last one arround.
*/
if (gNodeManagerCount > 1) {
NS_ADDREF(aNodeInfoManager);
}
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsNodeInfoManager_h___
#define nsNodeInfoManager_h___
#include "nsINodeInfo.h"
#include "nsINameSpaceManager.h"
#include "nsCOMPtr.h"
#include "plhash.h"
class nsNodeInfo;
class nsNodeInfoManager : public nsINodeInfoManager
{
public:
NS_DECL_ISUPPORTS
// nsINodeInfoManager
NS_IMETHOD Init(nsINameSpaceManager *aNameSpaceManager);
NS_IMETHOD GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo);
NS_IMETHOD GetNodeInfo(const nsString& aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo);
NS_IMETHOD GetNodeInfo(const nsString& aName, const nsString& aPrefix,
PRInt32 aNamespaceID, nsINodeInfo*& aNodeInfo);
NS_IMETHOD GetNodeInfo(const nsString& aName, const nsString& aPrefix,
const nsString& aNamespaceURI,
nsINodeInfo*& aNodeInfo);
NS_IMETHOD GetNamespaceManager(nsINameSpaceManager*& aNameSpaceManager);
// nsNodeInfoManager
nsNodeInfoManager();
virtual ~nsNodeInfoManager();
void RemoveNodeInfo(nsNodeInfo *aNodeInfo);
static nsresult GetAnonymousManager(nsINodeInfoManager*& aNodeInfoManager);
private:
PLHashTable *mNodeInfoHash;
nsCOMPtr<nsINameSpaceManager> mNameSpaceManager;
/*
* gAnonymousNodeInfoManager is a global nodeinfo manager used for nodes
* that are no longer part of a document and for nodes that are created
* where no document is accessible.
*
* gAnonymousNodeInfoManager is allocated when requested for the first time
* and once the last nodeinfo manager (appart from gAnonymousNodeInfoManager)
* is destroyed gAnonymousNodeInfoManager is destroyed. If the global
* nodeinfo manager is the only nodeinfo manager used it can be deleted
* and later reallocated if all users of the nodeinfo manager drops the
* referernces to it.
*/
static nsNodeInfoManager *gAnonymousNodeInfoManager;
static PRUint32 gNodeManagerCount;
};
#endif /* nsNodeInfoManager_h___ */