summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h')
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h981
1 files changed, 981 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h
new file mode 100644
index 00000000..3d159c2c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h
@@ -0,0 +1,981 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * 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 of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Library-private header for Interface Info system. */
+
+#ifndef xptiprivate_h___
+#define xptiprivate_h___
+
+#include "nscore.h"
+#include "nsISupports.h"
+
+// this after nsISupports, to pick up IID
+// so that xpt stuff doesn't try to define it itself...
+#include "xpt_struct.h"
+#include "xpt_xdr.h"
+
+#include "nsIInterfaceInfo.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptinfo.h"
+#include "nsIXPTLoader.h"
+
+#include "nsIServiceManager.h"
+#include "nsILocalFile.h"
+#include "nsIDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsIWeakReference.h"
+
+#include "nsCRT.h"
+#include "nsMemory.h"
+
+#include "nsISupportsArray.h"
+#include "nsSupportsArray.h"
+#include "nsInt64.h"
+
+#include "nsQuickSort.h"
+
+#include "nsXPIDLString.h"
+
+#include "nsIInputStream.h"
+
+#include "nsAutoLock.h"
+
+#include "pldhash.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "prio.h"
+#include "prtime.h"
+#include "prenv.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/***************************************************************************/
+
+#if 0 && defined(DEBUG_jband)
+#define LOG_RESOLVE(x) printf x
+#define LOG_LOAD(x) printf x
+#define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0)
+#else
+#define LOG_RESOLVE(x) ((void)0)
+#define LOG_LOAD(x) ((void)0)
+#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;
+
+/***************************************************************************/
+
+class xptiTypelib
+{
+public:
+ // No ctors or dtors so that we can be in a union in xptiInterfaceInfo.
+ // Allow automatic shallow copies.
+
+ uint16 GetFileIndex() const {return mFileIndex;}
+ uint16 GetZipItemIndex() const {return mZipItemIndex;}
+
+ enum {NOT_ZIP = 0xffff};
+
+ PRBool IsZip() const {return mZipItemIndex != NOT_ZIP;}
+
+ void Init(uint16 aFileIndex, uint16 aZipItemIndex = NOT_ZIP)
+ {mFileIndex = aFileIndex; mZipItemIndex = aZipItemIndex;}
+
+ PRBool Equals(const xptiTypelib& r) const
+ {return mFileIndex == r.mFileIndex &&
+ mZipItemIndex == r.mZipItemIndex;}
+
+private:
+ uint16 mFileIndex;
+ uint16 mZipItemIndex;
+};
+
+/***************************************************************************/
+
+// No virtuals.
+// These are always constructed in the struct arena using placement new.
+// dtor need not be called.
+
+class xptiTypelibGuts
+{
+public:
+ static xptiTypelibGuts* NewGuts(XPTHeader* aHeader,
+ xptiWorkingSet* aWorkingSet);
+
+ 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:
+ xptiTypelibGuts(); // not implemented
+ xptiTypelibGuts(XPTHeader* aHeader);
+ ~xptiTypelibGuts() {}
+ void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
+
+private:
+ XPTHeader* mHeader; // hold pointer into arena
+ xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit.
+};
+
+/***************************************************************************/
+
+class xptiFile
+{
+public:
+ const nsInt64& GetSize() const {return mSize;}
+ const nsInt64& GetDate() const {return mDate;}
+ const char* GetName() const {return mName;}
+ /*const*/ PRUint32 GetDirectory() const {return mDirectory;}
+ xptiTypelibGuts* GetGuts() {return mGuts;}
+
+ xptiFile();
+
+ xptiFile(const nsInt64& aSize,
+ const nsInt64& aDate,
+ PRUint32 aDirectory,
+ const char* aName,
+ xptiWorkingSet* aWorkingSet);
+
+ xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet);
+
+ ~xptiFile();
+
+ PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
+
+ PRBool Equals(const xptiFile& r) const
+ {
+ return mDirectory == r.mDirectory &&
+ mSize == r.mSize &&
+ mDate == r.mDate &&
+ 0 == PL_strcmp(mName, r.mName);
+ }
+
+ xptiFile(const xptiFile& r) {CopyFields(r);}
+ xptiFile& operator= (const xptiFile& r)
+ {
+ if(this != &r)
+ CopyFields(r);
+ return *this;
+ }
+
+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;
+ 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; // hold pointer into arena
+ PRUint32 mDirectory;
+};
+
+/***************************************************************************/
+
+class xptiZipItem
+{
+public:
+ const char* GetName() const {return mName;}
+ xptiTypelibGuts* GetGuts() {return mGuts;}
+
+ xptiZipItem();
+
+ xptiZipItem(const char* aName,
+ xptiWorkingSet* aWorkingSet);
+
+ xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet);
+
+ ~xptiZipItem();
+
+ PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
+
+ PRBool Equals(const xptiZipItem& r) const
+ {
+ return 0 == PL_strcmp(mName, r.mName);
+ }
+
+ xptiZipItem(const xptiZipItem& r) {CopyFields(r);}
+ xptiZipItem& operator= (const xptiZipItem& r)
+ {
+ if(this != &r)
+ CopyFields(r);
+ return *this;
+ }
+
+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;
+ mGuts = r.mGuts;
+ }
+
+private:
+#ifdef DEBUG
+ xptiWorkingSet* mDEBUG_WorkingSet;
+#endif
+ const char* mName; // hold pointer into arena from initializer
+ xptiTypelibGuts* mGuts; // hold pointer into arena
+};
+
+/***************************************************************************/
+
+class xptiWorkingSet
+{
+public:
+ xptiWorkingSet(); // not implmented
+ xptiWorkingSet(nsISupportsArray* aDirectories);
+ ~xptiWorkingSet();
+
+ PRBool IsValid() const;
+
+ void InvalidateInterfaceInfos();
+ void ClearHashTables();
+ void ClearFiles();
+ void ClearZipItems();
+
+ // utility methods...
+
+ xptiTypelibGuts* GetTypelibGuts(const xptiTypelib& typelib)
+ {
+ return typelib.IsZip() ?
+ GetZipItemAt(typelib.GetZipItemIndex()).GetGuts() :
+ GetFileAt(typelib.GetFileIndex()).GetGuts();
+ }
+
+ enum {NOT_FOUND = 0xffffffff};
+
+ // FileArray stuff...
+
+ PRUint32 GetFileCount() const {return mFileCount;}
+ PRUint32 GetFileFreeSpace()
+ {return mFileArray ? mMaxFileCount - mFileCount : 0;}
+
+ PRUint32 FindFile(PRUint32 dir, const char* name);
+
+ PRUint32 GetTypelibDirectoryIndex(const xptiTypelib& typelib)
+ {
+ return GetFileAt(typelib.GetFileIndex()).GetDirectory();
+ }
+
+ const char* GetTypelibFileName(const xptiTypelib& typelib)
+ {
+ return GetFileAt(typelib.GetFileIndex()).GetName();
+ }
+
+ xptiFile& GetFileAt(PRUint32 i) const
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(i < mFileCount, "bad param!");
+ return mFileArray[i];
+ }
+
+ void SetFileAt(PRUint32 i, const xptiFile& r)
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(i < mFileCount, "bad param!");
+ mFileArray[i] = r;
+ }
+
+ void AppendFile(const xptiFile& r)
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(mFileCount < mMaxFileCount, "bad param!");
+ mFileArray[mFileCount++] = r;
+ }
+
+ PRBool NewFileArray(PRUint32 count);
+ PRBool ExtendFileArray(PRUint32 count);
+
+ // ZipItemArray stuff...
+
+ PRUint32 GetZipItemCount() const {return mZipItemCount;}
+ PRUint32 GetZipItemFreeSpace()
+ {return mZipItemArray ? mMaxZipItemCount - mZipItemCount : 0;}
+
+ PRUint32 FindZipItemWithName(const char* name);
+
+ xptiZipItem& GetZipItemAt(PRUint32 i) const
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(i < mZipItemCount, "bad param!");
+ return mZipItemArray[i];
+ }
+
+ void SetZipItemAt(PRUint32 i, const xptiZipItem& r)
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(i < mZipItemCount, "bad param!");
+ mZipItemArray[i] = r;
+ }
+
+ void AppendZipItem(const xptiZipItem& r)
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(mZipItemCount < mMaxZipItemCount, "bad param!");
+ mZipItemArray[mZipItemCount++] = r;
+ }
+
+ PRBool NewZipItemArray(PRUint32 count);
+ PRBool ExtendZipItemArray(PRUint32 count);
+
+ // Directory stuff...
+
+ PRUint32 GetDirectoryCount();
+ nsresult GetCloneOfDirectoryAt(PRUint32 i, nsILocalFile** dir);
+ nsresult GetDirectoryAt(PRUint32 i, nsILocalFile** dir);
+ PRBool FindDirectory(nsILocalFile* dir, PRUint32* index);
+ PRBool FindDirectoryOfFile(nsILocalFile* file, PRUint32* index);
+ PRBool DirectoryAtMatchesPersistentDescriptor(PRUint32 i, const char* desc);
+
+ // Arena stuff...
+
+ XPTArena* GetStringArena() {return mStringArena;}
+ XPTArena* GetStructArena() {return mStructArena;}
+
+
+private:
+ PRUint32 mFileCount;
+ PRUint32 mMaxFileCount;
+ xptiFile* mFileArray; // using new[] and delete[]
+
+ PRUint32 mZipItemCount;
+ PRUint32 mMaxZipItemCount;
+ xptiZipItem* mZipItemArray; // using new[] and delete[]
+
+ XPTArena* mStringArena;
+ XPTArena* mStructArena;
+
+ nsCOMPtr<nsISupportsArray> mDirectories;
+
+public:
+ // XXX make these private with accessors
+ PLDHashTable* mNameTable;
+ PLDHashTable* mIIDTable;
+ PRUint32* mFileMergeOffsetMap; // always in an arena
+ PRUint32* mZipItemMergeOffsetMap; // always in an arena
+};
+
+/***************************************************************************/
+
+class xptiInterfaceGuts
+{
+public:
+ uint16 mMethodBaseIndex;
+ uint16 mConstantBaseIndex;
+ 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) CPP_THROW_NEW {return p;}
+ xptiInterfaceGuts(XPTInterfaceDescriptor* aDescriptor,
+ const xptiTypelib& aTypelib,
+ xptiWorkingSet* aWorkingSet)
+ : mMethodBaseIndex(0),
+ mConstantBaseIndex(0),
+ mParent(nsnull),
+ mDescriptor(aDescriptor),
+ mTypelib(aTypelib),
+ mWorkingSet(aWorkingSet) {}
+
+ ~xptiInterfaceGuts() {}
+};
+
+/***************************************************************************/
+
+// This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value
+// and a set of bitflags in one 8bit value. See below.
+
+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);}
+
+ void Clear()
+ {mData = 0;}
+
+ uint8 GetData() const
+ {return mData;}
+
+ uint8 GetState() const
+ {return mData & GetStateMask();}
+
+ void SetState(uint8 state)
+ {mData &= ~GetStateMask(); mData |= state;}
+
+ void SetFlagBit(uint8 flag, PRBool on)
+ {if(on)
+ mData |= ~GetStateMask() & flag;
+ else
+ mData &= GetStateMask() | ~flag;}
+
+ PRBool GetFlagBit(uint8 flag) const
+ {return (mData & flag) ? PR_TRUE : PR_FALSE;}
+
+private:
+ uint8 mData;
+};
+
+/****************************************************/
+
+// No virtual methods.
+// We always create in the struct arena and construct using "placement new".
+// No members need dtor calls.
+
+class xptiInterfaceEntry
+{
+public:
+ static xptiInterfaceEntry* NewEntry(const char* name,
+ int nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet);
+
+ static xptiInterfaceEntry* NewEntry(const xptiInterfaceEntry& r,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet);
+
+ enum {
+ NOT_RESOLVED = 0,
+ PARTIALLY_RESOLVED = 1,
+ FULLY_RESOLVED = 2,
+ RESOLVE_FAILED = 3
+ };
+
+ // Additional bit flags...
+ enum {SCRIPTABLE = 4};
+
+ uint8 GetResolveState() const {return mFlags.GetState();}
+
+ PRBool IsFullyResolved() const
+ {return GetResolveState() == (uint8) FULLY_RESOLVED;}
+
+ PRBool HasInterfaceRecord() const
+ {int s = (int) GetResolveState();
+ return (s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface;}
+
+ const xptiTypelib& GetTypelibRecord() const
+ {return HasInterfaceRecord() ? mInterface->mTypelib : mTypelib;}
+
+ xptiInterfaceGuts* GetInterfaceGuts() const
+ {return HasInterfaceRecord() ? mInterface : nsnull;}
+
+#ifdef DEBUG
+ PRBool DEBUG_ScriptableFlagIsValid() const
+ {int s = (int) GetResolveState();
+ if((s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface)
+ {
+ if(XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags))
+ return GetScriptableFlag();
+ return !GetScriptableFlag();
+ }
+ return PR_TRUE;
+ }
+#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);
+ nsresult GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid);
+
+ //////////////////////
+
+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) CPP_THROW_NEW {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 GetInterfaceIID(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); }
+ NS_IMETHOD GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
+
+public:
+ xptiInterfaceInfo(xptiInterfaceEntry* entry);
+
+ void Invalidate()
+ {NS_IF_RELEASE(mParent); mEntry = nsnull;}
+
+#ifdef DEBUG
+ static void DEBUG_ShutdownNotification();
+#endif
+
+private:
+
+ ~xptiInterfaceInfo();
+
+ // 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;
+};
+
+/***************************************************************************/
+
+class xptiManifest
+{
+public:
+ static PRBool Read(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet);
+
+ static PRBool Write(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet);
+
+ static PRBool Delete(xptiInterfaceInfoManager* aMgr);
+
+private:
+ xptiManifest(); // no implementation
+};
+
+/***************************************************************************/
+
+class xptiZipLoaderSink : public nsIXPTLoaderSink
+{
+public:
+ xptiZipLoaderSink(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet) :
+ mManager(aMgr),
+ mWorkingSet(aWorkingSet) {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIXPTLOADERSINK
+
+private:
+ ~xptiZipLoaderSink() {}
+
+ xptiInterfaceInfoManager* mManager;
+ xptiWorkingSet* mWorkingSet;
+
+};
+
+class xptiZipLoader
+{
+public:
+ xptiZipLoader(); // not implemented
+
+ static XPTHeader*
+ ReadXPTFileFromInputStream(nsIInputStream *stream,
+ xptiWorkingSet* aWorkingSet);
+
+};
+
+
+/***************************************************************************/
+
+class xptiFileType
+{
+public:
+ enum Type {UNKNOWN = -1, XPT = 0, ZIP = 1 };
+
+ static Type GetType(const char* name);
+
+ static PRBool IsUnknown(const char* name)
+ {return GetType(name) == UNKNOWN;}
+
+ static PRBool IsXPT(const char* name)
+ {return GetType(name) == XPT;}
+
+ static PRBool IsZip(const char* name)
+ {return GetType(name) == ZIP;}
+private:
+ xptiFileType(); // no implementation
+};
+
+/***************************************************************************/
+
+// We use this is as a fancy way to open a logfile to be used within the scope
+// of some given function where it is instantiated.
+
+class xptiAutoLog
+{
+public:
+ xptiAutoLog(); // not implemented
+ xptiAutoLog(xptiInterfaceInfoManager* mgr,
+ nsILocalFile* logfile, PRBool append);
+ ~xptiAutoLog();
+private:
+ void WriteTimestamp(PRFileDesc* fd, const char* msg);
+
+ xptiInterfaceInfoManager* mMgr;
+ PRFileDesc* mOldFileDesc;
+#ifdef DEBUG
+ PRFileDesc* m_DEBUG_FileDesc;
+#endif
+};
+
+/***************************************************************************/
+
+class xptiInterfaceInfoManager
+ : public nsIInterfaceInfoSuperManager
+{
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINTERFACEINFOMANAGER
+ NS_DECL_NSIINTERFACEINFOSUPERMANAGER
+
+ // helper
+ PRBool
+ FoundZipEntry(const char* entryName,
+ int index,
+ XPTHeader* header,
+ xptiWorkingSet* aWorkingSet);
+
+public:
+ static xptiInterfaceInfoManager* GetInterfaceInfoManagerNoAddRef();
+ static void FreeInterfaceInfoManager();
+
+ xptiWorkingSet* GetWorkingSet() {return &mWorkingSet;}
+ PRFileDesc* GetOpenLogFile() {return mOpenLogFile;}
+ PRFileDesc* SetOpenLogFile(PRFileDesc* fd)
+ {PRFileDesc* temp = mOpenLogFile; mOpenLogFile = fd; return temp;}
+
+ PRBool LoadFile(const xptiTypelib& aTypelibRecord,
+ xptiWorkingSet* aWorkingSet = nsnull);
+
+ PRBool GetApplicationDir(nsILocalFile** aDir);
+ PRBool GetCloneOfManifestLocation(nsILocalFile** aDir);
+
+ void GetSearchPath(nsISupportsArray** aSearchPath)
+ {NS_ADDREF(*aSearchPath = mSearchPath);}
+
+ static PRLock* GetResolveLock(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ return nsnull;
+ return self->mResolveLock;}
+
+ static PRLock* GetAutoRegLock(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ 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:
+ ~xptiInterfaceInfoManager();
+ xptiInterfaceInfoManager(); // not implmented
+ xptiInterfaceInfoManager(nsISupportsArray* aSearchPath);
+
+ enum AutoRegMode {
+ NO_FILES_CHANGED = 0,
+ FILES_ADDED_ONLY,
+ FULL_VALIDATION_REQUIRED
+ };
+
+ PRBool IsValid();
+
+ PRBool BuildFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray** aFileList);
+
+ nsILocalFile** BuildOrderedFileArray(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ XPTHeader* ReadXPTFile(nsILocalFile* aFile, xptiWorkingSet* aWorkingSet);
+
+ AutoRegMode DetermineAutoRegStrategy(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool AddOnlyNewFilesFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool DoFullValidationMergeFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
+ XPTInterfaceDirectoryEntry* iface,
+ const xptiTypelib& typelibRecord,
+ xptiInterfaceEntry** entryAdded);
+
+ PRBool MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
+ xptiWorkingSet* aSrcWorkingSet);
+
+ void LogStats();
+
+ PRBool DEBUG_DumpFileList(nsISupportsArray* aFileList);
+ PRBool DEBUG_DumpFileArray(nsILocalFile** aFileArray, PRUint32 count);
+ PRBool DEBUG_DumpFileListInWorkingSet(xptiWorkingSet* aWorkingSet);
+
+ static PRBool BuildFileSearchPath(nsISupportsArray** aPath);
+
+private:
+ xptiWorkingSet mWorkingSet;
+ nsCOMPtr<nsILocalFile> mStatsLogFile;
+ nsCOMPtr<nsILocalFile> mAutoRegLogFile;
+ PRFileDesc* mOpenLogFile;
+ PRLock* mResolveLock;
+ PRLock* mAutoRegLock;
+ PRMonitor* mInfoMonitor;
+ PRLock* mAdditionalManagersLock;
+ nsSupportsArray mAdditionalManagers;
+ nsCOMPtr<nsISupportsArray> mSearchPath;
+};
+
+/***************************************************************************/
+// utilities...
+
+nsresult xptiCloneLocalFile(nsILocalFile* aLocalFile,
+ nsILocalFile** aCloneLocalFile);
+
+nsresult xptiCloneElementAsLocalFile(nsISupportsArray* aArray, PRUint32 aIndex,
+ nsILocalFile** aLocalFile);
+
+#endif /* xptiprivate_h___ */