зеркало из https://github.com/mozilla/gecko-dev.git
Not yet part of Seamonkey.
Progress on the nsInterfaceInfoManager typelib loader for xpconnect. Now has complete (I think) functionality, though the implementation is still probably rusty. I punted on defining a directory for .xpt files at this point; the implementation looks at the value of the XPTDIR environment variable for this value. Note that the nsXPTParaminfo interface (public/xpt_cpp) has changed (possibly temporarily) to take an 'entry' parameter.
This commit is contained in:
Родитель
a15117ca9c
Коммит
a7a7b4f959
|
@ -23,6 +23,8 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
DIRS = public src
|
||||
|
||||
DIRS += tests
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += tests
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -115,10 +115,10 @@ public:
|
|||
// is associated with so that we can find the table this index indexes
|
||||
// and then find the referenced XPTInterfaceDirectoryEntry so that we can
|
||||
// find (or build) the appropriate nsIInterfaceInfo. Simple :)
|
||||
nsIInterfaceInfo* GetInterface() const ;
|
||||
nsIInterfaceInfo* GetInterface(XPTInterfaceDirectoryEntry *entry) const ;
|
||||
|
||||
// a *little* simpler than the above
|
||||
const nsIID* GetInterfaceIID() const ;
|
||||
const nsIID* GetInterfaceIID(XPTInterfaceDirectoryEntry *entry) const ;
|
||||
|
||||
private:
|
||||
nsXPTParamInfo(); // no implementation
|
||||
|
|
|
@ -31,23 +31,22 @@ static NS_DEFINE_IID(kIInterfaceInfoIID, NS_IINTERFACEINFO_IID);
|
|||
NS_IMPL_ISUPPORTS(nsInterfaceInfo, kIInterfaceInfoIID);
|
||||
|
||||
nsInterfaceInfo::nsInterfaceInfo(XPTInterfaceDirectoryEntry* entry,
|
||||
nsInterfaceInfo *parent)
|
||||
nsInterfaceInfo *parent)
|
||||
: mEntry(entry),
|
||||
mParent(parent)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
if(mParent)
|
||||
if(mParent != NULL) {
|
||||
NS_ADDREF(mParent);
|
||||
if(mParent) {
|
||||
mMethodBaseIndex =
|
||||
mParent->mMethodBaseIndex + mParent->mMethodCount;
|
||||
mConstantBaseIndex =
|
||||
mParent->mConstantBaseIndex + mParent->mConstantCount;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
mMethodBaseIndex = mConstantBaseIndex = 0;
|
||||
}
|
||||
|
||||
mMethodCount = mEntry->interface_descriptor->num_methods;
|
||||
mConstantCount = mEntry->interface_descriptor->num_constants;
|
||||
|
@ -55,7 +54,7 @@ nsInterfaceInfo::nsInterfaceInfo(XPTInterfaceDirectoryEntry* entry,
|
|||
|
||||
nsInterfaceInfo::~nsInterfaceInfo()
|
||||
{
|
||||
if(mParent)
|
||||
if(mParent != NULL)
|
||||
NS_RELEASE(mParent);
|
||||
}
|
||||
|
||||
|
@ -134,11 +133,10 @@ NS_IMETHODIMP
|
|||
nsInterfaceInfo::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
|
||||
{
|
||||
NS_PRECONDITION(info, "bad param");
|
||||
if(index < mMethodBaseIndex)
|
||||
if (index < mMethodBaseIndex)
|
||||
return mParent->GetMethodInfo(index, info);
|
||||
|
||||
if(index >= mMethodBaseIndex + mMethodCount)
|
||||
{
|
||||
if (index >= mMethodBaseIndex + mMethodCount) {
|
||||
NS_PRECONDITION(0, "bad param");
|
||||
*info = NULL;
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -146,8 +144,8 @@ nsInterfaceInfo::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
|
|||
|
||||
// else...
|
||||
*info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
|
||||
&mEntry->interface_descriptor->
|
||||
method_descriptors[index - mMethodBaseIndex]);
|
||||
&mEntry->interface_descriptor->
|
||||
method_descriptors[index - mMethodBaseIndex]);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -155,11 +153,10 @@ NS_IMETHODIMP
|
|||
nsInterfaceInfo::GetConstant(uint16 index, const nsXPTConstant** constant)
|
||||
{
|
||||
NS_PRECONDITION(constant, "bad param");
|
||||
if(index < mConstantBaseIndex)
|
||||
if (index < mConstantBaseIndex)
|
||||
return mParent->GetConstant(index, constant);
|
||||
|
||||
if(index >= mConstantBaseIndex + mConstantCount)
|
||||
{
|
||||
if (index >= mConstantBaseIndex + mConstantCount) {
|
||||
NS_PRECONDITION(0, "bad param");
|
||||
*constant = NULL;
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -167,7 +164,23 @@ nsInterfaceInfo::GetConstant(uint16 index, const nsXPTConstant** constant)
|
|||
|
||||
// else...
|
||||
*constant = NS_REINTERPRET_CAST(nsXPTConstant*,
|
||||
&mEntry->interface_descriptor->
|
||||
const_descriptors[index-mConstantBaseIndex]);
|
||||
&mEntry->interface_descriptor->
|
||||
const_descriptors[index-mConstantBaseIndex]);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
void
|
||||
nsInterfaceInfo::print(FILE *fd)
|
||||
{
|
||||
fprintf(fd, "iid: %s name: %s name_space: %s\n",
|
||||
mEntry->iid.ToString(),
|
||||
mEntry->name,
|
||||
mEntry->name_space);
|
||||
if (mParent != NULL) {
|
||||
fprintf(fd, "parent:\n\t");
|
||||
mParent->print(fd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#include "xpt_struct.h"
|
||||
#include "xpt_cpp.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
// XXX destroy this!
|
||||
class nsInterfaceInfo : public nsIInterfaceInfo
|
||||
{
|
||||
|
@ -48,10 +52,12 @@ class nsInterfaceInfo : public nsIInterfaceInfo
|
|||
public:
|
||||
virtual ~nsInterfaceInfo();
|
||||
|
||||
// should be private
|
||||
XPTInterfaceDirectoryEntry* mEntry;
|
||||
#ifdef DEBUG
|
||||
void print(FILE *fd);
|
||||
#endif
|
||||
|
||||
private:
|
||||
XPTInterfaceDirectoryEntry* mEntry;
|
||||
nsInterfaceInfo* mParent;
|
||||
|
||||
uint16 mMethodBaseIndex;
|
||||
|
@ -60,5 +66,4 @@ private:
|
|||
uint16 mConstantCount;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsInterfaceInfo_h___ */
|
||||
|
|
|
@ -29,71 +29,14 @@
|
|||
#include "nsInterfaceInfo.h"
|
||||
#include "xptinfo.h"
|
||||
|
||||
#include "prio.h"
|
||||
#include "plstr.h"
|
||||
#include "prenv.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"
|
||||
|
||||
// should get multiple xpt files from some well-known dir.
|
||||
#define XPTFILE "simple.xpt"
|
||||
|
||||
// Stolen from xpt_dump.c
|
||||
// todo - lazy loading of file, etc.
|
||||
XPTHeader *getheader() {
|
||||
XPTState *state;
|
||||
XPTCursor curs, *cursor = &curs;
|
||||
XPTHeader *header;
|
||||
struct stat file_stat;
|
||||
int flen;
|
||||
char *whole;
|
||||
FILE *in;
|
||||
|
||||
if (stat(XPTFILE, &file_stat) != 0) {
|
||||
perror("FAILED: fstat");
|
||||
return NULL;
|
||||
}
|
||||
flen = file_stat.st_size;
|
||||
in = fopen(XPTFILE, "rb");
|
||||
|
||||
if (!in) {
|
||||
perror("FAILED: fopen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
whole = (char *)malloc(flen);
|
||||
if (!whole) {
|
||||
perror("FAILED: malloc for whole");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (flen > 0) {
|
||||
fread(whole, flen, 1, in);
|
||||
state = XPT_NewXDRState(XPT_DECODE, whole, flen);
|
||||
if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) {
|
||||
fprintf(stdout, "MakeCursor failed\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!XPT_DoHeader(cursor, &header)) {
|
||||
fprintf(stdout, "DoHeader failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(header);
|
||||
|
||||
XPT_DestroyXDRState(state);
|
||||
// assum'd to be OK
|
||||
free(whole);
|
||||
fclose(in);
|
||||
return header;
|
||||
}
|
||||
|
||||
free(whole);
|
||||
fclose(in);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static NS_DEFINE_IID(kIIIManagerIID, NS_IINTERFACEINFO_MANAGER_IID);
|
||||
NS_IMPL_ISUPPORTS(nsInterfaceInfoManager, kIIIManagerIID);
|
||||
|
||||
|
@ -139,53 +82,279 @@ nsInterfaceInfoManager::nsInterfaceInfoManager()
|
|||
NS_INIT_REFCNT();
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
mInfoArray = (nsInterfaceInfo**) calloc(HACK_CACHE_SIZE, sizeof(void*));
|
||||
|
||||
mHeader = getheader();
|
||||
PR_ASSERT((mHeader != NULL));
|
||||
|
||||
nsServiceManager::GetService(kAllocatorCID,
|
||||
kIAllocatorIID,
|
||||
(nsISupports **)&mAllocator);
|
||||
|
||||
PR_ASSERT((mAllocator != NULL));
|
||||
|
||||
initInterfaceTables();
|
||||
}
|
||||
|
||||
nsInterfaceInfo *
|
||||
nsInterfaceInfoManager::buildII(XPTInterfaceDirectoryEntry *entry) {
|
||||
int i;
|
||||
for (i = 0; i < HACK_CACHE_SIZE; i++) {
|
||||
if (mInfoArray[i] == NULL)
|
||||
break;
|
||||
if (mInfoArray[i]->mEntry == entry)
|
||||
return mInfoArray[i];
|
||||
// Stolen and modified from xpt_dump.c
|
||||
XPTHeader *getHeader(const char *filename) {
|
||||
XPTState *state = NULL;
|
||||
XPTCursor curs, *cursor = &curs;
|
||||
XPTHeader *header = NULL;
|
||||
PRFileInfo fileinfo;
|
||||
PRUint32 flen;
|
||||
char *whole = NULL;
|
||||
PRFileDesc *in = NULL;
|
||||
|
||||
if (PR_GetFileInfo(filename, &fileinfo) != PR_SUCCESS) {
|
||||
NS_ERROR("PR_GetFileInfo failed");
|
||||
return NULL;
|
||||
}
|
||||
flen = fileinfo.size;
|
||||
|
||||
whole = (char *)malloc(flen);
|
||||
if (!whole) {
|
||||
NS_ERROR("FAILED: malloc for whole");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ok, no dice. Does it have a parent?
|
||||
nsInterfaceInfo *parent = NULL;
|
||||
if (entry->interface_descriptor->parent_interface != NULL) {
|
||||
for (i = 0; i < HACK_CACHE_SIZE; i++) {
|
||||
if (mInfoArray[i] == NULL)
|
||||
break;
|
||||
if (mInfoArray[i]->mEntry ==
|
||||
entry->interface_descriptor->parent_interface)
|
||||
parent = mInfoArray[i];
|
||||
// XXX changed this to PR_OPEN; does this do binary for windows? ("b")
|
||||
// in = fopen(filename, "rb");
|
||||
in = PR_Open(filename, PR_RDONLY, 0);
|
||||
if (!in) {
|
||||
NS_ERROR("FAILED: fopen");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (flen > 0) {
|
||||
PRInt32 howmany = PR_Read(in, whole, flen);
|
||||
if (howmany < 0) {
|
||||
NS_ERROR("FAILED: reading typelib file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
// XXX lengths are PRUInt32, reads are PRInt32?
|
||||
if (howmany < flen) {
|
||||
NS_ERROR("short read of typelib file");
|
||||
goto out;
|
||||
}
|
||||
state = XPT_NewXDRState(XPT_DECODE, whole, flen);
|
||||
if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) {
|
||||
NS_ERROR("MakeCursor failed\n");
|
||||
goto out;
|
||||
}
|
||||
if (!XPT_DoHeader(cursor, &header)) {
|
||||
NS_ERROR("DoHeader failed\n");
|
||||
goto out;
|
||||
}
|
||||
if (parent == NULL)
|
||||
parent = buildII(entry->interface_descriptor->parent_interface);
|
||||
PR_ASSERT(parent);
|
||||
}
|
||||
|
||||
nsInterfaceInfo *result = new nsInterfaceInfo(entry, parent);
|
||||
|
||||
while (mInfoArray[i] == NULL)
|
||||
i++;
|
||||
PR_ASSERT(i < HACK_CACHE_SIZE);
|
||||
mInfoArray[i] = result;
|
||||
|
||||
return result;
|
||||
out:
|
||||
if (state != NULL)
|
||||
XPT_DestroyXDRState(state);
|
||||
if (whole != NULL)
|
||||
free(whole);
|
||||
if (in != NULL)
|
||||
PR_Close(in);
|
||||
return header;
|
||||
}
|
||||
|
||||
static void
|
||||
indexify_file(const char *filename,
|
||||
PLHashTable *interfaceTable,
|
||||
PLHashTable *typelibTable,
|
||||
nsHashtable *IIDTable,
|
||||
nsIAllocator *al)
|
||||
{
|
||||
XPTHeader *header = getHeader(filename);
|
||||
|
||||
int limit = header->num_interfaces;
|
||||
|
||||
interface_record *value;
|
||||
#ifdef DEBUG_mccabe
|
||||
static int which = 0;
|
||||
which++;
|
||||
#endif
|
||||
for (int i = 0; i < limit; i++) {
|
||||
XPTInterfaceDirectoryEntry *current = header->interface_directory + i;
|
||||
|
||||
// associate the current entry with the header it came from.
|
||||
PL_HashTableAdd(typelibTable, current, header);
|
||||
|
||||
#ifdef DEBUG_mccabe
|
||||
fprintf(stderr, "%s", current->name);
|
||||
#endif
|
||||
// first try to look it up...
|
||||
value = (interface_record *)PL_HashTableLookup(interfaceTable,
|
||||
current->name);
|
||||
// if none found, make a dummy record.
|
||||
if (value == NULL) {
|
||||
value = new interface_record();
|
||||
value->which_header = NULL;
|
||||
value->resolved = PR_FALSE;
|
||||
value->which = -1;
|
||||
value->entry = NULL;
|
||||
value->info = NULL;
|
||||
void *hashEntry =
|
||||
PL_HashTableAdd(interfaceTable, current->name, value);
|
||||
#ifdef DEBUG_mccabe
|
||||
fprintf(stderr, "... added, %d\n", which);
|
||||
#endif
|
||||
NS_ASSERTION(hashEntry != NULL, "PL_HashTableAdd failed?");
|
||||
}
|
||||
#ifdef DEBUG_MCCABE
|
||||
else {
|
||||
fprintf(stderr, "... found, %d\n", value->which);
|
||||
}
|
||||
#endif
|
||||
|
||||
// save info from the interface in the global table. if it's resolved.
|
||||
if (current->interface_descriptor != NULL) {
|
||||
// we claim it should only be defined once. XXX ?
|
||||
NS_ASSERTION(value->which_header == NULL,
|
||||
"some interface def'd in multiple typelibs.");
|
||||
value->which_header = header;
|
||||
value->resolved = PR_TRUE;
|
||||
value->which = which;
|
||||
value->entry = current;
|
||||
|
||||
// XXX is this a leak?
|
||||
nsIDKey idKey(current->iid);
|
||||
#ifdef DEBUG
|
||||
char * found_name;
|
||||
found_name = (char *)IIDTable->Get(&idKey);
|
||||
NS_ASSERTION(found_name == NULL,
|
||||
"iid already associated with a name?");
|
||||
#endif
|
||||
IIDTable->Put(&idKey, current->name);
|
||||
#ifdef DEBUG_mccabe
|
||||
fprintf(stderr, "\t... resolved, %d\n", value->which);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// as many InterfaceDirectoryEntries as we expect to see.
|
||||
#define XPT_HASHSIZE 64
|
||||
|
||||
#ifdef DEBUG
|
||||
static PRIntn
|
||||
check_enumerator(PLHashEntry *he, PRIntn index, void *arg);
|
||||
#endif
|
||||
|
||||
static PLHashNumber
|
||||
hash_by_value(const void *key) {
|
||||
return (uint32)key;
|
||||
}
|
||||
|
||||
void nsInterfaceInfoManager::initInterfaceTables()
|
||||
{
|
||||
// make a hashtable to associate names with arbitrary info
|
||||
this->mInterfaceTable = PL_NewHashTable(XPT_HASHSIZE,
|
||||
PL_HashString, // hash keys
|
||||
PL_CompareStrings, // compare keys
|
||||
PL_CompareValues, // comp values
|
||||
NULL, NULL);
|
||||
|
||||
// make a hashtable to associate InterfaceDirectoryEntry values
|
||||
// with XPTHeaders. (for nsXPTParamInfo::GetInterface)
|
||||
this->mTypelibTable = PL_NewHashTable(XPT_HASHSIZE,
|
||||
hash_by_value,
|
||||
PL_CompareValues,
|
||||
PL_CompareValues,
|
||||
NULL, NULL);
|
||||
|
||||
// make a hashtable to map iids to names
|
||||
this->mIIDTable = new nsHashtable(XPT_HASHSIZE);
|
||||
|
||||
// First, find the xpt directory from the env.
|
||||
// XXX don't free this?
|
||||
char *xptdirname = PR_GetEnv("XPTDIR");
|
||||
NS_ASSERTION(xptdirname != NULL,
|
||||
"set env var XPTDIR to a directory containg .xpt files.");
|
||||
|
||||
// now loop thru the xpt files in the directory.
|
||||
|
||||
// XXX This code stolen with few modifications from nsRepository; any
|
||||
// point in doing it through them instead?)
|
||||
|
||||
PRDir *xptdir = PR_OpenDir(xptdirname);
|
||||
if (xptdir == NULL) {
|
||||
NS_ERROR("Couldn't open XPT directory");
|
||||
return; // XXX fail gigantically.
|
||||
}
|
||||
|
||||
// Create a buffer that has dir/ in it so we can append
|
||||
// the filename each time in the loop
|
||||
char fullname[1024]; // NS_MAX_FILENAME_LEN
|
||||
PL_strncpyz(fullname, xptdirname, sizeof(fullname));
|
||||
unsigned int n = strlen(fullname);
|
||||
if (n+1 < sizeof(fullname)) {
|
||||
fullname[n] = '/';
|
||||
n++;
|
||||
}
|
||||
char *filepart = fullname + n;
|
||||
|
||||
PRDirEntry *dirent = NULL;
|
||||
#ifdef DEBUG_mccabe
|
||||
int which = 0;
|
||||
#endif
|
||||
while ((dirent = PR_ReadDir(xptdir, PR_SKIP_BOTH)) != NULL) {
|
||||
PL_strncpyz(filepart, dirent->name, sizeof(fullname)-n);
|
||||
PRFileInfo statbuf;
|
||||
// stattable?
|
||||
if (PR_GetFileInfo(fullname,&statbuf) != PR_SUCCESS)
|
||||
continue;
|
||||
// plain file?
|
||||
else if (statbuf.type != PR_FILE_FILE)
|
||||
continue;
|
||||
// .xpt suffix?
|
||||
int flen = PL_strlen(fullname);
|
||||
if (flen >= 4 && !PL_strcasecmp(&(fullname[flen - 4]), ".xpt")) {
|
||||
// it's a valid file, read it in.
|
||||
#ifdef DEBUG_mccabe
|
||||
which++;
|
||||
fprintf(stderr, "%d %s\n", which, fullname);
|
||||
#endif
|
||||
indexify_file(fullname,
|
||||
this->mInterfaceTable,
|
||||
this->mTypelibTable,
|
||||
this->mIIDTable,
|
||||
this->mAllocator);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
PR_CloseDir(xptdir);
|
||||
|
||||
#ifdef DEBUG
|
||||
// scan here to confirm that all interfaces are resolved.
|
||||
PL_HashTableEnumerateEntries(this->mInterfaceTable,
|
||||
check_enumerator,
|
||||
this->mIIDTable);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PRIntn check_enumerator(PLHashEntry *he, PRIntn index, void *arg) {
|
||||
char *key = (char *)he->key;
|
||||
interface_record *value = (interface_record *)he->value;
|
||||
nsHashtable *iidtable = (nsHashtable *)arg;
|
||||
|
||||
|
||||
if (value->resolved == PR_FALSE) {
|
||||
fprintf(stderr, "unresolved interface %s\n", key);
|
||||
} else {
|
||||
NS_ASSERTION(value->entry, "resolved, but no entry?");
|
||||
nsIDKey idKey(value->entry->iid);
|
||||
char *name_from_iid = (char *)iidtable->Get(&idKey);
|
||||
NS_ASSERTION(name_from_iid != NULL,
|
||||
"no name assoc'd with iid for entry for name?");
|
||||
|
||||
// XXX note that below is only ncc'ly the case if xdr doesn't give us
|
||||
// duplicated strings.
|
||||
// NS_ASSERTION(name_from_iid == key,
|
||||
// "key and iid name xpected to be same");
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsInterfaceInfoManager::~nsInterfaceInfoManager()
|
||||
{
|
||||
// let the singleton leak
|
||||
|
@ -193,76 +362,115 @@ nsInterfaceInfoManager::~nsInterfaceInfoManager()
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsInterfaceInfoManager::GetInfoForIID(const nsIID* iid,
|
||||
nsIInterfaceInfo** info)
|
||||
nsIInterfaceInfo** info)
|
||||
{
|
||||
for(int i = 0; i < mHeader->num_interfaces; i++) {
|
||||
XPTInterfaceDirectoryEntry *entry = &mHeader->interface_directory[i];
|
||||
if (iid->Equals(entry->iid)) {
|
||||
*info = buildII(entry);
|
||||
NS_ADDREF(*info);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
*info = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
nsIDKey idKey(*iid);
|
||||
char *result_name = (char *)this->mIIDTable->Get(&idKey);
|
||||
|
||||
return this->GetInfoForName(result_name, info);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInterfaceInfoManager::GetInfoForName(const char* name,
|
||||
nsIInterfaceInfo** info)
|
||||
nsIInterfaceInfo** info)
|
||||
{
|
||||
for(int i = 0; i < mHeader->num_interfaces; i++) {
|
||||
XPTInterfaceDirectoryEntry *entry = &mHeader->interface_directory[i];
|
||||
if (!strcmp(name, entry->name)) {
|
||||
*info = buildII(entry);
|
||||
NS_ADDREF(*info);
|
||||
return NS_OK;
|
||||
interface_record *record =
|
||||
(interface_record *)PL_HashTableLookup(this->mInterfaceTable, name);
|
||||
if (record == NULL || record->resolved == PR_FALSE) {
|
||||
*info = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PR_ASSERT(record->entry != NULL);
|
||||
|
||||
// Is there already an II obj associated with the interface_record?
|
||||
if (record->info != NULL) {
|
||||
// yay!
|
||||
*info = record->info;
|
||||
NS_ADDREF(*info);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nope, better make one. first, find a parent for it.
|
||||
nsIInterfaceInfo *parent;
|
||||
XPTInterfaceDirectoryEntry *entry = record->entry;
|
||||
uint16 parent_index = entry->interface_descriptor->parent_interface;
|
||||
// Does it _get_ a parent? (is it nsISupports?)
|
||||
if (parent_index == 0) {
|
||||
// presumably this is only the case for nsISupports.
|
||||
parent = NULL;
|
||||
} else {
|
||||
// there's a parent index that points to an entry in the same table
|
||||
// that this one was defined in. Accounting for magic offset.
|
||||
XPTInterfaceDirectoryEntry *parent_entry =
|
||||
record->which_header->interface_directory + parent_index - 1;
|
||||
// get a name from it (which should never be null) and build
|
||||
// that. XXX OPT Hm, could have a helper function to avoid
|
||||
// second lookup if this entry happens to be resolved.
|
||||
nsresult nsr = GetInfoForName(parent_entry->name, &parent);
|
||||
if (NS_IS_ERROR(nsr)) {
|
||||
*info = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
*info = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// got a parent for it, now build the object itself
|
||||
nsInterfaceInfo *result =
|
||||
new nsInterfaceInfo(entry, (nsInterfaceInfo *)parent);
|
||||
*info = result;
|
||||
NS_ADDREF(*info);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInterfaceInfoManager::GetIIDForName(const char* name, nsIID** iid)
|
||||
{
|
||||
for(int i = 0; i < mHeader->num_interfaces; i++) {
|
||||
XPTInterfaceDirectoryEntry *entry = &mHeader->interface_directory[i];
|
||||
if (!strcmp(name, entry->name)) {
|
||||
nsIID* p;
|
||||
|
||||
|
||||
if(!(p = (nsIID*)mAllocator->Alloc(sizeof(nsIID))))
|
||||
break;
|
||||
|
||||
// XXX I'm confused here about the lifetime of IID pointers.
|
||||
memcpy(p, &entry->iid, sizeof(nsIID));
|
||||
*iid = p;
|
||||
return NS_OK;
|
||||
}
|
||||
interface_record *record =
|
||||
(interface_record *)PL_HashTableLookup(this->mInterfaceTable, name);
|
||||
if (record == NULL || record->resolved == PR_FALSE) {
|
||||
*iid = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*iid = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
PR_ASSERT(record->entry != NULL);
|
||||
|
||||
nsIID* p;
|
||||
if(!(p = (nsIID *)mAllocator->Alloc(sizeof(nsIID))))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// XXX I'm confused here about the lifetime of IID pointers.
|
||||
memcpy(p, &record->entry->iid, sizeof(nsIID));
|
||||
*iid = p;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInterfaceInfoManager::GetNameForIID(const nsIID* iid, char** name)
|
||||
{
|
||||
for(int i = 0; i < mHeader->num_interfaces; i++) {
|
||||
XPTInterfaceDirectoryEntry *entry = &mHeader->interface_directory[i];
|
||||
if (iid->Equals(entry->iid)) {
|
||||
char* p;
|
||||
int len = strlen(entry->name)+1;
|
||||
if(!(p = (char*)mAllocator->Alloc(len)))
|
||||
break;
|
||||
memcpy(p, &entry->name, len);
|
||||
*name = p;
|
||||
return NS_OK;
|
||||
}
|
||||
nsIDKey idKey(*iid);
|
||||
char *result_name = (char *)this->mIIDTable->Get(&idKey);
|
||||
|
||||
#ifdef DEBUG
|
||||
// XXX assert here that lookup in table matches iid?
|
||||
nsIID *newid;
|
||||
nsresult isok = GetIIDForName(result_name, &newid);
|
||||
PR_ASSERT(newid->Equals(*newid));
|
||||
PR_ASSERT(isok == NS_OK);
|
||||
#endif
|
||||
|
||||
if (result_name == NULL) {
|
||||
*name = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*name = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
char *p;
|
||||
int len = strlen(result_name) + 1;
|
||||
if(!(p = (char *)mAllocator->Alloc(len))) {
|
||||
*name = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
memcpy(p, result_name, len);
|
||||
*name = p;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX this goes away; IIM should be a service.
|
||||
// ... where does decl for this go?
|
||||
|
@ -272,3 +480,35 @@ XPTI_GetInterfaceInfoManager()
|
|||
{
|
||||
return nsInterfaceInfoManager::GetInterfaceInfoManager();
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct XPTInterfaceDirectoryEntry {
|
||||
nsID iid;
|
||||
char *name;
|
||||
char *name_space;
|
||||
XPTInterfaceDescriptor *interface_descriptor;
|
||||
#if 0 /* not yet */
|
||||
/* not stored on disk */
|
||||
uint32 offset; /* the offset for an ID still to be read */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct XPTInterfaceDescriptor {
|
||||
uint16 parent_interface;
|
||||
uint16 num_methods;
|
||||
XPTMethodDescriptor *method_descriptors;
|
||||
uint16 num_constants;
|
||||
XPTConstDescriptor *const_descriptors;
|
||||
};
|
||||
|
||||
struct XPTHeader {
|
||||
char magic[16];
|
||||
uint8 major_version;
|
||||
uint8 minor_version;
|
||||
uint16 num_interfaces;
|
||||
uint32 file_length;
|
||||
XPTInterfaceDirectoryEntry *interface_directory;
|
||||
uint32 data_pool;
|
||||
XPTAnnotation *annotations;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
|
||||
#include "nsInterfaceInfo.h"
|
||||
|
||||
#include "nsHashtable.h"
|
||||
|
||||
#include "plhash.h"
|
||||
|
||||
class hash_record;
|
||||
|
||||
class nsInterfaceInfoManager : public nsIInterfaceInfoManager
|
||||
{
|
||||
NS_DECL_ISUPPORTS;
|
||||
|
@ -48,13 +54,37 @@ public:
|
|||
static nsIAllocator* GetAllocator(nsInterfaceInfoManager* iim = NULL);
|
||||
|
||||
private:
|
||||
// temporary hack
|
||||
nsInterfaceInfo **mInfoArray;
|
||||
nsInterfaceInfo *buildII(XPTInterfaceDirectoryEntry *entry);
|
||||
friend nsIInterfaceInfo*
|
||||
nsXPTParamInfo::GetInterface(XPTInterfaceDirectoryEntry *entry) const;
|
||||
friend const nsIID*
|
||||
nsXPTParamInfo::GetInterfaceIID(XPTInterfaceDirectoryEntry *entry) const;
|
||||
|
||||
void initInterfaceTables();
|
||||
|
||||
// mapping between names and records
|
||||
PLHashTable *mInterfaceTable;
|
||||
|
||||
// mapping between entries and typelibs (for nsXPTParamInfo::GetInterface)
|
||||
PLHashTable *mTypelibTable;
|
||||
|
||||
// mapping between iids and names
|
||||
// (record handling is looked up by name; iids are translated there)
|
||||
nsHashtable *mIIDTable;
|
||||
|
||||
XPTHeader *mHeader;
|
||||
nsInterfaceInfo *mParent;
|
||||
nsIAllocator* mAllocator;
|
||||
};
|
||||
|
||||
// For references in the mInterfaceTable hashtable.
|
||||
class interface_record {
|
||||
public:
|
||||
XPTHeader *which_header;
|
||||
PRBool resolved;
|
||||
int which;
|
||||
XPTInterfaceDirectoryEntry *entry;
|
||||
nsInterfaceInfo *info;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* nsInterfaceInfoManager_h___ */
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
* Reserved.
|
||||
*/
|
||||
|
||||
// Convienence bits of nsXPTParamInfo that don't fit into xpt_cpp.h
|
||||
// flyweight wrappers.
|
||||
/*
|
||||
* Convienence bits of nsXPTParamInfo that don't fit into xpt_cpp.h
|
||||
* flyweight wrappers.
|
||||
*/
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
|
@ -31,26 +33,67 @@
|
|||
// Placeholder - this implementation just returns NULL.
|
||||
|
||||
nsIInterfaceInfo*
|
||||
nsXPTParamInfo::GetInterface() const
|
||||
nsXPTParamInfo::GetInterface(XPTInterfaceDirectoryEntry *entry) const
|
||||
{
|
||||
NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE,"not an interface");
|
||||
NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE,
|
||||
"not an interface");
|
||||
|
||||
nsIInterfaceInfoManager* mgr;
|
||||
if(!(mgr = nsInterfaceInfoManager::GetInterfaceInfoManager()))
|
||||
return NULL;
|
||||
nsInterfaceInfoManager* mymgr = (nsInterfaceInfoManager *)mgr;
|
||||
|
||||
// nsIInterfaceInfo* info;
|
||||
// mgr->GetInfoForIID(&InterfaceDirectoryEntryTable[type.type.interface].iid,
|
||||
// &info);
|
||||
NS_RELEASE(mgr);
|
||||
// return info;
|
||||
return NULL;
|
||||
// what typelib did the entry come from?
|
||||
XPTHeader *which_header =
|
||||
(XPTHeader *)PL_HashTableLookup(mymgr->mTypelibTable, entry);
|
||||
NS_ASSERTION(which_header != NULL, "");
|
||||
|
||||
// can't use IID, because it could be null for this entry.
|
||||
char *interface_name;
|
||||
interface_name = which_header->interface_directory[type.type.interface].name;
|
||||
|
||||
nsIInterfaceInfo *info;
|
||||
nsresult nsr = mymgr->GetInfoForName(interface_name, &info);
|
||||
if (NS_IS_ERROR(nsr)) {
|
||||
NS_RELEASE(mgr);
|
||||
return NULL;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
const nsIID*
|
||||
nsXPTParamInfo::GetInterfaceIID() const
|
||||
nsXPTParamInfo::GetInterfaceIID(XPTInterfaceDirectoryEntry *entry) const
|
||||
{
|
||||
NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE,"not an interface");
|
||||
// return &InterfaceDirectoryEntryTable[type.type.interface].iid;
|
||||
return (const nsIID*) NULL;
|
||||
NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE,
|
||||
"not an interface");
|
||||
|
||||
nsIInterfaceInfoManager* mgr;
|
||||
if(!(mgr = nsInterfaceInfoManager::GetInterfaceInfoManager()))
|
||||
return NULL;
|
||||
nsInterfaceInfoManager* mymgr = (nsInterfaceInfoManager *)mgr;
|
||||
|
||||
// what typelib did the entry come from?
|
||||
XPTHeader *which_header =
|
||||
(XPTHeader *)PL_HashTableLookup(mymgr->mTypelibTable, entry);
|
||||
NS_ASSERTION(which_header != NULL, "");
|
||||
|
||||
// can't use IID, because it could be null for this entry.
|
||||
char *interface_name;
|
||||
interface_name = which_header->interface_directory[type.type.interface].name;
|
||||
|
||||
nsIID* iid;
|
||||
|
||||
nsresult nsr = mymgr->GetIIDForName(interface_name, &iid);
|
||||
if (NS_IS_ERROR(nsr)) {
|
||||
NS_RELEASE(mgr);
|
||||
return NULL;
|
||||
}
|
||||
return iid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -25,14 +25,54 @@
|
|||
#include "nsIInterfaceInfoManager.h"
|
||||
#include "xptinfo.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../src/nsInterfaceInfo.h"
|
||||
|
||||
static void RegAllocator();
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
RegAllocator();
|
||||
|
||||
nsIInterfaceInfoManager *iim = XPTI_GetInterfaceInfoManager();
|
||||
nsIID *iid;
|
||||
iim->GetIIDForName("Interface", &iid);
|
||||
nsIID *iid1, *iid2, *iid3, *iid4;
|
||||
char *name1, *name2, *name3, *name4;
|
||||
nsIInterfaceInfo *info1, *info2, *info3, *info4;
|
||||
|
||||
fprintf(stderr, "\ngetting iid for 'Interface'\n");
|
||||
iim->GetIIDForName("Interface", &iid1);
|
||||
iim->GetNameForIID(iid1, &name1);
|
||||
fprintf(stderr, "%s iid %s\n", name1, iid1->ToString());
|
||||
|
||||
fprintf(stderr, "\ngetting iid for 'nsIBaseStream'\n");
|
||||
iim->GetIIDForName("nsIBaseStream", &iid2);
|
||||
iim->GetNameForIID(iid2, &name2);
|
||||
fprintf(stderr, "%s iid %s\n", name2, iid2->ToString());
|
||||
|
||||
fprintf(stderr, "iid: %s, name: %s\n", iid1->ToString(), name1);
|
||||
fprintf(stderr, "iid: %s, name: %s\n", iid2->ToString(), name2);
|
||||
|
||||
fprintf(stderr, "\ngetting info for iid2 from above\n");
|
||||
iim->GetInfoForIID(iid2, &info2);
|
||||
#ifdef DEBUG
|
||||
((nsInterfaceInfo *)info2)->print(stderr);
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n");
|
||||
iim->GetIIDForName("nsIInputStream", &iid3);
|
||||
iim->GetNameForIID(iid3, &name3);
|
||||
fprintf(stderr, "%s iid %s\n", name3, iid2->ToString());
|
||||
iim->GetInfoForIID(iid3, &info3);
|
||||
#ifdef DEBUG
|
||||
((nsInterfaceInfo *)info3)->print(stderr);
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "\ngetting info for name 'nsIBidirectionalEnumerator'\n");
|
||||
iim->GetInfoForName("nsIBidirectionalEnumerator", &info4);
|
||||
#ifdef DEBUG
|
||||
((nsInterfaceInfo *)info4)->print(stderr);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -59,5 +99,3 @@ static void RegAllocator()
|
|||
nsRepository::RegisterComponent(kAllocatorCID, NULL, NULL, XPCOM_DLL,
|
||||
PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
DIRS = public src
|
||||
|
||||
DIRS += tests
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += tests
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -115,10 +115,10 @@ public:
|
|||
// is associated with so that we can find the table this index indexes
|
||||
// and then find the referenced XPTInterfaceDirectoryEntry so that we can
|
||||
// find (or build) the appropriate nsIInterfaceInfo. Simple :)
|
||||
nsIInterfaceInfo* GetInterface() const ;
|
||||
nsIInterfaceInfo* GetInterface(XPTInterfaceDirectoryEntry *entry) const ;
|
||||
|
||||
// a *little* simpler than the above
|
||||
const nsIID* GetInterfaceIID() const ;
|
||||
const nsIID* GetInterfaceIID(XPTInterfaceDirectoryEntry *entry) const ;
|
||||
|
||||
private:
|
||||
nsXPTParamInfo(); // no implementation
|
||||
|
|
|
@ -31,23 +31,22 @@ static NS_DEFINE_IID(kIInterfaceInfoIID, NS_IINTERFACEINFO_IID);
|
|||
NS_IMPL_ISUPPORTS(nsInterfaceInfo, kIInterfaceInfoIID);
|
||||
|
||||
nsInterfaceInfo::nsInterfaceInfo(XPTInterfaceDirectoryEntry* entry,
|
||||
nsInterfaceInfo *parent)
|
||||
nsInterfaceInfo *parent)
|
||||
: mEntry(entry),
|
||||
mParent(parent)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
if(mParent)
|
||||
if(mParent != NULL) {
|
||||
NS_ADDREF(mParent);
|
||||
if(mParent) {
|
||||
mMethodBaseIndex =
|
||||
mParent->mMethodBaseIndex + mParent->mMethodCount;
|
||||
mConstantBaseIndex =
|
||||
mParent->mConstantBaseIndex + mParent->mConstantCount;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
mMethodBaseIndex = mConstantBaseIndex = 0;
|
||||
}
|
||||
|
||||
mMethodCount = mEntry->interface_descriptor->num_methods;
|
||||
mConstantCount = mEntry->interface_descriptor->num_constants;
|
||||
|
@ -55,7 +54,7 @@ nsInterfaceInfo::nsInterfaceInfo(XPTInterfaceDirectoryEntry* entry,
|
|||
|
||||
nsInterfaceInfo::~nsInterfaceInfo()
|
||||
{
|
||||
if(mParent)
|
||||
if(mParent != NULL)
|
||||
NS_RELEASE(mParent);
|
||||
}
|
||||
|
||||
|
@ -134,11 +133,10 @@ NS_IMETHODIMP
|
|||
nsInterfaceInfo::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
|
||||
{
|
||||
NS_PRECONDITION(info, "bad param");
|
||||
if(index < mMethodBaseIndex)
|
||||
if (index < mMethodBaseIndex)
|
||||
return mParent->GetMethodInfo(index, info);
|
||||
|
||||
if(index >= mMethodBaseIndex + mMethodCount)
|
||||
{
|
||||
if (index >= mMethodBaseIndex + mMethodCount) {
|
||||
NS_PRECONDITION(0, "bad param");
|
||||
*info = NULL;
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -146,8 +144,8 @@ nsInterfaceInfo::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
|
|||
|
||||
// else...
|
||||
*info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
|
||||
&mEntry->interface_descriptor->
|
||||
method_descriptors[index - mMethodBaseIndex]);
|
||||
&mEntry->interface_descriptor->
|
||||
method_descriptors[index - mMethodBaseIndex]);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -155,11 +153,10 @@ NS_IMETHODIMP
|
|||
nsInterfaceInfo::GetConstant(uint16 index, const nsXPTConstant** constant)
|
||||
{
|
||||
NS_PRECONDITION(constant, "bad param");
|
||||
if(index < mConstantBaseIndex)
|
||||
if (index < mConstantBaseIndex)
|
||||
return mParent->GetConstant(index, constant);
|
||||
|
||||
if(index >= mConstantBaseIndex + mConstantCount)
|
||||
{
|
||||
if (index >= mConstantBaseIndex + mConstantCount) {
|
||||
NS_PRECONDITION(0, "bad param");
|
||||
*constant = NULL;
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -167,7 +164,23 @@ nsInterfaceInfo::GetConstant(uint16 index, const nsXPTConstant** constant)
|
|||
|
||||
// else...
|
||||
*constant = NS_REINTERPRET_CAST(nsXPTConstant*,
|
||||
&mEntry->interface_descriptor->
|
||||
const_descriptors[index-mConstantBaseIndex]);
|
||||
&mEntry->interface_descriptor->
|
||||
const_descriptors[index-mConstantBaseIndex]);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
void
|
||||
nsInterfaceInfo::print(FILE *fd)
|
||||
{
|
||||
fprintf(fd, "iid: %s name: %s name_space: %s\n",
|
||||
mEntry->iid.ToString(),
|
||||
mEntry->name,
|
||||
mEntry->name_space);
|
||||
if (mParent != NULL) {
|
||||
fprintf(fd, "parent:\n\t");
|
||||
mParent->print(fd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#include "xpt_struct.h"
|
||||
#include "xpt_cpp.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
// XXX destroy this!
|
||||
class nsInterfaceInfo : public nsIInterfaceInfo
|
||||
{
|
||||
|
@ -48,10 +52,12 @@ class nsInterfaceInfo : public nsIInterfaceInfo
|
|||
public:
|
||||
virtual ~nsInterfaceInfo();
|
||||
|
||||
// should be private
|
||||
XPTInterfaceDirectoryEntry* mEntry;
|
||||
#ifdef DEBUG
|
||||
void print(FILE *fd);
|
||||
#endif
|
||||
|
||||
private:
|
||||
XPTInterfaceDirectoryEntry* mEntry;
|
||||
nsInterfaceInfo* mParent;
|
||||
|
||||
uint16 mMethodBaseIndex;
|
||||
|
@ -60,5 +66,4 @@ private:
|
|||
uint16 mConstantCount;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsInterfaceInfo_h___ */
|
||||
|
|
|
@ -29,71 +29,14 @@
|
|||
#include "nsInterfaceInfo.h"
|
||||
#include "xptinfo.h"
|
||||
|
||||
#include "prio.h"
|
||||
#include "plstr.h"
|
||||
#include "prenv.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"
|
||||
|
||||
// should get multiple xpt files from some well-known dir.
|
||||
#define XPTFILE "simple.xpt"
|
||||
|
||||
// Stolen from xpt_dump.c
|
||||
// todo - lazy loading of file, etc.
|
||||
XPTHeader *getheader() {
|
||||
XPTState *state;
|
||||
XPTCursor curs, *cursor = &curs;
|
||||
XPTHeader *header;
|
||||
struct stat file_stat;
|
||||
int flen;
|
||||
char *whole;
|
||||
FILE *in;
|
||||
|
||||
if (stat(XPTFILE, &file_stat) != 0) {
|
||||
perror("FAILED: fstat");
|
||||
return NULL;
|
||||
}
|
||||
flen = file_stat.st_size;
|
||||
in = fopen(XPTFILE, "rb");
|
||||
|
||||
if (!in) {
|
||||
perror("FAILED: fopen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
whole = (char *)malloc(flen);
|
||||
if (!whole) {
|
||||
perror("FAILED: malloc for whole");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (flen > 0) {
|
||||
fread(whole, flen, 1, in);
|
||||
state = XPT_NewXDRState(XPT_DECODE, whole, flen);
|
||||
if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) {
|
||||
fprintf(stdout, "MakeCursor failed\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!XPT_DoHeader(cursor, &header)) {
|
||||
fprintf(stdout, "DoHeader failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(header);
|
||||
|
||||
XPT_DestroyXDRState(state);
|
||||
// assum'd to be OK
|
||||
free(whole);
|
||||
fclose(in);
|
||||
return header;
|
||||
}
|
||||
|
||||
free(whole);
|
||||
fclose(in);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static NS_DEFINE_IID(kIIIManagerIID, NS_IINTERFACEINFO_MANAGER_IID);
|
||||
NS_IMPL_ISUPPORTS(nsInterfaceInfoManager, kIIIManagerIID);
|
||||
|
||||
|
@ -139,53 +82,279 @@ nsInterfaceInfoManager::nsInterfaceInfoManager()
|
|||
NS_INIT_REFCNT();
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
mInfoArray = (nsInterfaceInfo**) calloc(HACK_CACHE_SIZE, sizeof(void*));
|
||||
|
||||
mHeader = getheader();
|
||||
PR_ASSERT((mHeader != NULL));
|
||||
|
||||
nsServiceManager::GetService(kAllocatorCID,
|
||||
kIAllocatorIID,
|
||||
(nsISupports **)&mAllocator);
|
||||
|
||||
PR_ASSERT((mAllocator != NULL));
|
||||
|
||||
initInterfaceTables();
|
||||
}
|
||||
|
||||
nsInterfaceInfo *
|
||||
nsInterfaceInfoManager::buildII(XPTInterfaceDirectoryEntry *entry) {
|
||||
int i;
|
||||
for (i = 0; i < HACK_CACHE_SIZE; i++) {
|
||||
if (mInfoArray[i] == NULL)
|
||||
break;
|
||||
if (mInfoArray[i]->mEntry == entry)
|
||||
return mInfoArray[i];
|
||||
// Stolen and modified from xpt_dump.c
|
||||
XPTHeader *getHeader(const char *filename) {
|
||||
XPTState *state = NULL;
|
||||
XPTCursor curs, *cursor = &curs;
|
||||
XPTHeader *header = NULL;
|
||||
PRFileInfo fileinfo;
|
||||
PRUint32 flen;
|
||||
char *whole = NULL;
|
||||
PRFileDesc *in = NULL;
|
||||
|
||||
if (PR_GetFileInfo(filename, &fileinfo) != PR_SUCCESS) {
|
||||
NS_ERROR("PR_GetFileInfo failed");
|
||||
return NULL;
|
||||
}
|
||||
flen = fileinfo.size;
|
||||
|
||||
whole = (char *)malloc(flen);
|
||||
if (!whole) {
|
||||
NS_ERROR("FAILED: malloc for whole");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ok, no dice. Does it have a parent?
|
||||
nsInterfaceInfo *parent = NULL;
|
||||
if (entry->interface_descriptor->parent_interface != NULL) {
|
||||
for (i = 0; i < HACK_CACHE_SIZE; i++) {
|
||||
if (mInfoArray[i] == NULL)
|
||||
break;
|
||||
if (mInfoArray[i]->mEntry ==
|
||||
entry->interface_descriptor->parent_interface)
|
||||
parent = mInfoArray[i];
|
||||
// XXX changed this to PR_OPEN; does this do binary for windows? ("b")
|
||||
// in = fopen(filename, "rb");
|
||||
in = PR_Open(filename, PR_RDONLY, 0);
|
||||
if (!in) {
|
||||
NS_ERROR("FAILED: fopen");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (flen > 0) {
|
||||
PRInt32 howmany = PR_Read(in, whole, flen);
|
||||
if (howmany < 0) {
|
||||
NS_ERROR("FAILED: reading typelib file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
// XXX lengths are PRUInt32, reads are PRInt32?
|
||||
if (howmany < flen) {
|
||||
NS_ERROR("short read of typelib file");
|
||||
goto out;
|
||||
}
|
||||
state = XPT_NewXDRState(XPT_DECODE, whole, flen);
|
||||
if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) {
|
||||
NS_ERROR("MakeCursor failed\n");
|
||||
goto out;
|
||||
}
|
||||
if (!XPT_DoHeader(cursor, &header)) {
|
||||
NS_ERROR("DoHeader failed\n");
|
||||
goto out;
|
||||
}
|
||||
if (parent == NULL)
|
||||
parent = buildII(entry->interface_descriptor->parent_interface);
|
||||
PR_ASSERT(parent);
|
||||
}
|
||||
|
||||
nsInterfaceInfo *result = new nsInterfaceInfo(entry, parent);
|
||||
|
||||
while (mInfoArray[i] == NULL)
|
||||
i++;
|
||||
PR_ASSERT(i < HACK_CACHE_SIZE);
|
||||
mInfoArray[i] = result;
|
||||
|
||||
return result;
|
||||
out:
|
||||
if (state != NULL)
|
||||
XPT_DestroyXDRState(state);
|
||||
if (whole != NULL)
|
||||
free(whole);
|
||||
if (in != NULL)
|
||||
PR_Close(in);
|
||||
return header;
|
||||
}
|
||||
|
||||
static void
|
||||
indexify_file(const char *filename,
|
||||
PLHashTable *interfaceTable,
|
||||
PLHashTable *typelibTable,
|
||||
nsHashtable *IIDTable,
|
||||
nsIAllocator *al)
|
||||
{
|
||||
XPTHeader *header = getHeader(filename);
|
||||
|
||||
int limit = header->num_interfaces;
|
||||
|
||||
interface_record *value;
|
||||
#ifdef DEBUG_mccabe
|
||||
static int which = 0;
|
||||
which++;
|
||||
#endif
|
||||
for (int i = 0; i < limit; i++) {
|
||||
XPTInterfaceDirectoryEntry *current = header->interface_directory + i;
|
||||
|
||||
// associate the current entry with the header it came from.
|
||||
PL_HashTableAdd(typelibTable, current, header);
|
||||
|
||||
#ifdef DEBUG_mccabe
|
||||
fprintf(stderr, "%s", current->name);
|
||||
#endif
|
||||
// first try to look it up...
|
||||
value = (interface_record *)PL_HashTableLookup(interfaceTable,
|
||||
current->name);
|
||||
// if none found, make a dummy record.
|
||||
if (value == NULL) {
|
||||
value = new interface_record();
|
||||
value->which_header = NULL;
|
||||
value->resolved = PR_FALSE;
|
||||
value->which = -1;
|
||||
value->entry = NULL;
|
||||
value->info = NULL;
|
||||
void *hashEntry =
|
||||
PL_HashTableAdd(interfaceTable, current->name, value);
|
||||
#ifdef DEBUG_mccabe
|
||||
fprintf(stderr, "... added, %d\n", which);
|
||||
#endif
|
||||
NS_ASSERTION(hashEntry != NULL, "PL_HashTableAdd failed?");
|
||||
}
|
||||
#ifdef DEBUG_MCCABE
|
||||
else {
|
||||
fprintf(stderr, "... found, %d\n", value->which);
|
||||
}
|
||||
#endif
|
||||
|
||||
// save info from the interface in the global table. if it's resolved.
|
||||
if (current->interface_descriptor != NULL) {
|
||||
// we claim it should only be defined once. XXX ?
|
||||
NS_ASSERTION(value->which_header == NULL,
|
||||
"some interface def'd in multiple typelibs.");
|
||||
value->which_header = header;
|
||||
value->resolved = PR_TRUE;
|
||||
value->which = which;
|
||||
value->entry = current;
|
||||
|
||||
// XXX is this a leak?
|
||||
nsIDKey idKey(current->iid);
|
||||
#ifdef DEBUG
|
||||
char * found_name;
|
||||
found_name = (char *)IIDTable->Get(&idKey);
|
||||
NS_ASSERTION(found_name == NULL,
|
||||
"iid already associated with a name?");
|
||||
#endif
|
||||
IIDTable->Put(&idKey, current->name);
|
||||
#ifdef DEBUG_mccabe
|
||||
fprintf(stderr, "\t... resolved, %d\n", value->which);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// as many InterfaceDirectoryEntries as we expect to see.
|
||||
#define XPT_HASHSIZE 64
|
||||
|
||||
#ifdef DEBUG
|
||||
static PRIntn
|
||||
check_enumerator(PLHashEntry *he, PRIntn index, void *arg);
|
||||
#endif
|
||||
|
||||
static PLHashNumber
|
||||
hash_by_value(const void *key) {
|
||||
return (uint32)key;
|
||||
}
|
||||
|
||||
void nsInterfaceInfoManager::initInterfaceTables()
|
||||
{
|
||||
// make a hashtable to associate names with arbitrary info
|
||||
this->mInterfaceTable = PL_NewHashTable(XPT_HASHSIZE,
|
||||
PL_HashString, // hash keys
|
||||
PL_CompareStrings, // compare keys
|
||||
PL_CompareValues, // comp values
|
||||
NULL, NULL);
|
||||
|
||||
// make a hashtable to associate InterfaceDirectoryEntry values
|
||||
// with XPTHeaders. (for nsXPTParamInfo::GetInterface)
|
||||
this->mTypelibTable = PL_NewHashTable(XPT_HASHSIZE,
|
||||
hash_by_value,
|
||||
PL_CompareValues,
|
||||
PL_CompareValues,
|
||||
NULL, NULL);
|
||||
|
||||
// make a hashtable to map iids to names
|
||||
this->mIIDTable = new nsHashtable(XPT_HASHSIZE);
|
||||
|
||||
// First, find the xpt directory from the env.
|
||||
// XXX don't free this?
|
||||
char *xptdirname = PR_GetEnv("XPTDIR");
|
||||
NS_ASSERTION(xptdirname != NULL,
|
||||
"set env var XPTDIR to a directory containg .xpt files.");
|
||||
|
||||
// now loop thru the xpt files in the directory.
|
||||
|
||||
// XXX This code stolen with few modifications from nsRepository; any
|
||||
// point in doing it through them instead?)
|
||||
|
||||
PRDir *xptdir = PR_OpenDir(xptdirname);
|
||||
if (xptdir == NULL) {
|
||||
NS_ERROR("Couldn't open XPT directory");
|
||||
return; // XXX fail gigantically.
|
||||
}
|
||||
|
||||
// Create a buffer that has dir/ in it so we can append
|
||||
// the filename each time in the loop
|
||||
char fullname[1024]; // NS_MAX_FILENAME_LEN
|
||||
PL_strncpyz(fullname, xptdirname, sizeof(fullname));
|
||||
unsigned int n = strlen(fullname);
|
||||
if (n+1 < sizeof(fullname)) {
|
||||
fullname[n] = '/';
|
||||
n++;
|
||||
}
|
||||
char *filepart = fullname + n;
|
||||
|
||||
PRDirEntry *dirent = NULL;
|
||||
#ifdef DEBUG_mccabe
|
||||
int which = 0;
|
||||
#endif
|
||||
while ((dirent = PR_ReadDir(xptdir, PR_SKIP_BOTH)) != NULL) {
|
||||
PL_strncpyz(filepart, dirent->name, sizeof(fullname)-n);
|
||||
PRFileInfo statbuf;
|
||||
// stattable?
|
||||
if (PR_GetFileInfo(fullname,&statbuf) != PR_SUCCESS)
|
||||
continue;
|
||||
// plain file?
|
||||
else if (statbuf.type != PR_FILE_FILE)
|
||||
continue;
|
||||
// .xpt suffix?
|
||||
int flen = PL_strlen(fullname);
|
||||
if (flen >= 4 && !PL_strcasecmp(&(fullname[flen - 4]), ".xpt")) {
|
||||
// it's a valid file, read it in.
|
||||
#ifdef DEBUG_mccabe
|
||||
which++;
|
||||
fprintf(stderr, "%d %s\n", which, fullname);
|
||||
#endif
|
||||
indexify_file(fullname,
|
||||
this->mInterfaceTable,
|
||||
this->mTypelibTable,
|
||||
this->mIIDTable,
|
||||
this->mAllocator);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
PR_CloseDir(xptdir);
|
||||
|
||||
#ifdef DEBUG
|
||||
// scan here to confirm that all interfaces are resolved.
|
||||
PL_HashTableEnumerateEntries(this->mInterfaceTable,
|
||||
check_enumerator,
|
||||
this->mIIDTable);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PRIntn check_enumerator(PLHashEntry *he, PRIntn index, void *arg) {
|
||||
char *key = (char *)he->key;
|
||||
interface_record *value = (interface_record *)he->value;
|
||||
nsHashtable *iidtable = (nsHashtable *)arg;
|
||||
|
||||
|
||||
if (value->resolved == PR_FALSE) {
|
||||
fprintf(stderr, "unresolved interface %s\n", key);
|
||||
} else {
|
||||
NS_ASSERTION(value->entry, "resolved, but no entry?");
|
||||
nsIDKey idKey(value->entry->iid);
|
||||
char *name_from_iid = (char *)iidtable->Get(&idKey);
|
||||
NS_ASSERTION(name_from_iid != NULL,
|
||||
"no name assoc'd with iid for entry for name?");
|
||||
|
||||
// XXX note that below is only ncc'ly the case if xdr doesn't give us
|
||||
// duplicated strings.
|
||||
// NS_ASSERTION(name_from_iid == key,
|
||||
// "key and iid name xpected to be same");
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsInterfaceInfoManager::~nsInterfaceInfoManager()
|
||||
{
|
||||
// let the singleton leak
|
||||
|
@ -193,76 +362,115 @@ nsInterfaceInfoManager::~nsInterfaceInfoManager()
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsInterfaceInfoManager::GetInfoForIID(const nsIID* iid,
|
||||
nsIInterfaceInfo** info)
|
||||
nsIInterfaceInfo** info)
|
||||
{
|
||||
for(int i = 0; i < mHeader->num_interfaces; i++) {
|
||||
XPTInterfaceDirectoryEntry *entry = &mHeader->interface_directory[i];
|
||||
if (iid->Equals(entry->iid)) {
|
||||
*info = buildII(entry);
|
||||
NS_ADDREF(*info);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
*info = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
nsIDKey idKey(*iid);
|
||||
char *result_name = (char *)this->mIIDTable->Get(&idKey);
|
||||
|
||||
return this->GetInfoForName(result_name, info);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInterfaceInfoManager::GetInfoForName(const char* name,
|
||||
nsIInterfaceInfo** info)
|
||||
nsIInterfaceInfo** info)
|
||||
{
|
||||
for(int i = 0; i < mHeader->num_interfaces; i++) {
|
||||
XPTInterfaceDirectoryEntry *entry = &mHeader->interface_directory[i];
|
||||
if (!strcmp(name, entry->name)) {
|
||||
*info = buildII(entry);
|
||||
NS_ADDREF(*info);
|
||||
return NS_OK;
|
||||
interface_record *record =
|
||||
(interface_record *)PL_HashTableLookup(this->mInterfaceTable, name);
|
||||
if (record == NULL || record->resolved == PR_FALSE) {
|
||||
*info = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PR_ASSERT(record->entry != NULL);
|
||||
|
||||
// Is there already an II obj associated with the interface_record?
|
||||
if (record->info != NULL) {
|
||||
// yay!
|
||||
*info = record->info;
|
||||
NS_ADDREF(*info);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nope, better make one. first, find a parent for it.
|
||||
nsIInterfaceInfo *parent;
|
||||
XPTInterfaceDirectoryEntry *entry = record->entry;
|
||||
uint16 parent_index = entry->interface_descriptor->parent_interface;
|
||||
// Does it _get_ a parent? (is it nsISupports?)
|
||||
if (parent_index == 0) {
|
||||
// presumably this is only the case for nsISupports.
|
||||
parent = NULL;
|
||||
} else {
|
||||
// there's a parent index that points to an entry in the same table
|
||||
// that this one was defined in. Accounting for magic offset.
|
||||
XPTInterfaceDirectoryEntry *parent_entry =
|
||||
record->which_header->interface_directory + parent_index - 1;
|
||||
// get a name from it (which should never be null) and build
|
||||
// that. XXX OPT Hm, could have a helper function to avoid
|
||||
// second lookup if this entry happens to be resolved.
|
||||
nsresult nsr = GetInfoForName(parent_entry->name, &parent);
|
||||
if (NS_IS_ERROR(nsr)) {
|
||||
*info = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
*info = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// got a parent for it, now build the object itself
|
||||
nsInterfaceInfo *result =
|
||||
new nsInterfaceInfo(entry, (nsInterfaceInfo *)parent);
|
||||
*info = result;
|
||||
NS_ADDREF(*info);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInterfaceInfoManager::GetIIDForName(const char* name, nsIID** iid)
|
||||
{
|
||||
for(int i = 0; i < mHeader->num_interfaces; i++) {
|
||||
XPTInterfaceDirectoryEntry *entry = &mHeader->interface_directory[i];
|
||||
if (!strcmp(name, entry->name)) {
|
||||
nsIID* p;
|
||||
|
||||
|
||||
if(!(p = (nsIID*)mAllocator->Alloc(sizeof(nsIID))))
|
||||
break;
|
||||
|
||||
// XXX I'm confused here about the lifetime of IID pointers.
|
||||
memcpy(p, &entry->iid, sizeof(nsIID));
|
||||
*iid = p;
|
||||
return NS_OK;
|
||||
}
|
||||
interface_record *record =
|
||||
(interface_record *)PL_HashTableLookup(this->mInterfaceTable, name);
|
||||
if (record == NULL || record->resolved == PR_FALSE) {
|
||||
*iid = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*iid = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
PR_ASSERT(record->entry != NULL);
|
||||
|
||||
nsIID* p;
|
||||
if(!(p = (nsIID *)mAllocator->Alloc(sizeof(nsIID))))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// XXX I'm confused here about the lifetime of IID pointers.
|
||||
memcpy(p, &record->entry->iid, sizeof(nsIID));
|
||||
*iid = p;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInterfaceInfoManager::GetNameForIID(const nsIID* iid, char** name)
|
||||
{
|
||||
for(int i = 0; i < mHeader->num_interfaces; i++) {
|
||||
XPTInterfaceDirectoryEntry *entry = &mHeader->interface_directory[i];
|
||||
if (iid->Equals(entry->iid)) {
|
||||
char* p;
|
||||
int len = strlen(entry->name)+1;
|
||||
if(!(p = (char*)mAllocator->Alloc(len)))
|
||||
break;
|
||||
memcpy(p, &entry->name, len);
|
||||
*name = p;
|
||||
return NS_OK;
|
||||
}
|
||||
nsIDKey idKey(*iid);
|
||||
char *result_name = (char *)this->mIIDTable->Get(&idKey);
|
||||
|
||||
#ifdef DEBUG
|
||||
// XXX assert here that lookup in table matches iid?
|
||||
nsIID *newid;
|
||||
nsresult isok = GetIIDForName(result_name, &newid);
|
||||
PR_ASSERT(newid->Equals(*newid));
|
||||
PR_ASSERT(isok == NS_OK);
|
||||
#endif
|
||||
|
||||
if (result_name == NULL) {
|
||||
*name = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*name = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
char *p;
|
||||
int len = strlen(result_name) + 1;
|
||||
if(!(p = (char *)mAllocator->Alloc(len))) {
|
||||
*name = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
memcpy(p, result_name, len);
|
||||
*name = p;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX this goes away; IIM should be a service.
|
||||
// ... where does decl for this go?
|
||||
|
@ -272,3 +480,35 @@ XPTI_GetInterfaceInfoManager()
|
|||
{
|
||||
return nsInterfaceInfoManager::GetInterfaceInfoManager();
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct XPTInterfaceDirectoryEntry {
|
||||
nsID iid;
|
||||
char *name;
|
||||
char *name_space;
|
||||
XPTInterfaceDescriptor *interface_descriptor;
|
||||
#if 0 /* not yet */
|
||||
/* not stored on disk */
|
||||
uint32 offset; /* the offset for an ID still to be read */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct XPTInterfaceDescriptor {
|
||||
uint16 parent_interface;
|
||||
uint16 num_methods;
|
||||
XPTMethodDescriptor *method_descriptors;
|
||||
uint16 num_constants;
|
||||
XPTConstDescriptor *const_descriptors;
|
||||
};
|
||||
|
||||
struct XPTHeader {
|
||||
char magic[16];
|
||||
uint8 major_version;
|
||||
uint8 minor_version;
|
||||
uint16 num_interfaces;
|
||||
uint32 file_length;
|
||||
XPTInterfaceDirectoryEntry *interface_directory;
|
||||
uint32 data_pool;
|
||||
XPTAnnotation *annotations;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
|
||||
#include "nsInterfaceInfo.h"
|
||||
|
||||
#include "nsHashtable.h"
|
||||
|
||||
#include "plhash.h"
|
||||
|
||||
class hash_record;
|
||||
|
||||
class nsInterfaceInfoManager : public nsIInterfaceInfoManager
|
||||
{
|
||||
NS_DECL_ISUPPORTS;
|
||||
|
@ -48,13 +54,37 @@ public:
|
|||
static nsIAllocator* GetAllocator(nsInterfaceInfoManager* iim = NULL);
|
||||
|
||||
private:
|
||||
// temporary hack
|
||||
nsInterfaceInfo **mInfoArray;
|
||||
nsInterfaceInfo *buildII(XPTInterfaceDirectoryEntry *entry);
|
||||
friend nsIInterfaceInfo*
|
||||
nsXPTParamInfo::GetInterface(XPTInterfaceDirectoryEntry *entry) const;
|
||||
friend const nsIID*
|
||||
nsXPTParamInfo::GetInterfaceIID(XPTInterfaceDirectoryEntry *entry) const;
|
||||
|
||||
void initInterfaceTables();
|
||||
|
||||
// mapping between names and records
|
||||
PLHashTable *mInterfaceTable;
|
||||
|
||||
// mapping between entries and typelibs (for nsXPTParamInfo::GetInterface)
|
||||
PLHashTable *mTypelibTable;
|
||||
|
||||
// mapping between iids and names
|
||||
// (record handling is looked up by name; iids are translated there)
|
||||
nsHashtable *mIIDTable;
|
||||
|
||||
XPTHeader *mHeader;
|
||||
nsInterfaceInfo *mParent;
|
||||
nsIAllocator* mAllocator;
|
||||
};
|
||||
|
||||
// For references in the mInterfaceTable hashtable.
|
||||
class interface_record {
|
||||
public:
|
||||
XPTHeader *which_header;
|
||||
PRBool resolved;
|
||||
int which;
|
||||
XPTInterfaceDirectoryEntry *entry;
|
||||
nsInterfaceInfo *info;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* nsInterfaceInfoManager_h___ */
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
* Reserved.
|
||||
*/
|
||||
|
||||
// Convienence bits of nsXPTParamInfo that don't fit into xpt_cpp.h
|
||||
// flyweight wrappers.
|
||||
/*
|
||||
* Convienence bits of nsXPTParamInfo that don't fit into xpt_cpp.h
|
||||
* flyweight wrappers.
|
||||
*/
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
|
@ -31,26 +33,67 @@
|
|||
// Placeholder - this implementation just returns NULL.
|
||||
|
||||
nsIInterfaceInfo*
|
||||
nsXPTParamInfo::GetInterface() const
|
||||
nsXPTParamInfo::GetInterface(XPTInterfaceDirectoryEntry *entry) const
|
||||
{
|
||||
NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE,"not an interface");
|
||||
NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE,
|
||||
"not an interface");
|
||||
|
||||
nsIInterfaceInfoManager* mgr;
|
||||
if(!(mgr = nsInterfaceInfoManager::GetInterfaceInfoManager()))
|
||||
return NULL;
|
||||
nsInterfaceInfoManager* mymgr = (nsInterfaceInfoManager *)mgr;
|
||||
|
||||
// nsIInterfaceInfo* info;
|
||||
// mgr->GetInfoForIID(&InterfaceDirectoryEntryTable[type.type.interface].iid,
|
||||
// &info);
|
||||
NS_RELEASE(mgr);
|
||||
// return info;
|
||||
return NULL;
|
||||
// what typelib did the entry come from?
|
||||
XPTHeader *which_header =
|
||||
(XPTHeader *)PL_HashTableLookup(mymgr->mTypelibTable, entry);
|
||||
NS_ASSERTION(which_header != NULL, "");
|
||||
|
||||
// can't use IID, because it could be null for this entry.
|
||||
char *interface_name;
|
||||
interface_name = which_header->interface_directory[type.type.interface].name;
|
||||
|
||||
nsIInterfaceInfo *info;
|
||||
nsresult nsr = mymgr->GetInfoForName(interface_name, &info);
|
||||
if (NS_IS_ERROR(nsr)) {
|
||||
NS_RELEASE(mgr);
|
||||
return NULL;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
const nsIID*
|
||||
nsXPTParamInfo::GetInterfaceIID() const
|
||||
nsXPTParamInfo::GetInterfaceIID(XPTInterfaceDirectoryEntry *entry) const
|
||||
{
|
||||
NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE,"not an interface");
|
||||
// return &InterfaceDirectoryEntryTable[type.type.interface].iid;
|
||||
return (const nsIID*) NULL;
|
||||
NS_PRECONDITION(GetType().TagPart() == nsXPTType::T_INTERFACE,
|
||||
"not an interface");
|
||||
|
||||
nsIInterfaceInfoManager* mgr;
|
||||
if(!(mgr = nsInterfaceInfoManager::GetInterfaceInfoManager()))
|
||||
return NULL;
|
||||
nsInterfaceInfoManager* mymgr = (nsInterfaceInfoManager *)mgr;
|
||||
|
||||
// what typelib did the entry come from?
|
||||
XPTHeader *which_header =
|
||||
(XPTHeader *)PL_HashTableLookup(mymgr->mTypelibTable, entry);
|
||||
NS_ASSERTION(which_header != NULL, "");
|
||||
|
||||
// can't use IID, because it could be null for this entry.
|
||||
char *interface_name;
|
||||
interface_name = which_header->interface_directory[type.type.interface].name;
|
||||
|
||||
nsIID* iid;
|
||||
|
||||
nsresult nsr = mymgr->GetIIDForName(interface_name, &iid);
|
||||
if (NS_IS_ERROR(nsr)) {
|
||||
NS_RELEASE(mgr);
|
||||
return NULL;
|
||||
}
|
||||
return iid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -25,14 +25,54 @@
|
|||
#include "nsIInterfaceInfoManager.h"
|
||||
#include "xptinfo.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../src/nsInterfaceInfo.h"
|
||||
|
||||
static void RegAllocator();
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
RegAllocator();
|
||||
|
||||
nsIInterfaceInfoManager *iim = XPTI_GetInterfaceInfoManager();
|
||||
nsIID *iid;
|
||||
iim->GetIIDForName("Interface", &iid);
|
||||
nsIID *iid1, *iid2, *iid3, *iid4;
|
||||
char *name1, *name2, *name3, *name4;
|
||||
nsIInterfaceInfo *info1, *info2, *info3, *info4;
|
||||
|
||||
fprintf(stderr, "\ngetting iid for 'Interface'\n");
|
||||
iim->GetIIDForName("Interface", &iid1);
|
||||
iim->GetNameForIID(iid1, &name1);
|
||||
fprintf(stderr, "%s iid %s\n", name1, iid1->ToString());
|
||||
|
||||
fprintf(stderr, "\ngetting iid for 'nsIBaseStream'\n");
|
||||
iim->GetIIDForName("nsIBaseStream", &iid2);
|
||||
iim->GetNameForIID(iid2, &name2);
|
||||
fprintf(stderr, "%s iid %s\n", name2, iid2->ToString());
|
||||
|
||||
fprintf(stderr, "iid: %s, name: %s\n", iid1->ToString(), name1);
|
||||
fprintf(stderr, "iid: %s, name: %s\n", iid2->ToString(), name2);
|
||||
|
||||
fprintf(stderr, "\ngetting info for iid2 from above\n");
|
||||
iim->GetInfoForIID(iid2, &info2);
|
||||
#ifdef DEBUG
|
||||
((nsInterfaceInfo *)info2)->print(stderr);
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n");
|
||||
iim->GetIIDForName("nsIInputStream", &iid3);
|
||||
iim->GetNameForIID(iid3, &name3);
|
||||
fprintf(stderr, "%s iid %s\n", name3, iid2->ToString());
|
||||
iim->GetInfoForIID(iid3, &info3);
|
||||
#ifdef DEBUG
|
||||
((nsInterfaceInfo *)info3)->print(stderr);
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "\ngetting info for name 'nsIBidirectionalEnumerator'\n");
|
||||
iim->GetInfoForName("nsIBidirectionalEnumerator", &info4);
|
||||
#ifdef DEBUG
|
||||
((nsInterfaceInfo *)info4)->print(stderr);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -59,5 +99,3 @@ static void RegAllocator()
|
|||
nsRepository::RegisterComponent(kAllocatorCID, NULL, NULL, XPCOM_DLL,
|
||||
PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче