mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-02 03:49:37 +00:00
Fix bug 114115. Reduce long lived allocations by refactoring to hold main interface info structs in arena and buil refcounted info objects on demand (though cached for reuse) r=dbradley sr=jst
This commit is contained in:
parent
c96b2c0c8d
commit
02b0142c2d
@ -55,6 +55,8 @@ interface nsIInterfaceInfoManager : nsISupports
|
||||
nsIEnumerator enumerateInterfaces();
|
||||
|
||||
void autoRegisterInterfaces();
|
||||
|
||||
nsIEnumerator enumerateInterfacesWhoseNamesStartWith(in string prefix);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -11,19 +11,10 @@
|
||||
- verify that interface names are always one-to-one with iids
|
||||
- check for truncated xpt files and version problems
|
||||
- http://bugzilla.mozilla.org/show_bug.cgi?id=33193
|
||||
- support xpt files in more than just the components dir; e.g. plugins?
|
||||
- probably just another field in the manifest containing a number
|
||||
i.e. '0' means components dir, '1' means plugins dir, etc.
|
||||
- TESTS!
|
||||
- e.g. verify the merge stuff really works for various inputs.
|
||||
- we really need a set of .xpt and .zip files and code that does an array
|
||||
of autoreg and interfaceinof use activitities to test various corners
|
||||
of the system.
|
||||
- support #ifdef'ing out the zip #includes and uses
|
||||
- this is needed if we want to remove the #include dependency on libjar
|
||||
- most zip code is already in separate file. Only the places where it
|
||||
finds and reads zips need #ifdefing - minimize the changes.
|
||||
- switch to MoveTo for .dat file
|
||||
- depends on bug 33098 (stupidly marked [feature]!)
|
||||
- better autoreg logging
|
||||
- use only 32 bits for file size?
|
||||
|
@ -20,6 +20,8 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe <mccabe@netscape.com>
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -42,7 +44,11 @@
|
||||
MOZ_DECL_CTOR_COUNTER(xptiFile)
|
||||
|
||||
xptiFile::xptiFile()
|
||||
: mSize(),
|
||||
:
|
||||
#ifdef DEBUG
|
||||
mDEBUG_WorkingSet(nsnull),
|
||||
#endif
|
||||
mSize(),
|
||||
mDate(),
|
||||
mName(nsnull),
|
||||
mGuts(nsnull),
|
||||
@ -56,10 +62,12 @@ xptiFile::xptiFile(const nsInt64& aSize,
|
||||
const nsInt64& aDate,
|
||||
PRUint32 aDirectory,
|
||||
const char* aName,
|
||||
xptiWorkingSet* aWorkingSet,
|
||||
XPTHeader* aHeader /*= nsnull */)
|
||||
|
||||
: mSize(aSize),
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
:
|
||||
#ifdef DEBUG
|
||||
mDEBUG_WorkingSet(aWorkingSet),
|
||||
#endif
|
||||
mSize(aSize),
|
||||
mDate(aDate),
|
||||
mName(aName),
|
||||
mGuts(nsnull),
|
||||
@ -68,15 +76,15 @@ xptiFile::xptiFile(const nsInt64& aSize,
|
||||
NS_ASSERTION(aWorkingSet,"bad param");
|
||||
mName = XPT_STRDUP(aWorkingSet->GetStringArena(), aName);
|
||||
|
||||
if(aHeader)
|
||||
SetHeader(aHeader);
|
||||
|
||||
MOZ_COUNT_CTOR(xptiFile);
|
||||
}
|
||||
|
||||
xptiFile::xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet,
|
||||
PRBool cloneGuts)
|
||||
: mSize(r.mSize),
|
||||
xptiFile::xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet)
|
||||
:
|
||||
#ifdef DEBUG
|
||||
mDEBUG_WorkingSet(aWorkingSet),
|
||||
#endif
|
||||
mSize(r.mSize),
|
||||
mDate(r.mDate),
|
||||
mName(nsnull),
|
||||
mGuts(nsnull),
|
||||
@ -85,31 +93,21 @@ xptiFile::xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet,
|
||||
NS_ASSERTION(aWorkingSet,"bad param");
|
||||
mName = XPT_STRDUP(aWorkingSet->GetStringArena(), r.mName);
|
||||
|
||||
if(cloneGuts && r.mGuts)
|
||||
mGuts = r.mGuts->Clone();
|
||||
|
||||
MOZ_COUNT_CTOR(xptiFile);
|
||||
}
|
||||
|
||||
xptiFile::~xptiFile()
|
||||
{
|
||||
if(mGuts)
|
||||
delete mGuts;
|
||||
|
||||
MOZ_COUNT_DTOR(xptiFile);
|
||||
}
|
||||
|
||||
PRBool
|
||||
xptiFile::SetHeader(XPTHeader* aHeader)
|
||||
xptiFile::SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet)
|
||||
{
|
||||
NS_ASSERTION(!mGuts,"bad state");
|
||||
NS_ASSERTION(aHeader,"bad param");
|
||||
NS_ASSERTION(aWorkingSet,"bad param");
|
||||
|
||||
mGuts = new xptiTypelibGuts(aHeader);
|
||||
if(mGuts && !mGuts->IsValid())
|
||||
{
|
||||
delete mGuts;
|
||||
mGuts = nsnull;
|
||||
}
|
||||
mGuts = xptiTypelibGuts::NewGuts(aHeader, aWorkingSet);
|
||||
return mGuts != nsnull;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe <mccabe@netscape.com>
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -35,91 +37,116 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Implementation of xptiInterfaceInfo. */
|
||||
/* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */
|
||||
|
||||
#include "xptiprivate.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(xptiInterfaceInfo, nsIInterfaceInfo)
|
||||
/***************************************************************************/
|
||||
// Debug Instrumentation...
|
||||
|
||||
void
|
||||
xptiInterfaceInfo::CopyName(const char* name,
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
#ifdef SHOW_INFO_COUNT_STATS
|
||||
static int DEBUG_TotalInfos = 0;
|
||||
static int DEBUG_CurrentInfos = 0;
|
||||
static int DEBUG_MaxInfos = 0;
|
||||
static int DEBUG_MonitorEntryCount = 0;
|
||||
|
||||
#define LOG_INFO_CREATE(t) \
|
||||
DEBUG_TotalInfos++; \
|
||||
DEBUG_CurrentInfos++; \
|
||||
if(DEBUG_MaxInfos < DEBUG_CurrentInfos) \
|
||||
DEBUG_MaxInfos = DEBUG_CurrentInfos /* no ';' */
|
||||
|
||||
#define LOG_INFO_DESTROY(t) \
|
||||
DEBUG_CurrentInfos-- /* no ';' */
|
||||
|
||||
#define LOG_INFO_MONITOR_ENTRY \
|
||||
DEBUG_MonitorEntryCount++ /* no ';' */
|
||||
|
||||
#else /* SHOW_INFO_COUNT_STATS */
|
||||
|
||||
#define LOG_INFO_CREATE(t) ((void)0)
|
||||
#define LOG_INFO_DESTROY(t) ((void)0)
|
||||
#define LOG_INFO_MONITOR_ENTRY ((void)0)
|
||||
#endif /* SHOW_INFO_COUNT_STATS */
|
||||
|
||||
#ifdef DEBUG
|
||||
// static
|
||||
void xptiInterfaceInfo::DEBUG_ShutdownNotification()
|
||||
{
|
||||
NS_ASSERTION(name, "bad param!");
|
||||
NS_ASSERTION(aWorkingSet, "bad param!");
|
||||
NS_ASSERTION(!mName, "bad caller!");
|
||||
#ifdef SHOW_INFO_COUNT_STATS
|
||||
printf("iiii %d total xptiInterfaceInfos created\n", DEBUG_TotalInfos);
|
||||
printf("iiii %d max xptiInterfaceInfos alive at one time\n", DEBUG_MaxInfos);
|
||||
printf("iiii %d xptiInterfaceInfos still alive\n", DEBUG_CurrentInfos);
|
||||
printf("iiii %d times locked\n", DEBUG_MonitorEntryCount);
|
||||
#endif
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
int len = PL_strlen(name);
|
||||
char* ptr = (char*) XPT_MALLOC(aWorkingSet->GetStringArena(), len+2);
|
||||
if(ptr)
|
||||
{
|
||||
mName = &ptr[1];
|
||||
memcpy(mName, name, len);
|
||||
// XXX These are redundant as long as the underlying arena continues
|
||||
// to zero out all mallocs. But...
|
||||
mName[-1] = mName[len] = 0;
|
||||
}
|
||||
/***************************************************************************/
|
||||
|
||||
}
|
||||
// static
|
||||
xptiInterfaceEntry*
|
||||
xptiInterfaceEntry::NewEntry(const char* name,
|
||||
const nsID& iid,
|
||||
const xptiTypelib& typelib,
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
{
|
||||
size_t nameLength = PL_strlen(name);
|
||||
void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
|
||||
sizeof(xptiInterfaceEntry) + nameLength);
|
||||
if(!place)
|
||||
return nsnull;
|
||||
return new(place) xptiInterfaceEntry(name, nameLength, iid, typelib);
|
||||
}
|
||||
|
||||
// static
|
||||
xptiInterfaceEntry*
|
||||
xptiInterfaceEntry::NewEntry(const xptiInterfaceEntry& r,
|
||||
const xptiTypelib& typelib,
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
{
|
||||
size_t nameLength = PL_strlen(r.mName);
|
||||
void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
|
||||
sizeof(xptiInterfaceEntry) + nameLength);
|
||||
if(!place)
|
||||
return nsnull;
|
||||
return new(place) xptiInterfaceEntry(r, nameLength, typelib);
|
||||
}
|
||||
|
||||
|
||||
xptiInterfaceInfo::xptiInterfaceInfo(const char* name,
|
||||
const nsID& iid,
|
||||
const xptiTypelib& typelib,
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
xptiInterfaceEntry::xptiInterfaceEntry(const char* name,
|
||||
size_t nameLength,
|
||||
const nsID& iid,
|
||||
const xptiTypelib& typelib)
|
||||
: mIID(iid),
|
||||
mName(nsnull),
|
||||
mTypelib(typelib)
|
||||
mTypelib(typelib),
|
||||
mInfo(nsnull),
|
||||
mFlags(uint8(0))
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
CopyName(name, aWorkingSet);
|
||||
memcpy(mName, name, nameLength);
|
||||
}
|
||||
|
||||
xptiInterfaceInfo::xptiInterfaceInfo(const xptiInterfaceInfo& r,
|
||||
const xptiTypelib& typelib,
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
xptiInterfaceEntry::xptiInterfaceEntry(const xptiInterfaceEntry& r,
|
||||
size_t nameLength,
|
||||
const xptiTypelib& typelib)
|
||||
: mIID(r.mIID),
|
||||
mName(nsnull),
|
||||
mTypelib(typelib)
|
||||
mTypelib(typelib),
|
||||
mInfo(nsnull),
|
||||
mFlags(r.mFlags)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
CopyName(r.mName, aWorkingSet);
|
||||
if(IsValid() && r.IsValid())
|
||||
{
|
||||
mName[-1] = r.mName[-1]; // copy any flags
|
||||
SetResolvedState(NOT_RESOLVED);
|
||||
}
|
||||
}
|
||||
|
||||
xptiInterfaceInfo::~xptiInterfaceInfo()
|
||||
{
|
||||
if(HasInterfaceRecord())
|
||||
delete mInterface;
|
||||
}
|
||||
|
||||
void
|
||||
xptiInterfaceInfo::Invalidate()
|
||||
{
|
||||
if(IsValid())
|
||||
{
|
||||
// The order of operations here is important!
|
||||
xptiTypelib typelib = GetTypelibRecord();
|
||||
if(HasInterfaceRecord())
|
||||
delete mInterface;
|
||||
mTypelib = typelib;
|
||||
mName = nsnull;
|
||||
}
|
||||
SetResolvedState(NOT_RESOLVED);
|
||||
memcpy(mName, r.mName, nameLength);
|
||||
}
|
||||
|
||||
PRBool
|
||||
xptiInterfaceInfo::Resolve(xptiWorkingSet* aWorkingSet /* = nsnull */)
|
||||
xptiInterfaceEntry::Resolve(xptiWorkingSet* aWorkingSet /* = nsnull */)
|
||||
{
|
||||
nsAutoLock lock(xptiInterfaceInfoManager::GetResolveLock());
|
||||
return ResolveLocked(aWorkingSet);
|
||||
}
|
||||
|
||||
PRBool
|
||||
xptiInterfaceInfo::ResolveLocked(xptiWorkingSet* aWorkingSet /* = nsnull */)
|
||||
xptiInterfaceEntry::ResolveLocked(xptiWorkingSet* aWorkingSet /* = nsnull */)
|
||||
{
|
||||
int resolvedState = GetResolveState();
|
||||
|
||||
@ -165,20 +192,20 @@ xptiInterfaceInfo::ResolveLocked(xptiWorkingSet* aWorkingSet /* = nsnull */)
|
||||
|
||||
if(parent_index)
|
||||
{
|
||||
xptiInterfaceInfo* parent =
|
||||
xptiInterfaceEntry* parent =
|
||||
aWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
|
||||
GetInfoAtNoAddRef(parent_index - 1);
|
||||
GetEntryAt(parent_index - 1);
|
||||
|
||||
if(!parent || !parent->EnsureResolvedLocked())
|
||||
{
|
||||
xptiTypelib aTypelib = mInterface->mTypelib;
|
||||
delete mInterface;
|
||||
mInterface = nsnull;
|
||||
mTypelib = aTypelib;
|
||||
SetResolvedState(RESOLVE_FAILED);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_ADDREF(mInterface->mParent = parent);
|
||||
mInterface->mParent = parent;
|
||||
|
||||
mInterface->mMethodBaseIndex =
|
||||
parent->mInterface->mMethodBaseIndex +
|
||||
@ -197,107 +224,85 @@ xptiInterfaceInfo::ResolveLocked(xptiWorkingSet* aWorkingSet /* = nsnull */)
|
||||
|
||||
// This *only* gets called by xptiInterfaceInfoManager::LoadFile (while locked).
|
||||
PRBool
|
||||
xptiInterfaceInfo::PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
xptiInterfaceEntry::PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
{
|
||||
NS_ASSERTION(GetResolveState() == NOT_RESOLVED, "bad state");
|
||||
|
||||
LOG_RESOLVE(("~ partial resolve of %s\n", mName));
|
||||
|
||||
xptiInterfaceGuts* iface =
|
||||
new xptiInterfaceGuts(aDescriptor, mTypelib, aWorkingSet);
|
||||
xptiInterfaceGuts::NewGuts(aDescriptor, mTypelib, aWorkingSet);
|
||||
|
||||
if(!iface)
|
||||
return PR_FALSE;
|
||||
|
||||
mInterface = iface;
|
||||
|
||||
if(!ScriptableFlagIsValid())
|
||||
#ifdef DEBUG
|
||||
if(!DEBUG_ScriptableFlagIsValid())
|
||||
{
|
||||
NS_ERROR("unexpected scriptable flag!");
|
||||
SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags));
|
||||
}
|
||||
#endif
|
||||
|
||||
SetResolvedState(PARTIALLY_RESOLVED);
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/**************************************************/
|
||||
// These non-virtual methods handle the delegated nsIInterfaceInfo methods.
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetName(char **name)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetName(char **name)
|
||||
{
|
||||
NS_PRECONDITION(name, "bad param");
|
||||
|
||||
if(!mName)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
char* ptr = *name = (char*) nsMemory::Clone(mName, PL_strlen(mName)+1);
|
||||
return ptr ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetIID(nsIID **iid)
|
||||
{
|
||||
NS_PRECONDITION(iid, "bad param");
|
||||
|
||||
nsIID* ptr = *iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID));
|
||||
return ptr ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::IsScriptable(PRBool* result)
|
||||
{
|
||||
NS_ASSERTION(result, "bad bad caller!");
|
||||
|
||||
// It is not necessary to Resolve because this info is read from manifest.
|
||||
*name = (char*) nsMemory::Clone(mName, PL_strlen(mName)+1);
|
||||
return *name ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_ASSERTION(ScriptableFlagIsValid(), "scriptable flag out of sync!");
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetIID(nsIID **iid)
|
||||
{
|
||||
// It is not necessary to Resolve because this info is read from manifest.
|
||||
*iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID));
|
||||
return *iid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xptiInterfaceEntry::IsScriptable(PRBool* result)
|
||||
{
|
||||
// It is not necessary to Resolve because this info is read from manifest.
|
||||
NS_ASSERTION(DEBUG_ScriptableFlagIsValid(), "scriptable flag out of sync!");
|
||||
*result = GetScriptableFlag();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::IsFunction(PRBool* result)
|
||||
nsresult
|
||||
xptiInterfaceEntry::IsFunction(PRBool* result)
|
||||
{
|
||||
NS_ASSERTION(result, "bad bad caller!");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
*result = XPT_ID_IS_FUNCTION(mInterface->mDescriptor->flags);
|
||||
*result = XPT_ID_IS_FUNCTION(GetInterfaceGuts()->mDescriptor->flags);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetParent(nsIInterfaceInfo** parent)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetMethodCount(uint16* count)
|
||||
{
|
||||
NS_PRECONDITION(parent, "bad param");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
NS_IF_ADDREF(*parent = mInterface->mParent);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetMethodCount(uint16* count)
|
||||
{
|
||||
NS_PRECONDITION(count, "bad param");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
|
||||
*count = mInterface->mMethodBaseIndex +
|
||||
mInterface->mDescriptor->num_methods;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetConstantCount(uint16* count)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetConstantCount(uint16* count)
|
||||
{
|
||||
NS_PRECONDITION(count, "bad param");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
@ -306,11 +311,9 @@ xptiInterfaceInfo::GetConstantCount(uint16* count)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
|
||||
{
|
||||
NS_PRECONDITION(info, "bad param");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
@ -333,21 +336,15 @@ xptiInterfaceInfo::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetMethodInfoForName(const char* methodName, uint16 *index,
|
||||
const nsXPTMethodInfo** result)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16 *index,
|
||||
const nsXPTMethodInfo** result)
|
||||
{
|
||||
NS_PRECONDITION(methodName, "bad param");
|
||||
NS_PRECONDITION(index, "bad param");
|
||||
NS_PRECONDITION(result, "bad param");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// This is a slow algorithm, but this is not expected to be called much.
|
||||
for(uint16 i = 0;
|
||||
i < mInterface->mDescriptor->num_methods;
|
||||
++i)
|
||||
for(uint16 i = 0; i < mInterface->mDescriptor->num_methods; ++i)
|
||||
{
|
||||
const nsXPTMethodInfo* info;
|
||||
info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
|
||||
@ -359,9 +356,9 @@ xptiInterfaceInfo::GetMethodInfoForName(const char* methodName, uint16 *index,
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if(mInterface->mParent)
|
||||
return mInterface->mParent->GetMethodInfoForName(methodName,
|
||||
index, result);
|
||||
return mInterface->mParent->GetMethodInfoForName(methodName, index, result);
|
||||
else
|
||||
{
|
||||
*index = 0;
|
||||
@ -370,11 +367,9 @@ xptiInterfaceInfo::GetMethodInfoForName(const char* methodName, uint16 *index,
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetConstant(uint16 index, const nsXPTConstant** constant)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetConstant(uint16 index, const nsXPTConstant** constant)
|
||||
{
|
||||
NS_PRECONDITION(constant, "bad param");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
@ -398,33 +393,30 @@ xptiInterfaceInfo::GetConstant(uint16 index, const nsXPTConstant** constant)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetInfoForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo *param,
|
||||
nsIInterfaceInfo** info)
|
||||
{
|
||||
NS_PRECONDITION(param, "bad pointer");
|
||||
NS_PRECONDITION(info, "bad pointer");
|
||||
// this is a private helper
|
||||
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetEntryForParam(PRUint16 methodIndex,
|
||||
const nsXPTParamInfo * param,
|
||||
xptiInterfaceEntry** entry)
|
||||
{
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if(methodIndex < mInterface->mMethodBaseIndex)
|
||||
return mInterface->mParent->GetInfoForParam(methodIndex, param, info);
|
||||
return mInterface->mParent->GetEntryForParam(methodIndex, param, entry);
|
||||
|
||||
if(methodIndex >= mInterface->mMethodBaseIndex +
|
||||
mInterface->mDescriptor->num_methods)
|
||||
{
|
||||
NS_PRECONDITION(0, "bad param");
|
||||
*info = NULL;
|
||||
NS_ERROR("bad param");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const XPTTypeDescriptor *td = ¶m->type;
|
||||
|
||||
while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
|
||||
td = &mInterface->mDescriptor->
|
||||
additional_types[td->type.additional_type];
|
||||
td = &mInterface->mDescriptor->additional_types[td->type.additional_type];
|
||||
}
|
||||
|
||||
if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) {
|
||||
@ -432,36 +424,51 @@ xptiInterfaceInfo::GetInfoForParam(uint16 methodIndex,
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsIInterfaceInfo* theInfo =
|
||||
mInterface->mWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
|
||||
GetInfoAtNoAddRef(td->type.iface - 1);
|
||||
xptiInterfaceEntry* theEntry =
|
||||
mInterface->mWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
|
||||
GetEntryAt(td->type.iface - 1);
|
||||
|
||||
if(!theInfo)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ADDREF(*info = theInfo);
|
||||
NS_ASSERTION(theEntry, "bad state");
|
||||
*entry = theEntry;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetIIDForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo* param, nsIID** iid)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetInfoForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo *param,
|
||||
nsIInterfaceInfo** info)
|
||||
{
|
||||
nsCOMPtr<nsIInterfaceInfo> ii;
|
||||
nsresult rv = GetInfoForParam(methodIndex, param, getter_AddRefs(ii));
|
||||
xptiInterfaceEntry* entry;
|
||||
nsresult rv = GetEntryForParam(methodIndex, param, &entry);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
return ii->GetIID(iid);
|
||||
|
||||
xptiInterfaceInfo* theInfo;
|
||||
rv = entry->GetInterfaceInfo(&theInfo);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
*info = NS_STATIC_CAST(nsIInterfaceInfo*, theInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetIIDForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo* param, nsIID** iid)
|
||||
{
|
||||
xptiInterfaceEntry* entry;
|
||||
nsresult rv = GetEntryForParam(methodIndex, param, &entry);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
return entry->GetIID(iid);
|
||||
}
|
||||
|
||||
// this is a private helper
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetTypeInArray(const nsXPTParamInfo* param,
|
||||
uint16 dimension,
|
||||
const XPTTypeDescriptor** type)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param,
|
||||
uint16 dimension,
|
||||
const XPTTypeDescriptor** type)
|
||||
{
|
||||
NS_ASSERTION(param, "bad state");
|
||||
NS_ASSERTION(type, "bad state");
|
||||
NS_ASSERTION(IsFullyResolved(), "bad state");
|
||||
|
||||
const XPTTypeDescriptor *td = ¶m->type;
|
||||
@ -480,21 +487,18 @@ xptiInterfaceInfo::GetTypeInArray(const nsXPTParamInfo* param,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetTypeForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo* param,
|
||||
uint16 dimension,
|
||||
nsXPTType* type)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetTypeForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo* param,
|
||||
uint16 dimension,
|
||||
nsXPTType* type)
|
||||
{
|
||||
NS_PRECONDITION(param, "bad pointer");
|
||||
NS_PRECONDITION(type, "bad pointer");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if(methodIndex < mInterface->mMethodBaseIndex)
|
||||
return mInterface->mParent->GetTypeForParam(methodIndex, param,
|
||||
dimension, type);
|
||||
return mInterface->mParent->
|
||||
GetTypeForParam(methodIndex, param, dimension, type);
|
||||
|
||||
if(methodIndex >= mInterface->mMethodBaseIndex +
|
||||
mInterface->mDescriptor->num_methods)
|
||||
@ -517,22 +521,18 @@ xptiInterfaceInfo::GetTypeForParam(uint16 methodIndex,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetSizeIsArgNumberForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo* param,
|
||||
uint16 dimension,
|
||||
uint8* argnum)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo* param,
|
||||
uint16 dimension,
|
||||
uint8* argnum)
|
||||
{
|
||||
NS_PRECONDITION(param, "bad pointer");
|
||||
NS_PRECONDITION(argnum, "bad pointer");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if(methodIndex < mInterface->mMethodBaseIndex)
|
||||
return mInterface->mParent->
|
||||
GetSizeIsArgNumberForParam(methodIndex, param,
|
||||
dimension, argnum);
|
||||
GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum);
|
||||
|
||||
if(methodIndex >= mInterface->mMethodBaseIndex +
|
||||
mInterface->mDescriptor->num_methods)
|
||||
@ -566,22 +566,18 @@ xptiInterfaceInfo::GetSizeIsArgNumberForParam(uint16 methodIndex,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetLengthIsArgNumberForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo* param,
|
||||
uint16 dimension,
|
||||
uint8* argnum)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetLengthIsArgNumberForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo* param,
|
||||
uint16 dimension,
|
||||
uint8* argnum)
|
||||
{
|
||||
NS_PRECONDITION(param, "bad pointer");
|
||||
NS_PRECONDITION(argnum, "bad pointer");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if(methodIndex < mInterface->mMethodBaseIndex)
|
||||
return mInterface->mParent->
|
||||
GetLengthIsArgNumberForParam(methodIndex, param,
|
||||
dimension, argnum);
|
||||
GetLengthIsArgNumberForParam(methodIndex, param, dimension, argnum);
|
||||
|
||||
if(methodIndex >= mInterface->mMethodBaseIndex +
|
||||
mInterface->mDescriptor->num_methods)
|
||||
@ -616,21 +612,17 @@ xptiInterfaceInfo::GetLengthIsArgNumberForParam(uint16 methodIndex,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetInterfaceIsArgNumberForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo* param,
|
||||
uint8* argnum)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16 methodIndex,
|
||||
const nsXPTParamInfo* param,
|
||||
uint8* argnum)
|
||||
{
|
||||
NS_PRECONDITION(param, "bad pointer");
|
||||
NS_PRECONDITION(argnum, "bad pointer");
|
||||
|
||||
if(!EnsureResolved())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if(methodIndex < mInterface->mMethodBaseIndex)
|
||||
return mInterface->mParent->
|
||||
GetInterfaceIsArgNumberForParam(methodIndex, param,
|
||||
argnum);
|
||||
GetInterfaceIsArgNumberForParam(methodIndex, param, argnum);
|
||||
|
||||
if(methodIndex >= mInterface->mMethodBaseIndex +
|
||||
mInterface->mDescriptor->num_methods)
|
||||
@ -656,49 +648,39 @@ xptiInterfaceInfo::GetInterfaceIsArgNumberForParam(uint16 methodIndex,
|
||||
}
|
||||
|
||||
/* PRBool isIID (in nsIIDPtr IID); */
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::IsIID(const nsIID * IID, PRBool *_retval)
|
||||
nsresult
|
||||
xptiInterfaceEntry::IsIID(const nsIID * IID, PRBool *_retval)
|
||||
{
|
||||
NS_PRECONDITION(IID, "bad pointer");
|
||||
NS_PRECONDITION(_retval, "bad pointer");
|
||||
|
||||
// It is not necessary to Resolve because this info is read from manifest.
|
||||
*_retval = mIID.Equals(*IID);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void getNameShared ([shared, retval] out string name); */
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetNameShared(const char **name)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetNameShared(const char **name)
|
||||
{
|
||||
NS_PRECONDITION(name, "bad param");
|
||||
|
||||
if(!mName)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// It is not necessary to Resolve because this info is read from manifest.
|
||||
*name = mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void getIIDShared ([shared, retval] out nsIIDPtrShared iid); */
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::GetIIDShared(const nsIID * *iid)
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetIIDShared(const nsIID * *iid)
|
||||
{
|
||||
NS_PRECONDITION(iid, "bad param");
|
||||
|
||||
// It is not necessary to Resolve because this info is read from manifest.
|
||||
*iid = &mIID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* PRBool hasAncestor (in nsIIDPtr iid); */
|
||||
NS_IMETHODIMP
|
||||
xptiInterfaceInfo::HasAncestor(const nsIID * iid, PRBool *_retval)
|
||||
nsresult
|
||||
xptiInterfaceEntry::HasAncestor(const nsIID * iid, PRBool *_retval)
|
||||
{
|
||||
NS_PRECONDITION(iid, "bad param");
|
||||
NS_PRECONDITION(_retval, "bad param");
|
||||
|
||||
*_retval = PR_FALSE;
|
||||
|
||||
for(xptiInterfaceInfo* current = this;
|
||||
for(xptiInterfaceEntry* current = this;
|
||||
current;
|
||||
current = current->mInterface->mParent)
|
||||
{
|
||||
@ -713,3 +695,106 @@ xptiInterfaceInfo::HasAncestor(const nsIID * iid, PRBool *_retval)
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
nsresult
|
||||
xptiInterfaceEntry::GetInterfaceInfo(xptiInterfaceInfo** info)
|
||||
{
|
||||
nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
|
||||
LOG_INFO_MONITOR_ENTRY;
|
||||
|
||||
#ifdef SHOW_INFO_COUNT_STATS
|
||||
static int callCount = 0;
|
||||
if(!(++callCount%100))
|
||||
printf("iiii %d xptiInterfaceInfos currently alive\n", DEBUG_CurrentInfos);
|
||||
#endif
|
||||
|
||||
if(!mInfo)
|
||||
{
|
||||
mInfo = new xptiInterfaceInfo(this);
|
||||
if(!mInfo)
|
||||
{
|
||||
*info = nsnull;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(*info = mInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
xptiInterfaceEntry::LockedInvalidateInterfaceInfo()
|
||||
{
|
||||
if(mInfo)
|
||||
{
|
||||
mInfo->Invalidate();
|
||||
mInfo = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE1(xptiInterfaceInfo, nsIInterfaceInfo)
|
||||
|
||||
xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry)
|
||||
: mEntry(entry), mParent(nsnull)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
LOG_INFO_CREATE(this);
|
||||
}
|
||||
|
||||
xptiInterfaceInfo::~xptiInterfaceInfo()
|
||||
{
|
||||
LOG_INFO_DESTROY(this);
|
||||
NS_IF_RELEASE(mParent);
|
||||
NS_ASSERTION(!mEntry, "bad state in dtor");
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
xptiInterfaceInfo::AddRef(void)
|
||||
{
|
||||
nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt);
|
||||
NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this));
|
||||
return cnt;
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
xptiInterfaceInfo::Release(void)
|
||||
{
|
||||
xptiInterfaceEntry* entry = mEntry;
|
||||
nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt);
|
||||
NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo");
|
||||
if(!cnt)
|
||||
{
|
||||
nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
|
||||
LOG_INFO_MONITOR_ENTRY;
|
||||
|
||||
// If GetInterfaceInfo added and *released* a reference before we
|
||||
// acquired the monitor then 'this' might already be dead. In that
|
||||
// case we would not want to try to access any instance data. We
|
||||
// would want to bail immediately. If 'this' is already dead then the
|
||||
// entry will no longer have a pointer to 'this'. So, we can protect
|
||||
// ourselves from danger without more aggressive locking.
|
||||
if(entry && !entry->InterfaceInfoEquals(this))
|
||||
return 0;
|
||||
|
||||
// If GetInterfaceInfo added a reference before we acquired the monitor
|
||||
// then we want to bail out of here without destorying the object.
|
||||
if(mRefCnt)
|
||||
return 1;
|
||||
|
||||
if(mEntry)
|
||||
{
|
||||
mEntry->LockedInterfaceInfoDeathNotification();
|
||||
mEntry = nsnull;
|
||||
}
|
||||
|
||||
NS_DELETEXPCOM(this);
|
||||
return 0;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -20,6 +20,8 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe <mccabe@netscape.com>
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -100,7 +102,8 @@ xptiInterfaceInfoManager::IsValid()
|
||||
{
|
||||
return mWorkingSet.IsValid() &&
|
||||
mResolveLock &&
|
||||
mAutoRegLock;
|
||||
mAutoRegLock &&
|
||||
mInfoMonitor;
|
||||
}
|
||||
|
||||
xptiInterfaceInfoManager::xptiInterfaceInfoManager(nsISupportsArray* aSearchPath)
|
||||
@ -108,6 +111,7 @@ xptiInterfaceInfoManager::xptiInterfaceInfoManager(nsISupportsArray* aSearchPath
|
||||
mOpenLogFile(nsnull),
|
||||
mResolveLock(PR_NewLock()),
|
||||
mAutoRegLock(PR_NewLock()),
|
||||
mInfoMonitor(nsAutoMonitor::NewMonitor("xptiInfoMonitor")),
|
||||
mSearchPath(aSearchPath)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
@ -158,6 +162,12 @@ xptiInterfaceInfoManager::~xptiInterfaceInfoManager()
|
||||
PR_DestroyLock(mResolveLock);
|
||||
if(mAutoRegLock)
|
||||
PR_DestroyLock(mAutoRegLock);
|
||||
if(mInfoMonitor)
|
||||
nsAutoMonitor::DestroyMonitor(mInfoMonitor);
|
||||
|
||||
#ifdef DEBUG
|
||||
xptiInterfaceInfo::DEBUG_ShutdownNotification();
|
||||
#endif
|
||||
}
|
||||
|
||||
static PRBool
|
||||
@ -210,10 +220,9 @@ PRBool xptiInterfaceInfoManager::BuildFileSearchPath(nsISupportsArray** aPath)
|
||||
static int callCount = 0;
|
||||
NS_ASSERTION(!callCount++, "Expected only one call!");
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsISupportsArray> searchPath =
|
||||
do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
|
||||
|
||||
|
||||
nsCOMPtr<nsISupportsArray> searchPath;
|
||||
NS_NewISupportsArray(getter_AddRefs(searchPath));
|
||||
if(!searchPath)
|
||||
return PR_FALSE;
|
||||
|
||||
@ -486,13 +495,13 @@ xptiInterfaceInfoManager::LoadFile(const xptiTypelib& aTypelibRecord,
|
||||
if(aTypelibRecord.IsZip())
|
||||
{
|
||||
// This also allocs zipItem.GetGuts() used below.
|
||||
if(!zipItem->SetHeader(header))
|
||||
if(!zipItem->SetHeader(header, aWorkingSet))
|
||||
return PR_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This also allocs fileRecord.GetGuts() used below.
|
||||
if(!fileRecord->SetHeader(header))
|
||||
if(!fileRecord->SetHeader(header, aWorkingSet))
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
@ -505,34 +514,40 @@ xptiInterfaceInfoManager::LoadFile(const xptiTypelib& aTypelibRecord,
|
||||
{ 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
|
||||
|
||||
XPTInterfaceDirectoryEntry* iface = header->interface_directory + i;
|
||||
xptiInterfaceInfo* info;
|
||||
|
||||
xptiHashEntry* hashEntry;
|
||||
|
||||
if(!iface->iid.Equals(zeroIID))
|
||||
{
|
||||
info = (xptiInterfaceInfo*)
|
||||
PL_HashTableLookup(aWorkingSet->mIIDTable, &iface->iid);
|
||||
hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(aWorkingSet->mIIDTable,
|
||||
&iface->iid, PL_DHASH_LOOKUP);
|
||||
}
|
||||
else
|
||||
{
|
||||
info = (xptiInterfaceInfo*)
|
||||
PL_HashTableLookup(aWorkingSet->mNameTable, iface->name);
|
||||
hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(aWorkingSet->mNameTable,
|
||||
iface->name, PL_DHASH_LOOKUP);
|
||||
}
|
||||
|
||||
if(!info)
|
||||
xptiInterfaceEntry* entry =
|
||||
PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
|
||||
|
||||
if(!entry)
|
||||
{
|
||||
// This one is just not resolved anywhere!
|
||||
continue;
|
||||
}
|
||||
|
||||
if(aTypelibRecord.IsZip())
|
||||
zipItem->GetGuts()->SetInfoAt(i, info);
|
||||
zipItem->GetGuts()->SetEntryAt(i, entry);
|
||||
else
|
||||
fileRecord->GetGuts()->SetInfoAt(i, info);
|
||||
fileRecord->GetGuts()->SetEntryAt(i, entry);
|
||||
|
||||
XPTInterfaceDescriptor* descriptor = iface->interface_descriptor;
|
||||
|
||||
if(descriptor && aTypelibRecord.Equals(info->GetTypelibRecord()))
|
||||
info->PartiallyResolveLocked(descriptor, aWorkingSet);
|
||||
if(descriptor && aTypelibRecord.Equals(entry->GetTypelibRecord()))
|
||||
entry->PartiallyResolveLocked(descriptor, aWorkingSet);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -588,7 +603,6 @@ xptiSortFileList(const void * p1, const void *p2, void * closure)
|
||||
nsILocalFile* pFile2 = *((nsILocalFile**) p2);
|
||||
SortData* data = (SortData*) closure;
|
||||
|
||||
|
||||
nsXPIDLCString name1;
|
||||
nsXPIDLCString name2;
|
||||
|
||||
@ -673,7 +687,6 @@ xptiInterfaceInfoManager::BuildOrderedFileArray(nsISupportsArray* aSearchPath,
|
||||
// will preceed all zipfile of those files not already in the working set.
|
||||
// To do this we will do a fancy sort on a copy of aFileList.
|
||||
|
||||
|
||||
nsILocalFile** orderedFileList = nsnull;
|
||||
PRUint32 countOfFilesInFileList;
|
||||
PRUint32 i;
|
||||
@ -917,29 +930,29 @@ xptiInterfaceInfoManager::AddOnlyNewFilesFromFileList(nsISupportsArray* aSearchP
|
||||
|
||||
for(PRUint16 k = 0; k < header->num_interfaces; k++)
|
||||
{
|
||||
xptiInterfaceInfo* info = nsnull;
|
||||
xptiInterfaceEntry* entry = nsnull;
|
||||
|
||||
if(!VerifyAndAddInterfaceIfNew(aWorkingSet,
|
||||
header->interface_directory + k,
|
||||
typelibRecord,
|
||||
&info))
|
||||
if(!VerifyAndAddEntryIfNew(aWorkingSet,
|
||||
header->interface_directory + k,
|
||||
typelibRecord,
|
||||
&entry))
|
||||
return PR_FALSE;
|
||||
|
||||
if(!info)
|
||||
if(!entry)
|
||||
continue;
|
||||
|
||||
// If this is the first interface we found for this file then
|
||||
// setup the fileRecord for the header and infos.
|
||||
if(!AddedFile)
|
||||
{
|
||||
if(!fileRecord.SetHeader(header))
|
||||
if(!fileRecord.SetHeader(header, aWorkingSet))
|
||||
{
|
||||
// XXX that would be bad.
|
||||
return PR_FALSE;
|
||||
}
|
||||
AddedFile = PR_TRUE;
|
||||
}
|
||||
fileRecord.GetGuts()->SetInfoAt(k, info);
|
||||
fileRecord.GetGuts()->SetEntryAt(k, entry);
|
||||
}
|
||||
|
||||
// This will correspond to typelibRecord above.
|
||||
@ -1054,29 +1067,29 @@ xptiInterfaceInfoManager::DoFullValidationMergeFromFileList(nsISupportsArray* aS
|
||||
|
||||
for(PRUint16 k = 0; k < header->num_interfaces; k++)
|
||||
{
|
||||
xptiInterfaceInfo* info = nsnull;
|
||||
xptiInterfaceEntry* entry = nsnull;
|
||||
|
||||
if(!VerifyAndAddInterfaceIfNew(aWorkingSet,
|
||||
header->interface_directory + k,
|
||||
typelibRecord,
|
||||
&info))
|
||||
if(!VerifyAndAddEntryIfNew(aWorkingSet,
|
||||
header->interface_directory + k,
|
||||
typelibRecord,
|
||||
&entry))
|
||||
return PR_FALSE;
|
||||
|
||||
if(!info)
|
||||
if(!entry)
|
||||
continue;
|
||||
|
||||
// If this is the first interface we found for this file then
|
||||
// setup the fileRecord for the header and infos.
|
||||
if(!AddedFile)
|
||||
{
|
||||
if(!fileRecord.SetHeader(header))
|
||||
if(!fileRecord.SetHeader(header, aWorkingSet))
|
||||
{
|
||||
// XXX that would be bad.
|
||||
return PR_FALSE;
|
||||
}
|
||||
AddedFile = PR_TRUE;
|
||||
}
|
||||
fileRecord.GetGuts()->SetInfoAt(k, info);
|
||||
fileRecord.GetGuts()->SetEntryAt(k, entry);
|
||||
}
|
||||
|
||||
// This will correspond to typelibRecord above.
|
||||
@ -1135,15 +1148,15 @@ xptiInterfaceInfoManager::FoundEntry(const char* entryName,
|
||||
|
||||
for(PRUint16 k = 0; k < header->num_interfaces; k++)
|
||||
{
|
||||
xptiInterfaceInfo* info = nsnull;
|
||||
xptiInterfaceEntry* entry = nsnull;
|
||||
|
||||
if(!VerifyAndAddInterfaceIfNew(aWorkingSet,
|
||||
header->interface_directory + k,
|
||||
typelibRecord,
|
||||
&info))
|
||||
if(!VerifyAndAddEntryIfNew(aWorkingSet,
|
||||
header->interface_directory + k,
|
||||
typelibRecord,
|
||||
&entry))
|
||||
return PR_FALSE;
|
||||
|
||||
if(!info)
|
||||
if(!entry)
|
||||
continue;
|
||||
|
||||
// If this is the first interface we found for this item
|
||||
@ -1151,14 +1164,14 @@ xptiInterfaceInfoManager::FoundEntry(const char* entryName,
|
||||
if(!countOfInterfacesAddedForItem)
|
||||
{
|
||||
// XXX fix this!
|
||||
if(!zipItemRecord.SetHeader(header))
|
||||
if(!zipItemRecord.SetHeader(header, aWorkingSet))
|
||||
{
|
||||
// XXX that would be bad.
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// zipItemRecord.GetGuts()->SetInfoAt(k, info);
|
||||
// zipItemRecord.GetGuts()->SetEntryAt(k, entry);
|
||||
++countOfInterfacesAddedForItem;
|
||||
}
|
||||
|
||||
@ -1179,15 +1192,15 @@ xptiInterfaceInfoManager::FoundEntry(const char* entryName,
|
||||
}
|
||||
|
||||
PRBool
|
||||
xptiInterfaceInfoManager::VerifyAndAddInterfaceIfNew(xptiWorkingSet* aWorkingSet,
|
||||
XPTInterfaceDirectoryEntry* iface,
|
||||
const xptiTypelib& typelibRecord,
|
||||
xptiInterfaceInfo** infoAdded)
|
||||
xptiInterfaceInfoManager::VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
|
||||
XPTInterfaceDirectoryEntry* iface,
|
||||
const xptiTypelib& typelibRecord,
|
||||
xptiInterfaceEntry** entryAdded)
|
||||
{
|
||||
NS_ASSERTION(iface, "loser!");
|
||||
NS_ASSERTION(infoAdded, "loser!");
|
||||
NS_ASSERTION(entryAdded, "loser!");
|
||||
|
||||
*infoAdded = nsnull;
|
||||
*entryAdded = nsnull;
|
||||
|
||||
if(!iface->interface_descriptor)
|
||||
{
|
||||
@ -1196,42 +1209,49 @@ xptiInterfaceInfoManager::VerifyAndAddInterfaceIfNew(xptiWorkingSet* aWorkingSet
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
xptiInterfaceInfo* info = (xptiInterfaceInfo*)
|
||||
PL_HashTableLookup(aWorkingSet->mIIDTable, &iface->iid);
|
||||
xptiHashEntry* hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(aWorkingSet->mIIDTable, &iface->iid, PL_DHASH_LOOKUP);
|
||||
|
||||
xptiInterfaceEntry* entry =
|
||||
PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
|
||||
|
||||
if(info)
|
||||
if(entry)
|
||||
{
|
||||
// XXX validate this info to find possible inconsistencies
|
||||
LOG_AUTOREG((" ignoring repeated interface: %s\n", iface->name));
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Build a new xptiInterfaceInfo object and hook it up.
|
||||
// Build a new xptiInterfaceEntry object and hook it up.
|
||||
|
||||
info = new xptiInterfaceInfo(iface->name, iface->iid,
|
||||
typelibRecord, aWorkingSet);
|
||||
if(!info)
|
||||
entry = xptiInterfaceEntry::NewEntry(iface->name, iface->iid,
|
||||
typelibRecord, aWorkingSet);
|
||||
if(!entry)
|
||||
{
|
||||
// XXX bad!
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_ADDREF(info);
|
||||
if(!info->IsValid())
|
||||
{
|
||||
// XXX bad!
|
||||
NS_RELEASE(info);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//XXX We should SetHeader too as part of the validation, no?
|
||||
info->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags));
|
||||
entry->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags));
|
||||
|
||||
// The name table now owns the reference we AddRef'd above
|
||||
PL_HashTableAdd(aWorkingSet->mNameTable, iface->name, info);
|
||||
PL_HashTableAdd(aWorkingSet->mIIDTable, &iface->iid, info);
|
||||
// Add our entry to the iid hashtable.
|
||||
|
||||
hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(aWorkingSet->mNameTable,
|
||||
entry->GetTheName(), PL_DHASH_ADD);
|
||||
if(hashEntry)
|
||||
hashEntry->value = entry;
|
||||
|
||||
*infoAdded = info;
|
||||
// Add our entry to the name hashtable.
|
||||
|
||||
hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(aWorkingSet->mIIDTable,
|
||||
entry->GetTheIID(), PL_DHASH_ADD);
|
||||
if(hashEntry)
|
||||
hashEntry->value = entry;
|
||||
|
||||
*entryAdded = entry;
|
||||
|
||||
LOG_AUTOREG((" added interface: %s\n", iface->name));
|
||||
|
||||
@ -1248,86 +1268,86 @@ struct TwoWorkingSets
|
||||
xptiWorkingSet* aDestWorkingSet;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
xpti_Merger(PLHashEntry *he, PRIntn i, void *arg)
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
xpti_Merger(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
PRUint32 number, void *arg)
|
||||
{
|
||||
xptiInterfaceInfo* srcInfo = (xptiInterfaceInfo*) he->value;
|
||||
xptiInterfaceEntry* srcEntry = ((xptiHashEntry*)hdr)->value;
|
||||
xptiWorkingSet* aSrcWorkingSet = ((TwoWorkingSets*)arg)->aSrcWorkingSet;
|
||||
xptiWorkingSet* aDestWorkingSet = ((TwoWorkingSets*)arg)->aDestWorkingSet;
|
||||
|
||||
xptiInterfaceInfo* destInfo = (xptiInterfaceInfo*)
|
||||
PL_HashTableLookup(aDestWorkingSet->mIIDTable, srcInfo->GetTheIID());
|
||||
xptiHashEntry* hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(aDestWorkingSet->mIIDTable,
|
||||
srcEntry->GetTheIID(), PL_DHASH_LOOKUP);
|
||||
|
||||
xptiInterfaceEntry* destEntry =
|
||||
PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
|
||||
|
||||
if(destInfo)
|
||||
if(destEntry)
|
||||
{
|
||||
// Let's see if this is referring to the same exact typelib
|
||||
|
||||
const char* destFilename =
|
||||
aDestWorkingSet->GetTypelibFileName(destInfo->GetTypelibRecord());
|
||||
aDestWorkingSet->GetTypelibFileName(destEntry->GetTypelibRecord());
|
||||
|
||||
const char* srcFilename =
|
||||
aSrcWorkingSet->GetTypelibFileName(srcInfo->GetTypelibRecord());
|
||||
aSrcWorkingSet->GetTypelibFileName(srcEntry->GetTypelibRecord());
|
||||
|
||||
if(0 == PL_strcmp(destFilename, srcFilename) &&
|
||||
(destInfo->GetTypelibRecord().GetZipItemIndex() ==
|
||||
srcInfo->GetTypelibRecord().GetZipItemIndex()))
|
||||
(destEntry->GetTypelibRecord().GetZipItemIndex() ==
|
||||
srcEntry->GetTypelibRecord().GetZipItemIndex()))
|
||||
{
|
||||
// This is the same item.
|
||||
// But... Let's make sure they didn't change the interface name.
|
||||
// There are wacky developers that do stuff like that!
|
||||
if(0 == PL_strcmp(destInfo->GetTheName(), srcInfo->GetTheName()))
|
||||
return HT_ENUMERATE_NEXT;
|
||||
if(0 == PL_strcmp(destEntry->GetTheName(), srcEntry->GetTheName()))
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
// else...
|
||||
|
||||
// We need to remove the old item before adding the new one below.
|
||||
|
||||
PL_HashTableRemove(aDestWorkingSet->mNameTable, destInfo->GetTheName());
|
||||
PL_HashTableRemove(aDestWorkingSet->mIIDTable, destInfo->GetTheIID());
|
||||
|
||||
// Release the one reference that was held by the name table.
|
||||
NS_RELEASE(destInfo);
|
||||
}
|
||||
|
||||
// Clone the xptiInterfaceInfo into our destination WorkingSet.
|
||||
// Clone the xptiInterfaceEntry into our destination WorkingSet.
|
||||
|
||||
xptiTypelib typelibRecord;
|
||||
|
||||
uint16 fileIndex = srcInfo->GetTypelibRecord().GetFileIndex();
|
||||
uint16 zipItemIndex = srcInfo->GetTypelibRecord().GetZipItemIndex();
|
||||
uint16 fileIndex = srcEntry->GetTypelibRecord().GetFileIndex();
|
||||
uint16 zipItemIndex = srcEntry->GetTypelibRecord().GetZipItemIndex();
|
||||
|
||||
fileIndex += aDestWorkingSet->mFileMergeOffsetMap[fileIndex];
|
||||
|
||||
// If it is not a zipItem, then the original index is fine.
|
||||
if(srcInfo->GetTypelibRecord().IsZip())
|
||||
if(srcEntry->GetTypelibRecord().IsZip())
|
||||
zipItemIndex += aDestWorkingSet->mZipItemMergeOffsetMap[zipItemIndex];
|
||||
|
||||
typelibRecord.Init(fileIndex, zipItemIndex);
|
||||
|
||||
destInfo = new xptiInterfaceInfo(*srcInfo, typelibRecord, aDestWorkingSet);
|
||||
|
||||
if(!destInfo)
|
||||
destEntry = xptiInterfaceEntry::NewEntry(*srcEntry, typelibRecord,
|
||||
aDestWorkingSet);
|
||||
if(!destEntry)
|
||||
{
|
||||
// XXX bad! should log
|
||||
return HT_ENUMERATE_NEXT;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_ADDREF(destInfo);
|
||||
if(!destInfo->IsValid())
|
||||
{
|
||||
// XXX bad! should log
|
||||
NS_RELEASE(destInfo);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
// The name table now owns the reference we AddRef'd above
|
||||
PL_HashTableAdd(aDestWorkingSet->mNameTable, destInfo->GetTheName(), destInfo);
|
||||
PL_HashTableAdd(aDestWorkingSet->mIIDTable, destInfo->GetTheIID(), destInfo);
|
||||
// Add our entry to the iid hashtable.
|
||||
|
||||
return HT_ENUMERATE_NEXT;
|
||||
hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(aDestWorkingSet->mNameTable,
|
||||
destEntry->GetTheName(), PL_DHASH_ADD);
|
||||
if(hashEntry)
|
||||
hashEntry->value = destEntry;
|
||||
|
||||
// Add our entry to the name hashtable.
|
||||
|
||||
hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(aDestWorkingSet->mIIDTable,
|
||||
destEntry->GetTheIID(), PL_DHASH_ADD);
|
||||
if(hashEntry)
|
||||
hashEntry->value = destEntry;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
xptiInterfaceInfoManager::MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
|
||||
xptiWorkingSet* aSrcWorkingSet)
|
||||
@ -1380,8 +1400,7 @@ xptiInterfaceInfoManager::MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
|
||||
|
||||
PRUint32 newIndex = aDestWorkingSet->GetFileCount();
|
||||
|
||||
aDestWorkingSet->AppendFile(
|
||||
xptiFile(srcFile, aDestWorkingSet, PR_FALSE));
|
||||
aDestWorkingSet->AppendFile(xptiFile(srcFile, aDestWorkingSet));
|
||||
|
||||
// Fixup the merge offset map.
|
||||
aDestWorkingSet->mFileMergeOffsetMap[i] = newIndex - i;
|
||||
@ -1434,7 +1453,7 @@ xptiInterfaceInfoManager::MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
|
||||
PRUint32 newIndex = aDestWorkingSet->GetZipItemCount();
|
||||
|
||||
aDestWorkingSet->AppendZipItem(
|
||||
xptiZipItem(srcZipItem, aDestWorkingSet, PR_FALSE));
|
||||
xptiZipItem(srcZipItem, aDestWorkingSet));
|
||||
|
||||
// Fixup the merge offset map.
|
||||
aDestWorkingSet->mZipItemMergeOffsetMap[i] = newIndex - i;
|
||||
@ -1445,7 +1464,7 @@ xptiInterfaceInfoManager::MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
|
||||
|
||||
TwoWorkingSets sets(aSrcWorkingSet, aDestWorkingSet);
|
||||
|
||||
PL_HashTableEnumerateEntries(aSrcWorkingSet->mNameTable, xpti_Merger, &sets);
|
||||
PL_DHashTableEnumerate(aSrcWorkingSet->mNameTable, xpti_Merger, &sets);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -1523,18 +1542,19 @@ xptiInterfaceInfoManager::WriteToLog(const char *fmt, ...)
|
||||
}
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
xpti_ResolvedFileNameLogger(PLHashEntry *he, PRIntn i, void *arg)
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
xpti_ResolvedFileNameLogger(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
PRUint32 number, void *arg)
|
||||
{
|
||||
xptiInterfaceInfo* ii = (xptiInterfaceInfo*) he->value;
|
||||
xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
|
||||
xptiInterfaceInfoManager* mgr = (xptiInterfaceInfoManager*) arg;
|
||||
|
||||
if(ii->IsFullyResolved())
|
||||
if(entry->IsFullyResolved())
|
||||
{
|
||||
xptiWorkingSet* aWorkingSet = mgr->GetWorkingSet();
|
||||
PRFileDesc* fd = mgr->GetOpenLogFile();
|
||||
|
||||
const xptiTypelib& typelib = ii->GetTypelibRecord();
|
||||
const xptiTypelib& typelib = entry->GetTypelibRecord();
|
||||
const char* filename =
|
||||
aWorkingSet->GetFileAt(typelib.GetFileIndex()).GetName();
|
||||
|
||||
@ -1543,15 +1563,15 @@ xpti_ResolvedFileNameLogger(PLHashEntry *he, PRIntn i, void *arg)
|
||||
const char* zipItemName =
|
||||
aWorkingSet->GetZipItemAt(typelib.GetZipItemIndex()).GetName();
|
||||
PR_fprintf(fd, "xpti used interface: %s from %s::%s\n",
|
||||
ii->GetTheName(), filename, zipItemName);
|
||||
entry->GetTheName(), filename, zipItemName);
|
||||
}
|
||||
else
|
||||
{
|
||||
PR_fprintf(fd, "xpti used interface: %s from %s\n",
|
||||
ii->GetTheName(), filename);
|
||||
entry->GetTheName(), filename);
|
||||
}
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1595,30 +1615,48 @@ xptiInterfaceInfoManager::LogStats()
|
||||
// Show name of each interface that was fully resolved and the name
|
||||
// of the file and (perhaps) zip from which it was loaded.
|
||||
|
||||
PL_HashTableEnumerateEntries(mWorkingSet.mNameTable,
|
||||
xpti_ResolvedFileNameLogger, this);
|
||||
PL_DHashTableEnumerate(mWorkingSet.mNameTable,
|
||||
xpti_ResolvedFileNameLogger, this);
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// this is a private helper
|
||||
static nsresult
|
||||
EntryToInfo(xptiInterfaceEntry* entry, nsIInterfaceInfo **_retval)
|
||||
{
|
||||
xptiInterfaceInfo* info;
|
||||
nsresult rv;
|
||||
|
||||
if(!entry)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = entry->GetInterfaceInfo(&info);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Transfer the AddRef done by GetInterfaceInfo.
|
||||
*_retval = NS_STATIC_CAST(nsIInterfaceInfo*, info);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIInterfaceInfo getInfoForIID (in nsIIDPtr iid); */
|
||||
NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval)
|
||||
{
|
||||
NS_ASSERTION(iid, "bad param");
|
||||
NS_ASSERTION(_retval, "bad param");
|
||||
|
||||
xptiInterfaceInfo* info = (xptiInterfaceInfo*)
|
||||
PL_HashTableLookup(mWorkingSet.mIIDTable, iid);
|
||||
xptiHashEntry* hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(mWorkingSet.mIIDTable, iid, PL_DHASH_LOOKUP);
|
||||
|
||||
if(!info)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
xptiInterfaceEntry* entry =
|
||||
PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
|
||||
|
||||
NS_ADDREF(*_retval = NS_STATIC_CAST(nsIInterfaceInfo*, info));
|
||||
return NS_OK;
|
||||
return EntryToInfo(entry, _retval);
|
||||
}
|
||||
|
||||
/* nsIInterfaceInfo getInfoForName (in string name); */
|
||||
@ -1627,17 +1665,13 @@ NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForName(const char *name, nsIInte
|
||||
NS_ASSERTION(name, "bad param");
|
||||
NS_ASSERTION(_retval, "bad param");
|
||||
|
||||
xptiInterfaceInfo* info = (xptiInterfaceInfo*)
|
||||
PL_HashTableLookup(mWorkingSet.mNameTable, name);
|
||||
xptiHashEntry* hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(mWorkingSet.mNameTable, name, PL_DHASH_LOOKUP);
|
||||
|
||||
if(!info)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
xptiInterfaceEntry* entry =
|
||||
PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
|
||||
|
||||
NS_ADDREF(*_retval = NS_STATIC_CAST(nsIInterfaceInfo*, info));
|
||||
return NS_OK;
|
||||
return EntryToInfo(entry, _retval);
|
||||
}
|
||||
|
||||
/* nsIIDPtr getIIDForName (in string name); */
|
||||
@ -1646,16 +1680,19 @@ NS_IMETHODIMP xptiInterfaceInfoManager::GetIIDForName(const char *name, nsIID *
|
||||
NS_ASSERTION(name, "bad param");
|
||||
NS_ASSERTION(_retval, "bad param");
|
||||
|
||||
xptiInterfaceInfo* info = (xptiInterfaceInfo*)
|
||||
PL_HashTableLookup(mWorkingSet.mNameTable, name);
|
||||
xptiHashEntry* hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(mWorkingSet.mNameTable, name, PL_DHASH_LOOKUP);
|
||||
|
||||
if(!info)
|
||||
xptiInterfaceEntry* entry =
|
||||
PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
|
||||
|
||||
if(!entry)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return info->GetIID(_retval);
|
||||
return entry->GetIID(_retval);
|
||||
}
|
||||
|
||||
/* string getNameForIID (in nsIIDPtr iid); */
|
||||
@ -1664,30 +1701,34 @@ NS_IMETHODIMP xptiInterfaceInfoManager::GetNameForIID(const nsIID * iid, char **
|
||||
NS_ASSERTION(iid, "bad param");
|
||||
NS_ASSERTION(_retval, "bad param");
|
||||
|
||||
xptiInterfaceInfo* info = (xptiInterfaceInfo*)
|
||||
PL_HashTableLookup(mWorkingSet.mIIDTable, iid);
|
||||
xptiHashEntry* hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(mWorkingSet.mIIDTable, iid, PL_DHASH_LOOKUP);
|
||||
|
||||
if(!info)
|
||||
xptiInterfaceEntry* entry =
|
||||
PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
|
||||
|
||||
if(!entry)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return info->GetName(_retval);
|
||||
return entry->GetName(_retval);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
xpti_ArrayAppender(PLHashEntry *he, PRIntn i, void *arg)
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
xpti_ArrayAppender(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
PRUint32 number, void *arg)
|
||||
{
|
||||
nsIInterfaceInfo* ii = (nsIInterfaceInfo*) he->value;
|
||||
xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
|
||||
nsISupportsArray* array = (nsISupportsArray*) arg;
|
||||
|
||||
// XXX nsSupportsArray.h shows that this method returns the wrong value!
|
||||
array->AppendElement(ii);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
nsCOMPtr<nsIInterfaceInfo> ii;
|
||||
if(NS_SUCCEEDED(EntryToInfo(entry, getter_AddRefs(ii))))
|
||||
array->AppendElement(ii);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
||||
/* nsIEnumerator enumerateInterfaces (); */
|
||||
NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfaces(nsIEnumerator **_retval)
|
||||
{
|
||||
@ -1696,13 +1737,50 @@ NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfaces(nsIEnumerator **_ret
|
||||
// the table using an nsISupportsArray and builds an enumerator for that.
|
||||
// We can afford this transient cost.
|
||||
|
||||
nsCOMPtr<nsISupportsArray> array =
|
||||
do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
|
||||
nsCOMPtr<nsISupportsArray> array;
|
||||
NS_NewISupportsArray(getter_AddRefs(array));
|
||||
if(!array)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
PL_HashTableEnumerateEntries(mWorkingSet.mNameTable, xpti_ArrayAppender,
|
||||
array);
|
||||
PL_DHashTableEnumerate(mWorkingSet.mNameTable, xpti_ArrayAppender, array);
|
||||
|
||||
return array->Enumerate(_retval);
|
||||
}
|
||||
|
||||
struct ArrayAndPrefix
|
||||
{
|
||||
nsISupportsArray* array;
|
||||
const char* prefix;
|
||||
PRUint32 length;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
xpti_ArrayPrefixAppender(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
PRUint32 number, void *arg)
|
||||
{
|
||||
xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
|
||||
ArrayAndPrefix* args = (ArrayAndPrefix*) arg;
|
||||
|
||||
const char* name = entry->GetTheName();
|
||||
if(name != PL_strnstr(name, args->prefix, args->length))
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
nsCOMPtr<nsIInterfaceInfo> ii;
|
||||
if(NS_SUCCEEDED(EntryToInfo(entry, getter_AddRefs(ii))))
|
||||
args->array->AppendElement(ii);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/* nsIEnumerator enumerateInterfacesWhoseNamesStartWith (in string prefix); */
|
||||
NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfacesWhoseNamesStartWith(const char *prefix, nsIEnumerator **_retval)
|
||||
{
|
||||
nsCOMPtr<nsISupportsArray> array;
|
||||
NS_NewISupportsArray(getter_AddRefs(array));
|
||||
if(!array)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
ArrayAndPrefix args = {array, prefix, PL_strlen(prefix)};
|
||||
PL_DHashTableEnumerate(mWorkingSet.mNameTable, xpti_ArrayPrefixAppender, &args);
|
||||
|
||||
return array->Enumerate(_retval);
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe <mccabe@netscape.com>
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -58,7 +60,8 @@ static const int g_VERSION_MINOR = 0;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static PRBool GetCurrentAppDirString(xptiInterfaceInfoManager* aMgr, char** aStr)
|
||||
static PRBool
|
||||
GetCurrentAppDirString(xptiInterfaceInfoManager* aMgr, char** aStr)
|
||||
{
|
||||
nsCOMPtr<nsILocalFile> appDir;
|
||||
aMgr->GetApplicationDir(getter_AddRefs(appDir));
|
||||
@ -67,53 +70,52 @@ static PRBool GetCurrentAppDirString(xptiInterfaceInfoManager* aMgr, char** aStr
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool CurrentAppDirMatchesPersistentDescriptor(xptiInterfaceInfoManager* aMgr, const char* inStr)
|
||||
static PRBool
|
||||
CurrentAppDirMatchesPersistentDescriptor(xptiInterfaceInfoManager* aMgr,
|
||||
const char* inStr)
|
||||
{
|
||||
nsCOMPtr<nsILocalFile> appDir;
|
||||
aMgr->GetApplicationDir(getter_AddRefs(appDir));
|
||||
|
||||
nsCOMPtr<nsILocalFile> descDir;
|
||||
nsresult rv = NS_NewLocalFile(nsnull, PR_FALSE, getter_AddRefs(descDir));
|
||||
if (NS_FAILED(rv))
|
||||
if(NS_FAILED(rv))
|
||||
return PR_FALSE;
|
||||
|
||||
rv = descDir->SetPersistentDescriptor(inStr);
|
||||
if (NS_FAILED(rv))
|
||||
if(NS_FAILED(rv))
|
||||
return PR_FALSE;
|
||||
|
||||
PRBool matches;
|
||||
rv = appDir->Equals(descDir, &matches);
|
||||
return (NS_SUCCEEDED(rv) && matches);
|
||||
return NS_SUCCEEDED(rv) && matches;
|
||||
}
|
||||
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
xpti_InterfaceWriter(PLHashEntry *he, PRIntn i, void *arg)
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
xpti_InterfaceWriter(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
PRUint32 number, void *arg)
|
||||
{
|
||||
xptiInterfaceInfo* info = (xptiInterfaceInfo*) he->value;
|
||||
xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
|
||||
PRFileDesc* fd = (PRFileDesc*) arg;
|
||||
|
||||
if(!info->IsValid())
|
||||
return HT_ENUMERATE_STOP;
|
||||
|
||||
char* iidStr = info->GetTheIID()->ToString();
|
||||
char* iidStr = entry->GetTheIID()->ToString();
|
||||
if(!iidStr)
|
||||
return HT_ENUMERATE_STOP;
|
||||
return PL_DHASH_STOP;
|
||||
|
||||
const xptiTypelib& typelib = info->GetTypelibRecord();
|
||||
const xptiTypelib& typelib = entry->GetTypelibRecord();
|
||||
|
||||
PRBool success = PR_fprintf(fd, "%d,%s,%s,%d,%d,%d\n",
|
||||
(int) i,
|
||||
info->GetTheName(),
|
||||
(int) number,
|
||||
entry->GetTheName(),
|
||||
iidStr,
|
||||
(int) typelib.GetFileIndex(),
|
||||
(int) (typelib.IsZip() ?
|
||||
typelib.GetZipItemIndex() : -1),
|
||||
(int) info->GetScriptableFlag());
|
||||
(int) entry->GetScriptableFlag());
|
||||
|
||||
nsCRT::free(iidStr);
|
||||
|
||||
return success ? HT_ENUMERATE_NEXT : HT_ENUMERATE_STOP;
|
||||
return success ? PL_DHASH_NEXT : PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
|
||||
@ -136,8 +138,7 @@ PRBool xptiManifest::Write(xptiInterfaceInfoManager* aMgr,
|
||||
if(NS_FAILED(tempFile->Append(g_TempManifestFilename)))
|
||||
return PR_FALSE;
|
||||
|
||||
// exist via "goto out;" from here on...
|
||||
|
||||
// All exits via "goto out;" from here on...
|
||||
|
||||
if(NS_FAILED(tempFile->
|
||||
OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
|
||||
@ -230,16 +231,16 @@ PRBool xptiManifest::Write(xptiInterfaceInfoManager* aMgr,
|
||||
|
||||
// write the Interfaces list
|
||||
|
||||
interfaceCount = aWorkingSet->mNameTable->nentries;
|
||||
interfaceCount = aWorkingSet->mNameTable->entryCount;
|
||||
|
||||
if(!PR_fprintf(fd, "\n[%s,%d]\n",
|
||||
g_TOKEN_Interfaces,
|
||||
(int) interfaceCount))
|
||||
goto out;
|
||||
|
||||
if(interfaceCount !=
|
||||
PL_HashTableEnumerateEntries(aWorkingSet->mNameTable,
|
||||
xpti_InterfaceWriter, fd))
|
||||
if(interfaceCount != (PRIntn)
|
||||
PL_DHashTableEnumerate(aWorkingSet->mNameTable,
|
||||
xpti_InterfaceWriter, fd))
|
||||
goto out;
|
||||
|
||||
|
||||
@ -318,7 +319,7 @@ ReadManifestIntoMemory(xptiInterfaceInfoManager* aMgr,
|
||||
if (!whole)
|
||||
return nsnull;
|
||||
|
||||
// all exits from on here should be via 'goto out'
|
||||
// All exits from on here should be via 'goto out'
|
||||
|
||||
if(NS_FAILED(aFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd)) || !fd)
|
||||
goto out;
|
||||
@ -463,6 +464,7 @@ PRBool xptiManifest::Read(xptiInterfaceInfoManager* aMgr,
|
||||
PRBool succeeded = PR_FALSE;
|
||||
PRUint32 flen;
|
||||
ManifestLineReader reader;
|
||||
xptiHashEntry* hashEntry;
|
||||
int headerCount = 0;
|
||||
int dirCount = 0;
|
||||
int fileCount = 0;
|
||||
@ -481,7 +483,7 @@ PRBool xptiManifest::Read(xptiInterfaceInfoManager* aMgr,
|
||||
|
||||
reader.Init(whole, flen);
|
||||
|
||||
// all exits from on here should be via 'goto out'
|
||||
// All exits from here on should be via 'goto out'
|
||||
|
||||
// Look for "Header" section
|
||||
|
||||
@ -680,7 +682,7 @@ PRBool xptiManifest::Read(xptiInterfaceInfoManager* aMgr,
|
||||
int fileIndex;
|
||||
int zipItemIndex;
|
||||
nsIID iid;
|
||||
xptiInterfaceInfo* info;
|
||||
xptiInterfaceEntry* entry;
|
||||
xptiTypelib typelibRecord;
|
||||
|
||||
if(!reader.NextLine())
|
||||
@ -723,23 +725,29 @@ PRBool xptiManifest::Read(xptiInterfaceInfoManager* aMgr,
|
||||
typelibRecord.Init(fileIndex);
|
||||
else
|
||||
typelibRecord.Init(fileIndex, zipItemIndex);
|
||||
info = new xptiInterfaceInfo(values[1], iid, typelibRecord, aWorkingSet);
|
||||
if(!info)
|
||||
|
||||
entry = xptiInterfaceEntry::NewEntry(values[1], iid, typelibRecord,
|
||||
aWorkingSet);
|
||||
if(!entry)
|
||||
goto out;
|
||||
|
||||
NS_ADDREF(info);
|
||||
if(!info->IsValid())
|
||||
{
|
||||
// XXX bad!
|
||||
NS_RELEASE(info);
|
||||
goto out;
|
||||
}
|
||||
entry->SetScriptableFlag(flags==1);
|
||||
|
||||
info->SetScriptableFlag(flags==1);
|
||||
// Add our entry to the iid hashtable.
|
||||
|
||||
// The name table now owns the reference we AddRef'd above
|
||||
PL_HashTableAdd(aWorkingSet->mNameTable, info->GetTheName(), info);
|
||||
PL_HashTableAdd(aWorkingSet->mIIDTable, info->GetTheIID(), info);
|
||||
hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(aWorkingSet->mNameTable,
|
||||
entry->GetTheName(), PL_DHASH_ADD);
|
||||
if(hashEntry)
|
||||
hashEntry->value = entry;
|
||||
|
||||
// Add our entry to the name hashtable.
|
||||
|
||||
hashEntry = (xptiHashEntry*)
|
||||
PL_DHashTableOperate(aWorkingSet->mIIDTable,
|
||||
entry->GetTheIID(), PL_DHASH_ADD);
|
||||
if(hashEntry)
|
||||
hashEntry->value = entry;
|
||||
}
|
||||
|
||||
// success!
|
||||
|
@ -20,6 +20,8 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe <mccabe@netscape.com>
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -58,9 +60,9 @@ static const xptiFileTypeEntry g_Entries[] =
|
||||
xptiFileType::Type xptiFileType::GetType(const char* name)
|
||||
{
|
||||
NS_ASSERTION(name, "loser!");
|
||||
int len = PL_strlen(name);
|
||||
for(const xptiFileTypeEntry* p = g_Entries; p->name; p++)
|
||||
{
|
||||
int len = PL_strlen(name);
|
||||
if(len > p->len && 0 == PL_strcasecmp(p->name, &(name[len - p->len])))
|
||||
return p->type;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe <mccabe@netscape.com>
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -39,78 +41,23 @@
|
||||
|
||||
#include "xptiprivate.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(xptiTypelibGuts)
|
||||
// static
|
||||
xptiTypelibGuts*
|
||||
xptiTypelibGuts::NewGuts(XPTHeader* aHeader,
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
{
|
||||
NS_ASSERTION(aHeader, "bad param");
|
||||
void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
|
||||
sizeof(xptiTypelibGuts) +
|
||||
(sizeof(xptiInterfaceEntry*) *
|
||||
(aHeader->num_interfaces - 1)));
|
||||
if(!place)
|
||||
return nsnull;
|
||||
return new(place) xptiTypelibGuts(aHeader);
|
||||
}
|
||||
|
||||
xptiTypelibGuts::xptiTypelibGuts(XPTHeader* aHeader)
|
||||
: mHeader(aHeader),
|
||||
mInfoArray(nsnull)
|
||||
: mHeader(aHeader)
|
||||
{
|
||||
MOZ_COUNT_CTOR(xptiTypelibGuts);
|
||||
|
||||
NS_ASSERTION(mHeader, "bad param");
|
||||
|
||||
if(mHeader->num_interfaces)
|
||||
{
|
||||
mInfoArray = new xptiInterfaceInfo*[GetInfoCount()];
|
||||
if(mInfoArray)
|
||||
memset(mInfoArray, 0, sizeof(xptiInterfaceInfo*) * GetInfoCount());
|
||||
else
|
||||
mHeader = nsnull;
|
||||
}
|
||||
// empty
|
||||
}
|
||||
|
||||
xptiTypelibGuts::~xptiTypelibGuts()
|
||||
{
|
||||
MOZ_COUNT_DTOR(xptiTypelibGuts);
|
||||
|
||||
if(mHeader && mInfoArray)
|
||||
for(PRUint16 i = 0; i < GetInfoCount(); ++i)
|
||||
NS_IF_RELEASE(mInfoArray[i]);
|
||||
delete [] mInfoArray;
|
||||
}
|
||||
|
||||
xptiTypelibGuts*
|
||||
xptiTypelibGuts::Clone()
|
||||
{
|
||||
xptiTypelibGuts* clone = new xptiTypelibGuts(mHeader);
|
||||
if(clone && clone->IsValid())
|
||||
for(PRUint16 i = 0; i < GetInfoCount(); ++i)
|
||||
clone->SetInfoAt(i, GetInfoAtNoAddRef(i));
|
||||
return clone;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xptiTypelibGuts::GetInfoAt(PRUint16 i, xptiInterfaceInfo** ptr)
|
||||
{
|
||||
NS_ASSERTION(mHeader,"bad state!");
|
||||
NS_ASSERTION(mInfoArray,"bad state!");
|
||||
NS_ASSERTION(i < GetInfoCount(),"bad param!");
|
||||
NS_ASSERTION(ptr,"bad param!");
|
||||
|
||||
NS_IF_ADDREF(*ptr = mInfoArray[i]);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
xptiInterfaceInfo*
|
||||
xptiTypelibGuts::GetInfoAtNoAddRef(PRUint16 i)
|
||||
{
|
||||
NS_ASSERTION(mHeader,"bad state!");
|
||||
NS_ASSERTION(mInfoArray,"bad state!");
|
||||
NS_ASSERTION(i < GetInfoCount(),"bad param!");
|
||||
|
||||
return mInfoArray[i];
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
xptiTypelibGuts::SetInfoAt(PRUint16 i, xptiInterfaceInfo* ptr)
|
||||
{
|
||||
NS_ASSERTION(mHeader,"bad state!");
|
||||
NS_ASSERTION(mInfoArray,"bad state!");
|
||||
NS_ASSERTION(i < GetInfoCount(),"bad param!");
|
||||
|
||||
NS_IF_ADDREF(ptr);
|
||||
NS_IF_RELEASE(mInfoArray[i]);
|
||||
mInfoArray[i] = ptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe <mccabe@netscape.com>
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -43,17 +45,74 @@
|
||||
#define XPTI_STRUCT_ARENA_BLOCK_SIZE (1024 * 1)
|
||||
#define XPTI_HASHTABLE_SIZE 128
|
||||
|
||||
PR_STATIC_CALLBACK(PLHashNumber)
|
||||
xpti_HashIID(const void *key)
|
||||
/***************************************************************************/
|
||||
|
||||
PR_STATIC_CALLBACK(const void*)
|
||||
IIDGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
|
||||
{
|
||||
return ((nsID*)key)->m0;
|
||||
return ((xptiHashEntry*)entry)->value->GetTheIID();
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
xpti_CompareIIDs(const void *v1, const void *v2)
|
||||
PR_STATIC_CALLBACK(PLDHashNumber)
|
||||
IIDHash(PLDHashTable *table, const void *key)
|
||||
{
|
||||
return (PRIntn) ((const nsID*)v1)->Equals(*((const nsID*)v2));
|
||||
}
|
||||
return (PLDHashNumber) ((const nsIID*)key)->m0;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
IIDMatch(PLDHashTable *table,
|
||||
const PLDHashEntryHdr *entry,
|
||||
const void *key)
|
||||
{
|
||||
const nsIID* iid1 = ((xptiHashEntry*)entry)->value->GetTheIID();
|
||||
const nsIID* iid2 = (const nsIID*)key;
|
||||
|
||||
return iid1 == iid2 || iid1->Equals(*iid2);
|
||||
}
|
||||
|
||||
static struct PLDHashTableOps IIDTableOps =
|
||||
{
|
||||
PL_DHashAllocTable,
|
||||
PL_DHashFreeTable,
|
||||
IIDGetKey,
|
||||
IIDHash,
|
||||
IIDMatch,
|
||||
PL_DHashMoveEntryStub,
|
||||
PL_DHashClearEntryStub,
|
||||
PL_DHashFinalizeStub
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
PR_STATIC_CALLBACK(const void*)
|
||||
NameGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
|
||||
{
|
||||
return ((xptiHashEntry*)entry)->value->GetTheName();
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
NameMatch(PLDHashTable *table,
|
||||
const PLDHashEntryHdr *entry,
|
||||
const void *key)
|
||||
{
|
||||
const char* str1 = ((xptiHashEntry*)entry)->value->GetTheName();
|
||||
const char* str2 = (const char*) key;
|
||||
return str1 == str2 || 0 == PL_strcmp(str1, str2);
|
||||
}
|
||||
|
||||
static struct PLDHashTableOps NameTableOps =
|
||||
{
|
||||
PL_DHashAllocTable,
|
||||
PL_DHashFreeTable,
|
||||
NameGetKey,
|
||||
PL_DHashStringKey,
|
||||
NameMatch,
|
||||
PL_DHashMoveEntryStub,
|
||||
PL_DHashClearEntryStub,
|
||||
PL_DHashFinalizeStub
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(xptiWorkingSet)
|
||||
|
||||
@ -69,14 +128,12 @@ xptiWorkingSet::xptiWorkingSet(nsISupportsArray* aDirectories)
|
||||
mStructArena(XPT_NewArena(XPTI_STRUCT_ARENA_BLOCK_SIZE, sizeof(double),
|
||||
"xptiWorkingSet structs")),
|
||||
mDirectories(aDirectories),
|
||||
mNameTable(PL_NewHashTable(XPTI_HASHTABLE_SIZE, PL_HashString,
|
||||
PL_CompareStrings, PL_CompareValues,
|
||||
nsnull, nsnull)),
|
||||
mIIDTable(PL_NewHashTable(XPTI_HASHTABLE_SIZE, xpti_HashIID,
|
||||
xpti_CompareIIDs, PL_CompareValues,
|
||||
nsnull, nsnull)),
|
||||
mFileMergeOffsetMap(nsnull),
|
||||
mZipItemMergeOffsetMap(nsnull)
|
||||
mNameTable(PL_NewDHashTable(&NameTableOps, nsnull, sizeof(xptiHashEntry),
|
||||
XPTI_HASHTABLE_SIZE)),
|
||||
mIIDTable(PL_NewDHashTable(&IIDTableOps, nsnull, sizeof(xptiHashEntry),
|
||||
XPTI_HASHTABLE_SIZE)),
|
||||
mFileMergeOffsetMap(nsnull),
|
||||
mZipItemMergeOffsetMap(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(xptiWorkingSet);
|
||||
// do nothing else...
|
||||
@ -93,43 +150,40 @@ xptiWorkingSet::IsValid() const
|
||||
mIIDTable;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
xpti_Remover(PLHashEntry *he, PRIntn i, void *arg)
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
xpti_Remover(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
PRUint32 number, void *arg)
|
||||
{
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
xpti_ReleaseAndRemover(PLHashEntry *he, PRIntn i, void *arg)
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
xpti_Invalidator(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
PRUint32 number, void *arg)
|
||||
{
|
||||
nsIInterfaceInfo* ii = (nsIInterfaceInfo*) he->value;
|
||||
NS_RELEASE(ii);
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
xpti_Invalidator(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
((xptiInterfaceInfo*)he->value)->Invalidate();
|
||||
return HT_ENUMERATE_NEXT;
|
||||
xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
|
||||
entry->LockedInvalidateInterfaceInfo();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
xptiWorkingSet::InvalidateInterfaceInfos()
|
||||
{
|
||||
if(mNameTable)
|
||||
PL_HashTableEnumerateEntries(mNameTable, xpti_Invalidator, nsnull);
|
||||
{
|
||||
nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
|
||||
PL_DHashTableEnumerate(mNameTable, xpti_Invalidator, nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xptiWorkingSet::ClearHashTables()
|
||||
{
|
||||
if(mNameTable)
|
||||
PL_HashTableEnumerateEntries(mNameTable, xpti_Remover, nsnull);
|
||||
PL_DHashTableEnumerate(mNameTable, xpti_Remover, nsnull);
|
||||
|
||||
if(mIIDTable)
|
||||
PL_HashTableEnumerateEntries(mIIDTable, xpti_ReleaseAndRemover, nsnull);
|
||||
PL_DHashTableEnumerate(mIIDTable, xpti_Remover, nsnull);
|
||||
}
|
||||
|
||||
void
|
||||
@ -161,10 +215,10 @@ xptiWorkingSet::~xptiWorkingSet()
|
||||
ClearHashTables();
|
||||
|
||||
if(mNameTable)
|
||||
PL_HashTableDestroy(mNameTable);
|
||||
PL_DHashTableDestroy(mNameTable);
|
||||
|
||||
if(mIIDTable)
|
||||
PL_HashTableDestroy(mIIDTable);
|
||||
PL_DHashTableDestroy(mIIDTable);
|
||||
|
||||
if(mFileArray)
|
||||
delete [] mFileArray;
|
||||
@ -363,15 +417,15 @@ PRBool xptiWorkingSet::DirectoryAtMatchesPersistentDescriptor(PRUint32 i,
|
||||
|
||||
nsCOMPtr<nsILocalFile> descDir;
|
||||
nsresult rv = NS_NewLocalFile(nsnull, PR_FALSE, getter_AddRefs(descDir));
|
||||
if (NS_FAILED(rv))
|
||||
if(NS_FAILED(rv))
|
||||
return PR_FALSE;
|
||||
|
||||
rv = descDir->SetPersistentDescriptor(inDesc);
|
||||
if (NS_FAILED(rv))
|
||||
if(NS_FAILED(rv))
|
||||
return PR_FALSE;
|
||||
|
||||
PRBool matches;
|
||||
rv = dir->Equals(descDir, &matches);
|
||||
return (NS_SUCCEEDED(rv) && matches);
|
||||
return NS_SUCCEEDED(rv) && matches;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe <mccabe@netscape.com>
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -42,7 +44,11 @@
|
||||
MOZ_DECL_CTOR_COUNTER(xptiZipItem)
|
||||
|
||||
xptiZipItem::xptiZipItem()
|
||||
: mName(nsnull),
|
||||
:
|
||||
#ifdef DEBUG
|
||||
mDEBUG_WorkingSet(nsnull),
|
||||
#endif
|
||||
mName(nsnull),
|
||||
mGuts(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(xptiZipItem);
|
||||
@ -50,54 +56,47 @@ xptiZipItem::xptiZipItem()
|
||||
}
|
||||
|
||||
xptiZipItem::xptiZipItem(const char* aName,
|
||||
xptiWorkingSet* aWorkingSet,
|
||||
XPTHeader* aHeader /*= nsnull */)
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
|
||||
: mName(aName),
|
||||
:
|
||||
#ifdef DEBUG
|
||||
mDEBUG_WorkingSet(aWorkingSet),
|
||||
#endif
|
||||
mName(aName),
|
||||
mGuts(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(xptiZipItem);
|
||||
|
||||
NS_ASSERTION(aWorkingSet,"bad param");
|
||||
mName = XPT_STRDUP(aWorkingSet->GetStringArena(), aName);
|
||||
|
||||
if(aHeader)
|
||||
SetHeader(aHeader);
|
||||
}
|
||||
|
||||
xptiZipItem::xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet,
|
||||
PRBool cloneGuts)
|
||||
: mName(nsnull),
|
||||
xptiZipItem::xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet)
|
||||
:
|
||||
#ifdef DEBUG
|
||||
mDEBUG_WorkingSet(aWorkingSet),
|
||||
#endif
|
||||
mName(nsnull),
|
||||
mGuts(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(xptiZipItem);
|
||||
|
||||
NS_ASSERTION(aWorkingSet,"bad param");
|
||||
mName = XPT_STRDUP(aWorkingSet->GetStringArena(), r.mName);
|
||||
|
||||
if(cloneGuts && r.mGuts)
|
||||
mGuts = r.mGuts->Clone();
|
||||
}
|
||||
|
||||
xptiZipItem::~xptiZipItem()
|
||||
{
|
||||
MOZ_COUNT_DTOR(xptiZipItem);
|
||||
|
||||
if(mGuts)
|
||||
delete mGuts;
|
||||
}
|
||||
|
||||
PRBool
|
||||
xptiZipItem::SetHeader(XPTHeader* aHeader)
|
||||
xptiZipItem::SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet)
|
||||
{
|
||||
NS_ASSERTION(!mGuts,"bad state");
|
||||
NS_ASSERTION(aHeader,"bad param");
|
||||
NS_ASSERTION(aWorkingSet,"bad param");
|
||||
|
||||
mGuts = new xptiTypelibGuts(aHeader);
|
||||
if(mGuts && !mGuts->IsValid())
|
||||
{
|
||||
delete mGuts;
|
||||
mGuts = nsnull;
|
||||
}
|
||||
mGuts = xptiTypelibGuts::NewGuts(aHeader, aWorkingSet);
|
||||
return mGuts != nsnull;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe <mccabe@netscape.com>
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -20,6 +20,8 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe <mccabe@netscape.com>
|
||||
* John Bandhauer <jband@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -82,7 +84,7 @@
|
||||
|
||||
#include "nsAutoLock.h"
|
||||
|
||||
#include "plhash.h"
|
||||
#include "pldhash.h"
|
||||
#include "plstr.h"
|
||||
#include "prprf.h"
|
||||
#include "prio.h"
|
||||
@ -104,11 +106,16 @@
|
||||
#define LOG_AUTOREG(x) xptiInterfaceInfoManager::WriteToLog x
|
||||
#endif
|
||||
|
||||
#if 1 && defined(DEBUG_jband)
|
||||
#define SHOW_INFO_COUNT_STATS
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
class xptiFile;
|
||||
class xptiInterfaceInfo;
|
||||
class xptiInterfaceInfoManager;
|
||||
class xptiInterfaceEntry;
|
||||
class xptiInterfaceGuts;
|
||||
class xptiTypelibGuts;
|
||||
class xptiWorkingSet;
|
||||
@ -142,24 +149,42 @@ private:
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// No virtuals.
|
||||
// These are always constructed in the struct arena using placement new.
|
||||
// dtor need not be called.
|
||||
|
||||
class xptiTypelibGuts
|
||||
{
|
||||
public:
|
||||
xptiTypelibGuts(); // not implemented
|
||||
xptiTypelibGuts(XPTHeader* aHeader);
|
||||
~xptiTypelibGuts();
|
||||
static xptiTypelibGuts* NewGuts(XPTHeader* aHeader,
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
PRBool IsValid() const {return mHeader != nsnull;}
|
||||
XPTHeader* GetHeader() {return mHeader;}
|
||||
PRUint16 GetInfoCount() const {return mHeader->num_interfaces;}
|
||||
nsresult SetInfoAt(PRUint16 i, xptiInterfaceInfo* ptr);
|
||||
nsresult GetInfoAt(PRUint16 i, xptiInterfaceInfo** ptr);
|
||||
xptiInterfaceInfo* GetInfoAtNoAddRef(PRUint16 i);
|
||||
xptiTypelibGuts* Clone();
|
||||
XPTHeader* GetHeader() {return mHeader;}
|
||||
PRUint16 GetEntryCount() const {return mHeader->num_interfaces;}
|
||||
|
||||
void SetEntryAt(PRUint16 i, xptiInterfaceEntry* ptr)
|
||||
{
|
||||
NS_ASSERTION(mHeader,"bad state!");
|
||||
NS_ASSERTION(i < GetEntryCount(),"bad param!");
|
||||
mEntryArray[i] = ptr;
|
||||
}
|
||||
|
||||
xptiInterfaceEntry* GetEntryAt(PRUint16 i) const
|
||||
{
|
||||
NS_ASSERTION(mHeader,"bad state!");
|
||||
NS_ASSERTION(i < GetEntryCount(),"bad param!");
|
||||
return mEntryArray[i];
|
||||
}
|
||||
|
||||
private:
|
||||
XPTHeader* mHeader; // hold pointer into arena
|
||||
xptiInterfaceInfo** mInfoArray;
|
||||
xptiTypelibGuts(); // not implemented
|
||||
xptiTypelibGuts(XPTHeader* aHeader);
|
||||
~xptiTypelibGuts() {}
|
||||
void* operator new(size_t, void* p) {return p;}
|
||||
|
||||
private:
|
||||
XPTHeader* mHeader; // hold pointer into arena
|
||||
xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit.
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
@ -171,7 +196,7 @@ public:
|
||||
const nsInt64& GetDate() const {return mDate;}
|
||||
const char* GetName() const {return mName;}
|
||||
const PRUint32 GetDirectory() const {return mDirectory;}
|
||||
xptiTypelibGuts* GetGuts() {return mGuts;}
|
||||
xptiTypelibGuts* GetGuts() {return mGuts;}
|
||||
|
||||
xptiFile();
|
||||
|
||||
@ -179,15 +204,13 @@ public:
|
||||
const nsInt64& aDate,
|
||||
PRUint32 aDirectory,
|
||||
const char* aName,
|
||||
xptiWorkingSet* aWorkingSet,
|
||||
XPTHeader* aHeader = nsnull);
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet,
|
||||
PRBool cloneGuts);
|
||||
xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet);
|
||||
|
||||
~xptiFile();
|
||||
|
||||
PRBool SetHeader(XPTHeader* aHeader);
|
||||
PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
|
||||
|
||||
PRBool Equals(const xptiFile& r) const
|
||||
{
|
||||
@ -208,23 +231,29 @@ public:
|
||||
private:
|
||||
void CopyFields(const xptiFile& r)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// If 'this' has a workingset then it better match that of the assigner.
|
||||
NS_ASSERTION(!mDEBUG_WorkingSet ||
|
||||
mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
|
||||
"illegal xptiFile assignment");
|
||||
mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
|
||||
#endif
|
||||
|
||||
mSize = r.mSize;
|
||||
mDate = r.mDate;
|
||||
mName = r.mName;
|
||||
mDirectory = r.mDirectory;
|
||||
if(mGuts)
|
||||
delete mGuts;
|
||||
if(r.mGuts)
|
||||
mGuts = r.mGuts->Clone();
|
||||
else
|
||||
mGuts = nsnull;
|
||||
mGuts = r.mGuts;
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef DEBUG
|
||||
xptiWorkingSet* mDEBUG_WorkingSet;
|
||||
#endif
|
||||
nsInt64 mSize;
|
||||
nsInt64 mDate;
|
||||
const char* mName; // hold pointer into arena from initializer
|
||||
xptiTypelibGuts* mGuts; // new/delete
|
||||
xptiTypelibGuts* mGuts; // hold pointer into arena
|
||||
PRUint32 mDirectory;
|
||||
};
|
||||
|
||||
@ -239,15 +268,13 @@ public:
|
||||
xptiZipItem();
|
||||
|
||||
xptiZipItem(const char* aName,
|
||||
xptiWorkingSet* aWorkingSet,
|
||||
XPTHeader* aHeader = nsnull);
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet,
|
||||
PRBool cloneGuts);
|
||||
xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet);
|
||||
|
||||
~xptiZipItem();
|
||||
|
||||
PRBool SetHeader(XPTHeader* aHeader);
|
||||
PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
|
||||
|
||||
PRBool Equals(const xptiZipItem& r) const
|
||||
{
|
||||
@ -265,18 +292,24 @@ public:
|
||||
private:
|
||||
void CopyFields(const xptiZipItem& r)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// If 'this' has a workingset then it better match that of the assigner.
|
||||
NS_ASSERTION(!mDEBUG_WorkingSet ||
|
||||
mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
|
||||
"illegal xptiFile assignment");
|
||||
mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
|
||||
#endif
|
||||
|
||||
mName = r.mName;
|
||||
if(mGuts)
|
||||
delete mGuts;
|
||||
if(r.mGuts)
|
||||
mGuts = r.mGuts->Clone();
|
||||
else
|
||||
mGuts = nsnull;
|
||||
mGuts = r.mGuts;
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef DEBUG
|
||||
xptiWorkingSet* mDEBUG_WorkingSet;
|
||||
#endif
|
||||
const char* mName; // hold pointer into arena from initializer
|
||||
xptiTypelibGuts* mGuts; // new/delete
|
||||
xptiTypelibGuts* mGuts; // hold pointer into arena
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
@ -411,27 +444,37 @@ private:
|
||||
|
||||
public:
|
||||
// XXX make these private with accessors
|
||||
PLHashTable* mNameTable;
|
||||
PLHashTable* mIIDTable;
|
||||
PLDHashTable* mNameTable;
|
||||
PLDHashTable* mIIDTable;
|
||||
PRUint32* mFileMergeOffsetMap; // always in an arena
|
||||
PRUint32* mZipItemMergeOffsetMap; // always in an arena
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// XXX could move this class to xptiInterfaceInfo.cpp.
|
||||
|
||||
class xptiInterfaceGuts
|
||||
{
|
||||
public:
|
||||
|
||||
uint16 mMethodBaseIndex;
|
||||
uint16 mConstantBaseIndex;
|
||||
xptiInterfaceInfo* mParent;
|
||||
xptiInterfaceEntry* mParent;
|
||||
XPTInterfaceDescriptor* mDescriptor;
|
||||
xptiTypelib mTypelib;
|
||||
xptiWorkingSet* mWorkingSet;
|
||||
|
||||
static xptiInterfaceGuts* NewGuts(XPTInterfaceDescriptor* aDescriptor,
|
||||
const xptiTypelib& aTypelib,
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
{
|
||||
void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
|
||||
sizeof(xptiInterfaceGuts));
|
||||
if(!place)
|
||||
return nsnull;
|
||||
return new(place) xptiInterfaceGuts(aDescriptor, aTypelib, aWorkingSet);
|
||||
}
|
||||
|
||||
private:
|
||||
void* operator new(size_t, void* p) {return p;}
|
||||
xptiInterfaceGuts(XPTInterfaceDescriptor* aDescriptor,
|
||||
const xptiTypelib& aTypelib,
|
||||
xptiWorkingSet* aWorkingSet)
|
||||
@ -442,8 +485,7 @@ public:
|
||||
mTypelib(aTypelib),
|
||||
mWorkingSet(aWorkingSet) {}
|
||||
|
||||
// method definition below to avoid use before declaring xptiInterfaceInfo
|
||||
inline ~xptiInterfaceGuts();
|
||||
~xptiInterfaceGuts() {}
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
@ -455,6 +497,9 @@ class xptiInfoFlags
|
||||
{
|
||||
enum {STATE_MASK = 3};
|
||||
public:
|
||||
xptiInfoFlags(uint8 n) : mData(n) {}
|
||||
xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
|
||||
|
||||
static uint8 GetStateMask()
|
||||
{return uint8(STATE_MASK);}
|
||||
|
||||
@ -485,30 +530,21 @@ private:
|
||||
|
||||
/****************************************************/
|
||||
|
||||
class xptiInterfaceInfo : public nsIInterfaceInfo
|
||||
// No virtual methods.
|
||||
// We always create in the struct arena and construct using "placement new".
|
||||
// No members need dtor calls.
|
||||
|
||||
class xptiInterfaceEntry
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINTERFACEINFO
|
||||
static xptiInterfaceEntry* NewEntry(const char* name,
|
||||
const nsID& iid,
|
||||
const xptiTypelib& typelib,
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
public:
|
||||
xptiInterfaceInfo(); // not implemented
|
||||
|
||||
xptiInterfaceInfo(const char* name,
|
||||
const nsID& iid,
|
||||
const xptiTypelib& typelib,
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
xptiInterfaceInfo(const xptiInterfaceInfo& r,
|
||||
const xptiTypelib& typelib,
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
virtual ~xptiInterfaceInfo();
|
||||
|
||||
// We use mName[-1] (cast as a xptiInfoFlags) to hold the two bit state
|
||||
// below and also the bit flags that follow. If the states ever grow beyond
|
||||
// 2 bits then these flags need to be adjusted along with STATE_MASK in
|
||||
// xptiInfoFlags.
|
||||
static xptiInterfaceEntry* NewEntry(const xptiInterfaceEntry& r,
|
||||
const xptiTypelib& typelib,
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
enum {
|
||||
NOT_RESOLVED = 0,
|
||||
@ -520,11 +556,7 @@ public:
|
||||
// Additional bit flags...
|
||||
enum {SCRIPTABLE = 4};
|
||||
|
||||
PRBool IsValid() const
|
||||
{return mName != nsnull;}
|
||||
|
||||
uint8 GetResolveState() const
|
||||
{return IsValid() ? GetFlags().GetState() : (uint8) RESOLVE_FAILED;}
|
||||
uint8 GetResolveState() const {return mFlags.GetState();}
|
||||
|
||||
PRBool IsFullyResolved() const
|
||||
{return GetResolveState() == (uint8) FULLY_RESOLVED;}
|
||||
@ -536,43 +568,11 @@ public:
|
||||
const xptiTypelib& GetTypelibRecord() const
|
||||
{return HasInterfaceRecord() ? mInterface->mTypelib : mTypelib;}
|
||||
|
||||
void SetScriptableFlag(PRBool on)
|
||||
{GetFlags().SetFlagBit(uint8(SCRIPTABLE),on);}
|
||||
PRBool GetScriptableFlag() const
|
||||
{return GetFlags().GetFlagBit(uint8(SCRIPTABLE));}
|
||||
xptiInterfaceGuts* GetInterfaceGuts() const
|
||||
{return HasInterfaceRecord() ? mInterface : nsnull;}
|
||||
|
||||
const nsID* GetTheIID() const {return &mIID;}
|
||||
const char* GetTheName() const {return mName;}
|
||||
|
||||
PRBool PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
void Invalidate();
|
||||
|
||||
private:
|
||||
void CopyName(const char* name,
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
xptiInfoFlags& GetFlags() const {return (xptiInfoFlags&) mName[-1];}
|
||||
xptiInfoFlags& GetFlags() {return (xptiInfoFlags&) mName[-1];}
|
||||
|
||||
void SetResolvedState(int state)
|
||||
{NS_ASSERTION(IsValid(),"bad state");
|
||||
GetFlags().SetState(uint8(state));}
|
||||
|
||||
PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
|
||||
{return IsFullyResolved() ? PR_TRUE : Resolve(aWorkingSet);}
|
||||
PRBool Resolve(xptiWorkingSet* aWorkingSet = nsnull);
|
||||
|
||||
// We only call these "*Locked" varients after locking. This is done to
|
||||
// allow reentrace as files are loaded and various interfaces resolved
|
||||
// without having to worry about the locked state.
|
||||
|
||||
PRBool EnsureResolvedLocked(xptiWorkingSet* aWorkingSet = nsnull)
|
||||
{return IsFullyResolved() ? PR_TRUE : ResolveLocked(aWorkingSet);}
|
||||
PRBool ResolveLocked(xptiWorkingSet* aWorkingSet = nsnull);
|
||||
|
||||
PRBool ScriptableFlagIsValid() const
|
||||
#ifdef DEBUG
|
||||
PRBool DEBUG_ScriptableFlagIsValid() const
|
||||
{int s = (int) GetResolveState();
|
||||
if((s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface)
|
||||
{
|
||||
@ -580,20 +580,190 @@ private:
|
||||
return GetScriptableFlag();
|
||||
return !GetScriptableFlag();
|
||||
}
|
||||
else return PR_TRUE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetTypeInArray(const nsXPTParamInfo* param,
|
||||
uint16 dimension,
|
||||
const XPTTypeDescriptor** type);
|
||||
private:
|
||||
nsID mIID;
|
||||
char* mName; // This is in arena (not free'd) and mName[-1] is a flag.
|
||||
#endif
|
||||
|
||||
void SetScriptableFlag(PRBool on)
|
||||
{mFlags.SetFlagBit(uint8(SCRIPTABLE),on);}
|
||||
PRBool GetScriptableFlag() const
|
||||
{return mFlags.GetFlagBit(uint8(SCRIPTABLE));}
|
||||
|
||||
const nsID* GetTheIID() const {return &mIID;}
|
||||
const char* GetTheName() const {return mName;}
|
||||
|
||||
PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
|
||||
{return IsFullyResolved() ? PR_TRUE : Resolve(aWorkingSet);}
|
||||
|
||||
PRBool PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
nsresult GetInterfaceInfo(xptiInterfaceInfo** info);
|
||||
PRBool InterfaceInfoEquals(const xptiInterfaceInfo* info) const
|
||||
{return info == mInfo;}
|
||||
|
||||
void LockedInvalidateInterfaceInfo();
|
||||
void LockedInterfaceInfoDeathNotification() {mInfo = nsnull;}
|
||||
|
||||
//////////////////////
|
||||
// These non-virtual methods handle the delegated nsIInterfaceInfo methods.
|
||||
|
||||
nsresult GetName(char * *aName);
|
||||
nsresult GetIID(nsIID * *aIID);
|
||||
nsresult IsScriptable(PRBool *_retval);
|
||||
// Except this one.
|
||||
//nsresult GetParent(nsIInterfaceInfo * *aParent);
|
||||
nsresult GetMethodCount(PRUint16 *aMethodCount);
|
||||
nsresult GetConstantCount(PRUint16 *aConstantCount);
|
||||
nsresult GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info);
|
||||
nsresult GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info);
|
||||
nsresult GetConstant(PRUint16 index, const nsXPTConstant * *constant);
|
||||
nsresult GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
|
||||
nsresult GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval);
|
||||
nsresult GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval);
|
||||
nsresult GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
|
||||
nsresult GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
|
||||
nsresult GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval);
|
||||
nsresult IsIID(const nsIID * IID, PRBool *_retval);
|
||||
nsresult GetNameShared(const char **name);
|
||||
nsresult GetIIDShared(const nsIID * *iid);
|
||||
nsresult IsFunction(PRBool *_retval);
|
||||
nsresult HasAncestor(const nsIID * iid, PRBool *_retval);
|
||||
|
||||
//////////////////////
|
||||
|
||||
private:
|
||||
xptiInterfaceEntry(); // not implemented
|
||||
|
||||
xptiInterfaceEntry(const char* name,
|
||||
size_t nameLength,
|
||||
const nsID& iid,
|
||||
const xptiTypelib& typelib);
|
||||
|
||||
xptiInterfaceEntry(const xptiInterfaceEntry& r,
|
||||
size_t nameLength,
|
||||
const xptiTypelib& typelib);
|
||||
~xptiInterfaceEntry();
|
||||
|
||||
void* operator new(size_t, void* p) {return p;}
|
||||
|
||||
void SetResolvedState(int state)
|
||||
{mFlags.SetState(uint8(state));}
|
||||
|
||||
PRBool Resolve(xptiWorkingSet* aWorkingSet = nsnull);
|
||||
|
||||
// We only call these "*Locked" variants after locking. This is done to
|
||||
// allow reentrace as files are loaded and various interfaces resolved
|
||||
// without having to worry about the locked state.
|
||||
|
||||
PRBool EnsureResolvedLocked(xptiWorkingSet* aWorkingSet = nsnull)
|
||||
{return IsFullyResolved() ? PR_TRUE : ResolveLocked(aWorkingSet);}
|
||||
PRBool ResolveLocked(xptiWorkingSet* aWorkingSet = nsnull);
|
||||
|
||||
// private helpers
|
||||
|
||||
nsresult GetEntryForParam(PRUint16 methodIndex,
|
||||
const nsXPTParamInfo * param,
|
||||
xptiInterfaceEntry** entry);
|
||||
|
||||
nsresult GetTypeInArray(const nsXPTParamInfo* param,
|
||||
uint16 dimension,
|
||||
const XPTTypeDescriptor** type);
|
||||
|
||||
private:
|
||||
nsID mIID;
|
||||
union {
|
||||
xptiTypelib mTypelib; // Valid only until resolved.
|
||||
xptiInterfaceGuts* mInterface; // Valid only after resolved.
|
||||
};
|
||||
xptiInterfaceInfo* mInfo; // May come and go.
|
||||
xptiInfoFlags mFlags;
|
||||
char mName[1]; // Always last. Sized to fit.
|
||||
};
|
||||
|
||||
struct xptiHashEntry : public PLDHashEntryHdr
|
||||
{
|
||||
xptiInterfaceEntry* value;
|
||||
};
|
||||
|
||||
/****************************************************/
|
||||
|
||||
class xptiInterfaceInfo : public nsIInterfaceInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// Use delegation to implement (most!) of nsIInterfaceInfo.
|
||||
NS_IMETHOD GetName(char * *aName) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
|
||||
NS_IMETHOD GetIID(nsIID * *aIID) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
|
||||
NS_IMETHOD IsScriptable(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
|
||||
// Except this one.
|
||||
NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent)
|
||||
{
|
||||
if(!EnsureResolved() || !EnsureParent())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
NS_IF_ADDREF(*aParent = mParent);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD GetMethodCount(PRUint16 *aMethodCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
|
||||
NS_IMETHOD GetConstantCount(PRUint16 *aConstantCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
|
||||
NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
|
||||
NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
|
||||
NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant); }
|
||||
NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); }
|
||||
NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); }
|
||||
NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); }
|
||||
NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); }
|
||||
NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetLengthIsArgNumberForParam(methodIndex, param, dimension, _retval); }
|
||||
NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
|
||||
NS_IMETHOD IsIID(const nsIID * IID, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
|
||||
NS_IMETHOD GetNameShared(const char **name) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
|
||||
NS_IMETHOD GetIIDShared(const nsIID * *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
|
||||
NS_IMETHOD IsFunction(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
|
||||
NS_IMETHOD HasAncestor(const nsIID * iid, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
|
||||
|
||||
public:
|
||||
xptiInterfaceInfo(xptiInterfaceEntry* entry);
|
||||
|
||||
virtual ~xptiInterfaceInfo() ;
|
||||
|
||||
void Invalidate()
|
||||
{NS_IF_RELEASE(mParent); mEntry = nsnull;}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void DEBUG_ShutdownNotification();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
// Note that mParent might still end up as nsnull if we don't have one.
|
||||
PRBool EnsureParent(xptiWorkingSet* aWorkingSet = nsnull)
|
||||
{
|
||||
NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
|
||||
return mParent || !mEntry->GetInterfaceGuts()->mParent || BuildParent();
|
||||
}
|
||||
|
||||
PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
|
||||
{
|
||||
return mEntry && mEntry->EnsureResolved(aWorkingSet);
|
||||
}
|
||||
|
||||
PRBool BuildParent()
|
||||
{
|
||||
NS_ASSERTION(mEntry &&
|
||||
mEntry->IsFullyResolved() &&
|
||||
!mParent &&
|
||||
mEntry->GetInterfaceGuts()->mParent,
|
||||
"bad BuildParent call");
|
||||
return NS_SUCCEEDED(mEntry->GetInterfaceGuts()->mParent->
|
||||
GetInterfaceInfo(&mParent));
|
||||
}
|
||||
|
||||
xptiInterfaceInfo(); // not implemented
|
||||
|
||||
private:
|
||||
xptiInterfaceEntry* mEntry;
|
||||
xptiInterfaceInfo* mParent;
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
@ -609,6 +779,7 @@ public:
|
||||
|
||||
static PRBool Delete(xptiInterfaceInfoManager* aMgr);
|
||||
|
||||
private:
|
||||
xptiManifest(); // no implementation
|
||||
};
|
||||
|
||||
@ -677,6 +848,8 @@ public:
|
||||
|
||||
static PRBool IsZip(const char* name)
|
||||
{return GetType(name) == ZIP;}
|
||||
private:
|
||||
xptiFileType(); // no implementation
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
@ -746,6 +919,11 @@ public:
|
||||
return nsnull;
|
||||
return self->mAutoRegLock;}
|
||||
|
||||
static PRMonitor* GetInfoMonitor(xptiInterfaceInfoManager* self = nsnull)
|
||||
{if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
|
||||
return nsnull;
|
||||
return self->mInfoMonitor;}
|
||||
|
||||
static void WriteToLog(const char *fmt, ...);
|
||||
|
||||
private:
|
||||
@ -781,10 +959,10 @@ private:
|
||||
nsISupportsArray* aFileList,
|
||||
xptiWorkingSet* aWorkingSet);
|
||||
|
||||
PRBool VerifyAndAddInterfaceIfNew(xptiWorkingSet* aWorkingSet,
|
||||
XPTInterfaceDirectoryEntry* iface,
|
||||
const xptiTypelib& typelibRecord,
|
||||
xptiInterfaceInfo** infoAdded);
|
||||
PRBool VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
|
||||
XPTInterfaceDirectoryEntry* iface,
|
||||
const xptiTypelib& typelibRecord,
|
||||
xptiInterfaceEntry** entryAdded);
|
||||
|
||||
PRBool MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
|
||||
xptiWorkingSet* aSrcWorkingSet);
|
||||
@ -804,6 +982,7 @@ private:
|
||||
PRFileDesc* mOpenLogFile;
|
||||
PRLock* mResolveLock;
|
||||
PRLock* mAutoRegLock;
|
||||
PRMonitor* mInfoMonitor;
|
||||
nsCOMPtr<nsILocalFile> mManifestDir;
|
||||
nsCOMPtr<nsISupportsArray> mSearchPath;
|
||||
};
|
||||
@ -817,10 +996,4 @@ nsresult xptiCloneLocalFile(nsILocalFile* aLocalFile,
|
||||
nsresult xptiCloneElementAsLocalFile(nsISupportsArray* aArray, PRUint32 aIndex,
|
||||
nsILocalFile** aLocalFile);
|
||||
|
||||
/***************************************************************************/
|
||||
//inlines...
|
||||
|
||||
inline xptiInterfaceGuts::~xptiInterfaceGuts() {NS_IF_RELEASE(mParent);}
|
||||
|
||||
|
||||
#endif /* xptiprivate_h___ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user