adding new file - not part of build

git-svn-id: svn://10.0.0.236/trunk@64329 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
jband%netscape.com
2000-03-28 05:10:05 +00:00
parent b20ae88f6e
commit 97ad980ef8
13 changed files with 4019 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* The nsIInterfaceInfo public declaration. */
#include "nsISupports.idl"
// forward declaration of non-XPCOM types
[ptr] native nsXPTMethodInfoPtr(nsXPTMethodInfo);
[ptr] native nsXPTConstantPtr(nsXPTConstant);
[ptr] native nsXPTParamInfoPtr(nsXPTParamInfo);
native nsXPTType(nsXPTType);
%{C++
class nsXPTMethodInfo;
class nsXPTConstant;
class nsXPTParamInfo;
class nsXPTType;
%}
/* this is NOT intended to be scriptable */
[uuid(215DBE04-94A7-11d2-BA58-00805F8A5DD7)]
interface nsIInterfaceInfo : nsISupports
{
readonly attribute string name;
readonly attribute nsIIDPtr IID;
PRBool isScriptable();
readonly attribute nsIInterfaceInfo parent;
/**
* These include counts for parent (and all ancestors).
*/
readonly attribute PRUint16 methodCount;
readonly attribute PRUint16 constantCount;
/**
* These include methods and constants for parent (and all ancestors).
*
* These do *not* make copies ***explicit bending of XPCOM rules***.
*/
void getMethodInfo(in PRUint16 index,
[shared, retval] out nsXPTMethodInfoPtr info);
void getMethodInfoForName(in string methodName, out PRUint16 index,
[shared, retval] out nsXPTMethodInfoPtr info);
void getConstant(in PRUint16 index,
[shared, retval] out nsXPTConstantPtr constant);
/**
* Get the interface information or iid associated with a param of some
* method in this interface.
*/
nsIInterfaceInfo getInfoForParam(in PRUint16 methodIndex,
[const] in nsXPTParamInfoPtr param);
nsIIDPtr getIIDForParam(in PRUint16 methodIndex,
[const] in nsXPTParamInfoPtr param);
/**
* These do *not* make copies ***explicit bending of XPCOM rules***.
*/
nsXPTType getTypeForParam(in PRUint16 methodIndex,
[const] in nsXPTParamInfoPtr param,
in PRUint16 dimension);
PRUint8 getSizeIsArgNumberForParam(in PRUint16 methodIndex,
[const] in nsXPTParamInfoPtr param,
in PRUint16 dimension);
PRUint8 getLengthIsArgNumberForParam(in PRUint16 methodIndex,
[const] in nsXPTParamInfoPtr param,
in PRUint16 dimension);
PRUint8 getInterfaceIsArgNumberForParam(in PRUint16 methodIndex,
[const] in nsXPTParamInfoPtr param);
};

View File

@@ -0,0 +1,43 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* The nsIInterfaceInfoManager public declaration. */
#include "nsISupports.idl"
#include "nsIInterfaceInfo.idl"
#include "nsIEnumerator.idl"
/* this is NOT intended to be scriptable */
[uuid(8B161900-BE2B-11d2-9831-006008962422)]
interface nsIInterfaceInfoManager : nsISupports
{
nsIInterfaceInfo getInfoForIID(in nsIIDPtr iid);
nsIInterfaceInfo getInfoForName(in string name);
nsIIDPtr getIIDForName(in string name);
string getNameForIID(in nsIIDPtr iid);
nsIEnumerator enumerateInterfaces();
void autoRegisterInterfaces();
};

View File

@@ -0,0 +1,30 @@
#ifndef NS_DECL_NSIINTERFACEINFO
#define NS_DECL_NSIINTERFACEINFO \
NS_IMETHOD GetName(char * *aName); \
NS_IMETHOD GetIID(nsIID * *aIID); \
NS_IMETHOD IsScriptable(PRBool *_retval); \
NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent); \
NS_IMETHOD GetMethodCount(PRUint16 *aMethodCount); \
NS_IMETHOD GetConstantCount(PRUint16 *aConstantCount); \
NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info); \
NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info); \
NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant); \
NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval); \
NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval); \
NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval); \
NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval); \
NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval); \
NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval);
#endif
#ifndef NS_DECL_NSIINTERFACEINFOMANAGER
#define NS_DECL_NSIINTERFACEINFOMANAGER \
NS_IMETHOD GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval); \
NS_IMETHOD GetInfoForName(const char *name, nsIInterfaceInfo **_retval); \
NS_IMETHOD GetIIDForName(const char *name, nsIID * *_retval); \
NS_IMETHOD GetNameForIID(const nsIID * iid, char **_retval); \
NS_IMETHOD EnumerateInterfaces(nsIEnumerator **_retval); \
NS_IMETHOD AutoRegisterInterfaces(void);
#endif

View File

@@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Implementation of xptiFile. */
#include "xptiprivate.h"
xptiFile::xptiFile()
: mSize(),
mDate(),
mName(nsnull),
mGuts(nsnull)
{
// empty
}
xptiFile::xptiFile(const nsInt64& aSize,
const nsInt64& aDate,
const char* aName,
xptiWorkingSet* aWorkingSet,
XPTHeader* aHeader /*= nsnull */)
: mSize(aSize),
mDate(aDate),
mName(aName),
mGuts(nsnull)
{
NS_ASSERTION(aWorkingSet,"bad param");
mName = XPT_STRDUP(aWorkingSet->GetStringArena(), aName);
if(aHeader)
SetHeader(aHeader);
}
xptiFile::xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet,
PRBool cloneGuts)
: mSize(r.mSize),
mDate(r.mDate),
mName(nsnull),
mGuts(nsnull)
{
NS_ASSERTION(aWorkingSet,"bad param");
mName = XPT_STRDUP(aWorkingSet->GetStringArena(), r.mName);
if(cloneGuts && r.mGuts)
mGuts = r.mGuts->Clone();
}
xptiFile::~xptiFile()
{
if(mGuts)
delete mGuts;
}
PRBool
xptiFile::SetHeader(XPTHeader* aHeader)
{
NS_ASSERTION(!mGuts,"bad state");
NS_ASSERTION(aHeader,"bad param");
mGuts = new xptiTypelibGuts(aHeader);
if(mGuts && !mGuts->IsValid())
{
delete mGuts;
mGuts = nsnull;
}
return mGuts != nsnull;
}

View File

@@ -0,0 +1,594 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Implementation of xptiInterfaceInfo. */
#include "xptiprivate.h"
NS_IMPL_THREADSAFE_ISUPPORTS1(xptiInterfaceInfo, nsIInterfaceInfo)
xptiInterfaceInfo::xptiInterfaceInfo(const char* name,
const nsID& iid,
const xptiTypelib& typelib,
xptiWorkingSet& aWorkingSet)
: mIID(iid),
mName(nsnull),
mTypelib(typelib)
{
NS_INIT_REFCNT();
int len = PL_strlen(name);
char* ptr = (char*) XPT_MALLOC(aWorkingSet.GetStringArena(), len+2);
if(ptr)
{
mName = &ptr[1];
memcpy(mName, name, len);
// XXX These are redundant as long as the underlying arena continues
// to zero out all mallocs. But...
mName[-1] = mName[len] = 0;
}
}
xptiInterfaceInfo::~xptiInterfaceInfo()
{
if(HasInterfaceRecord())
delete mInterface;
}
PRBool
xptiInterfaceInfo::Resolve(xptiWorkingSet* aWorkingSet)
{
int resolvedState = GetResolveState();
if(resolvedState == FULLY_RESOLVED)
return PR_TRUE;
if(resolvedState == RESOLVE_FAILED)
return PR_FALSE;
xptiInterfaceInfoManager* mgr =
xptiInterfaceInfoManager::GetInterfaceInfoManager();
if(!mgr)
return PR_FALSE;
if(!aWorkingSet)
{
aWorkingSet = mgr->GetWorkingSet();
}
if(resolvedState == NOT_RESOLVED)
{
printf("~ partial resolve of %s\n", mName);
// Make a copy of mTypelib because the underlying memory will change!
xptiTypelib typelib = mTypelib;
// We expect our PartiallyResolve() to get called before this returns.
if(!mgr->LoadFile(typelib, aWorkingSet))
{
NS_RELEASE(mgr);
SetResolvedState(RESOLVE_FAILED);
return PR_FALSE;
}
// The state was changed by LoadFile to PARTIALLY_RESOLVED, so this
// ...falls through...
}
NS_IF_RELEASE(mgr);
NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!");
printf("+ final resolve of %s\n", mName);
// Finish out resolution by finding parent and Resolving it so
// we can set the info we get from it.
PRUint16 parent_index = mInterface->mDescriptor->parent_interface;
if(parent_index)
{
xptiInterfaceInfo* parent =
aWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
GetInfoAtNoAddRef(parent_index - 1);
if(!parent || !parent->EnsureResolved())
{
xptiTypelib aTypelib = mInterface->mTypelib;
delete mInterface;
mTypelib = aTypelib;
SetResolvedState(RESOLVE_FAILED);
return PR_FALSE;
}
NS_ADDREF(mInterface->mParent = parent);
mInterface->mMethodBaseIndex =
parent->mInterface->mMethodBaseIndex +
parent->mInterface->mDescriptor->num_methods;
mInterface->mConstantBaseIndex =
parent->mInterface->mConstantBaseIndex +
parent->mInterface->mDescriptor->num_constants;
}
SetResolvedState(FULLY_RESOLVED);
return PR_TRUE;
}
PRBool
xptiInterfaceInfo::PartiallyResolve(XPTInterfaceDescriptor* aDescriptor,
xptiWorkingSet* aWorkingSet)
{
NS_ASSERTION(GetResolveState() == NOT_RESOLVED, "bad state");
xptiInterfaceGuts* iface =
new xptiInterfaceGuts(aDescriptor, mTypelib, aWorkingSet);
if(!iface)
return PR_FALSE;
mInterface = iface;
SetResolvedState(PARTIALLY_RESOLVED);
return PR_TRUE;
}
/***************************************************************************/
NS_IMETHODIMP
xptiInterfaceInfo::GetName(char **name)
{
NS_PRECONDITION(name, "bad param");
if(!mName)
return NS_ERROR_UNEXPECTED;
char* ptr = *name = (char*) nsAllocator::Clone(mName, PL_strlen(mName)+1);
return ptr ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetIID(nsIID **iid)
{
NS_PRECONDITION(iid, "bad param");
nsIID* ptr = *iid = (nsIID*) nsAllocator::Clone(&mIID, sizeof(nsIID));
return ptr ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP
xptiInterfaceInfo::IsScriptable(PRBool* result)
{
NS_ASSERTION(result, "bad bad caller!");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
*result = XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags);
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetParent(nsIInterfaceInfo** parent)
{
NS_PRECONDITION(parent, "bad param");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
NS_IF_ADDREF(*parent = mInterface->mParent);
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetMethodCount(uint16* count)
{
NS_PRECONDITION(count, "bad param");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
*count = mInterface->mMethodBaseIndex +
mInterface->mDescriptor->num_methods;
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetConstantCount(uint16* count)
{
NS_PRECONDITION(count, "bad param");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
*count = mInterface->mConstantBaseIndex +
mInterface->mDescriptor->num_constants;
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
{
NS_PRECONDITION(info, "bad param");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(index < mInterface->mMethodBaseIndex)
return mInterface->mParent->GetMethodInfo(index, info);
if(index >= mInterface->mMethodBaseIndex +
mInterface->mDescriptor->num_methods)
{
NS_ASSERTION(0, "bad param");
*info = NULL;
return NS_ERROR_INVALID_ARG;
}
// else...
*info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
&mInterface->mDescriptor->
method_descriptors[index -
mInterface->mMethodBaseIndex]);
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetMethodInfoForName(const char* methodName, uint16 *index,
const nsXPTMethodInfo** result)
{
NS_PRECONDITION(methodName, "bad param");
NS_PRECONDITION(index, "bad param");
NS_PRECONDITION(result, "bad param");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
// This is a slow algorithm, but this is not expected to be called much.
for(uint16 i = mInterface->mMethodBaseIndex;
i < mInterface->mDescriptor->num_methods;
++i)
{
const nsXPTMethodInfo* info;
info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
&mInterface->mDescriptor->
method_descriptors[i -
mInterface->mMethodBaseIndex]);
*index = i;
*result = info;
return NS_OK;
}
if(mInterface->mParent)
return mInterface->mParent->GetMethodInfoForName(methodName, index, result);
else
return NS_ERROR_INVALID_ARG;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetConstant(uint16 index, const nsXPTConstant** constant)
{
NS_PRECONDITION(constant, "bad param");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(index < mInterface->mConstantBaseIndex)
return mInterface->mParent->GetConstant(index, constant);
if(index >= mInterface->mConstantBaseIndex +
mInterface->mDescriptor->num_constants)
{
NS_PRECONDITION(0, "bad param");
*constant = NULL;
return NS_ERROR_INVALID_ARG;
}
// else...
*constant =
NS_REINTERPRET_CAST(nsXPTConstant*,
&mInterface->mDescriptor->
const_descriptors[index -
mInterface->mConstantBaseIndex]);
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetInfoForParam(uint16 methodIndex,
const nsXPTParamInfo *param,
nsIInterfaceInfo** info)
{
NS_PRECONDITION(param, "bad pointer");
NS_PRECONDITION(info, "bad pointer");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mInterface->mMethodBaseIndex)
return mInterface->mParent->GetInfoForParam(methodIndex, param, info);
if(methodIndex >= mInterface->mMethodBaseIndex +
mInterface->mDescriptor->num_methods)
{
NS_PRECONDITION(0, "bad param");
*info = NULL;
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td = &param->type;
while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
td = &mInterface->mDescriptor->
additional_types[td->type.additional_type];
}
if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) {
NS_ASSERTION(0, "not an interface");
return NS_ERROR_INVALID_ARG;
}
nsIInterfaceInfo* theInfo =
mInterface->mWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
GetInfoAtNoAddRef(td->type.interface - 1);
NS_IF_ADDREF(*info = theInfo);
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetIIDForParam(uint16 methodIndex,
const nsXPTParamInfo* param, nsIID** iid)
{
NS_PRECONDITION(param, "bad pointer");
NS_PRECONDITION(iid, "bad pointer");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mInterface->mMethodBaseIndex)
return mInterface->mParent->GetIIDForParam(methodIndex, param, iid);
if(methodIndex >= mInterface->mMethodBaseIndex +
mInterface->mDescriptor->num_methods)
{
NS_PRECONDITION(0, "bad param");
*iid = NULL;
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td = &param->type;
while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
td = &mInterface->mDescriptor->
additional_types[td->type.additional_type];
}
if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) {
NS_ASSERTION(0, "not an interface");
return NS_ERROR_INVALID_ARG;
}
nsIInterfaceInfo* theInfo =
mInterface->mWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
GetInfoAtNoAddRef(td->type.interface - 1);
return theInfo->GetIID(iid);
}
// this is a private helper
NS_IMETHODIMP
xptiInterfaceInfo::GetTypeInArray(const nsXPTParamInfo* param,
uint16 dimension,
const XPTTypeDescriptor** type)
{
NS_ASSERTION(param, "bad state");
NS_ASSERTION(type, "bad state");
NS_ASSERTION(IsFullyResolved(), "bad state");
const XPTTypeDescriptor *td = &param->type;
const XPTTypeDescriptor *additional_types =
mInterface->mDescriptor->additional_types;
for (uint16 i = 0; i < dimension; i++) {
if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) {
NS_ASSERTION(0, "bad dimension");
return NS_ERROR_INVALID_ARG;
}
td = &additional_types[td->type.additional_type];
}
*type = td;
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetTypeForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
nsXPTType* type)
{
NS_PRECONDITION(param, "bad pointer");
NS_PRECONDITION(type, "bad pointer");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mInterface->mMethodBaseIndex)
return mInterface->mParent->GetTypeForParam(methodIndex, param,
dimension, type);
if(methodIndex >= mInterface->mMethodBaseIndex +
mInterface->mDescriptor->num_methods)
{
NS_ASSERTION(0, "bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td;
if(dimension) {
nsresult rv = GetTypeInArray(param, dimension, &td);
if(NS_FAILED(rv))
return rv;
}
else
td = &param->type;
*type = nsXPTType(td->prefix);
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetSizeIsArgNumberForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
uint8* argnum)
{
NS_PRECONDITION(param, "bad pointer");
NS_PRECONDITION(argnum, "bad pointer");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mInterface->mMethodBaseIndex)
return mInterface->mParent->
GetSizeIsArgNumberForParam(methodIndex, param,
dimension, argnum);
if(methodIndex >= mInterface->mMethodBaseIndex +
mInterface->mDescriptor->num_methods)
{
NS_ASSERTION(0, "bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td;
if(dimension) {
nsresult rv = GetTypeInArray(param, dimension, &td);
if(NS_FAILED(rv))
return rv;
}
else
td = &param->type;
// verify that this is a type that has size_is
switch (XPT_TDP_TAG(td->prefix)) {
case TD_ARRAY:
case TD_PSTRING_SIZE_IS:
case TD_PWSTRING_SIZE_IS:
break;
default:
NS_ASSERTION(0, "not a size_is");
return NS_ERROR_INVALID_ARG;
}
*argnum = td->argnum;
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetLengthIsArgNumberForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint16 dimension,
uint8* argnum)
{
NS_PRECONDITION(param, "bad pointer");
NS_PRECONDITION(argnum, "bad pointer");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mInterface->mMethodBaseIndex)
return mInterface->mParent->
GetLengthIsArgNumberForParam(methodIndex, param,
dimension, argnum);
if(methodIndex >= mInterface->mMethodBaseIndex +
mInterface->mDescriptor->num_methods)
{
NS_ASSERTION(0, "bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td;
if(dimension) {
nsresult rv = GetTypeInArray(param, dimension, &td);
if(NS_FAILED(rv)) {
return rv;
}
}
else
td = &param->type;
// verify that this is a type that has length_is
switch (XPT_TDP_TAG(td->prefix)) {
case TD_ARRAY:
case TD_PSTRING_SIZE_IS:
case TD_PWSTRING_SIZE_IS:
break;
default:
NS_ASSERTION(0, "not a length_is");
return NS_ERROR_INVALID_ARG;
}
*argnum = td->argnum2;
return NS_OK;
}
NS_IMETHODIMP
xptiInterfaceInfo::GetInterfaceIsArgNumberForParam(uint16 methodIndex,
const nsXPTParamInfo* param,
uint8* argnum)
{
NS_PRECONDITION(param, "bad pointer");
NS_PRECONDITION(argnum, "bad pointer");
if(!EnsureResolved())
return NS_ERROR_UNEXPECTED;
if(methodIndex < mInterface->mMethodBaseIndex)
return mInterface->mParent->
GetInterfaceIsArgNumberForParam(methodIndex, param,
argnum);
if(methodIndex >= mInterface->mMethodBaseIndex +
mInterface->mDescriptor->num_methods)
{
NS_ASSERTION(0, "bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td = &param->type;
while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
td = &mInterface->mDescriptor->
additional_types[td->type.additional_type];
}
if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) {
NS_ASSERTION(0, "not an iid_is");
return NS_ERROR_INVALID_ARG;
}
*argnum = td->argnum;
return NS_OK;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,567 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Implementation of xptiManifest. */
#include "xptiprivate.h"
static const char g_MainManifestFilename[] = "xpti.dat";
static const char g_TempManifestFilename[] = "xptitemp.dat";
static const char g_Disclaimer[] = "# Generated file. ** DO NOT EDIT! **";
static const char g_TOKEN_Files[] = "Files";
static const char g_TOKEN_ArchiveItems[] = "ArchiveItems";
static const char g_TOKEN_Interfaces[] = "Interfaces";
static const char g_TOKEN_Header[] = "Header";
static const char g_TOKEN_Version[] = "Version";
static const int g_VERSION_MAJOR = 1;
static const int g_VERSION_MINOR = 0;
// This is used to make PR_sscanf for strings safer. We refuse to even
// attempt to do a PR_sscanf from a line longer than this.
static const int g_MAX_LINE_LEN = 256;
/***************************************************************************/
static PRBool
WriteFormatted(FILE* file, const char* fmt, ... )
{
va_list ap;
va_start(ap, fmt);
char* buf = PR_vsmprintf(fmt, ap);
va_end(ap);
if(!buf)
return PR_FALSE;
size_t len = PL_strlen(buf);
PRBool result = (len == fwrite(buf, 1, len, file));
PR_smprintf_free(buf);
return result;
}
static PR_CALLBACK PRIntn
xpti_InterfaceWriter(PLHashEntry *he, PRIntn i, void *arg)
{
xptiInterfaceInfo* info = (xptiInterfaceInfo*) he->value;
FILE* file = (FILE*) arg;
if(!info->IsValid())
return HT_ENUMERATE_STOP;
char* iidStr = info->GetTheIID()->ToString();
if(!iidStr)
return HT_ENUMERATE_STOP;
const xptiTypelib& typelib = info->GetTypelibRecord();
PRBool success = WriteFormatted(file, "%d,%s,%s,%d,%d\n",
(int) i,
info->GetTheName(),
iidStr,
(int) typelib.GetFileIndex(),
(int) (typelib.IsZip() ?
typelib.GetZipItemIndex() : -1));
nsCRT::free(iidStr);
return success ? HT_ENUMERATE_NEXT : HT_ENUMERATE_STOP;
}
// static
PRBool xptiManifest::Write(xptiInterfaceInfoManager* aMgr,
xptiWorkingSet& aWorkingSet)
{
PRBool succeeded = PR_FALSE;
FILE* file = nsnull;
PRUint32 i;
PRIntn interfaceCount = 0;
nsCOMPtr<nsILocalFile> tempFile;
if(!aMgr->GetComponentsDir(getter_AddRefs(tempFile)) || !tempFile)
return PR_FALSE;
if(NS_FAILED(tempFile->Append(g_TempManifestFilename)))
return PR_FALSE;
// exist via "goto out;" from here on...
if(NS_FAILED(tempFile->OpenANSIFileDesc("w", &file)) || !file)
{
goto out;
}
// write file header comments
if(!WriteFormatted(file, "%s\n", g_Disclaimer))
goto out;
// write the [Header] block and version number.
if(!WriteFormatted(file, "\n[%s,%d]\n", g_TOKEN_Header, 1))
goto out;
if(!WriteFormatted(file, "%d,%s,%d,%d\n",
0, g_TOKEN_Version, g_VERSION_MAJOR, g_VERSION_MINOR))
goto out;
// write Files list
if(!WriteFormatted(file, "\n[%s,%d]\n",
g_TOKEN_Files,
(int) aWorkingSet.GetFileCount()))
goto out;
for(i = 0; i < aWorkingSet.GetFileCount(); i++)
{
if(!WriteFormatted(file, "%d,%s,%lld,%lld\n",
(int) i,
aWorkingSet.GetFileAt(i).GetName(),
PRInt64(aWorkingSet.GetFileAt(i).GetSize()),
PRInt64(aWorkingSet.GetFileAt(i).GetDate())))
goto out;
}
// write ArchiveItems list
if(!WriteFormatted(file, "\n[%s,%d]\n",
g_TOKEN_ArchiveItems,
(int) aWorkingSet.GetZipItemCount()))
goto out;
for(i = 0; i < aWorkingSet.GetZipItemCount(); i++)
{
if(!WriteFormatted(file, "%d,%s\n",
(int) i,
aWorkingSet.GetZipItemAt(i).GetName()))
goto out;
}
// write the Interfaces list
interfaceCount = aWorkingSet.mNameTable->nentries;
if(!WriteFormatted(file, "\n[%s,%d]\n",
g_TOKEN_Interfaces,
(int) interfaceCount))
goto out;
if(interfaceCount !=
PL_HashTableEnumerateEntries(aWorkingSet.mNameTable,
xpti_InterfaceWriter, file))
goto out;
if(0 == fclose(file))
{
succeeded = PR_TRUE;
}
file = nsnull;
out:
if(file)
fclose(file);
if(succeeded)
{
// delete the old file and rename this
nsCOMPtr<nsILocalFile> mainFile;
if(!aMgr->GetComponentsDir(getter_AddRefs(mainFile)) || !mainFile)
return PR_FALSE;
if(NS_FAILED(mainFile->Append(g_MainManifestFilename)))
return PR_FALSE;
PRBool exists;
if(NS_FAILED(mainFile->Exists(&exists)))
return PR_FALSE;
if(exists && NS_FAILED(mainFile->Delete(PR_FALSE)))
return PR_FALSE;
// XXX Would prefer MoveTo with a 'null' newdir, the but nsILocalFile
// implementation are broken.
// http://bugzilla.mozilla.org/show_bug.cgi?id=33098
nsCOMPtr<nsILocalFile> dir;
if(!aMgr->GetComponentsDir(getter_AddRefs(dir)) || !dir)
return PR_FALSE;
if(NS_FAILED(tempFile->CopyTo(dir, g_MainManifestFilename)))
return PR_FALSE;
}
return succeeded;
}
static char*
ReadManifestIntoMemory(xptiInterfaceInfoManager* aMgr,
PRUint32* pLength)
{
FILE* file = nsnull;
PRUint32 flen;
PRInt64 fileSize;
char* whole = nsnull;
nsCOMPtr<nsILocalFile> aFile;
if(!aMgr->GetComponentsDir(getter_AddRefs(aFile)) || !aFile)
return nsnull;
if(NS_FAILED(aFile->Append(g_MainManifestFilename)))
return nsnull;
if(NS_FAILED(aFile->GetFileSize(&fileSize)) || !(flen = nsInt64(fileSize)))
return nsnull;
whole = new char[flen];
if (!whole)
return nsnull;
// all exits from on here should be via 'goto out'
if(NS_FAILED(aFile->OpenANSIFileDesc("rb", &file)) || !file)
goto out;
if(flen > fread(whole, 1, flen, file))
goto out;
out:
if(file)
fclose(file);
*pLength = flen;
return whole;
}
/***************************************************/
class ManifestLineReader
{
public:
ManifestLineReader() : mBase(nsnull) {}
~ManifestLineReader() {}
void Init(char* base, PRUint32 flen)
{mBase = mCur = mNext = base;
mLength = 0;
mLimit = base + flen;}
PRBool NextLine();
char* LinePtr() {return mCur;}
PRUint32 LineLength() {return mLength;}
private:
char* mCur;
PRUint32 mLength;
char* mNext;
char* mBase;
char* mLimit;
};
PRBool
ManifestLineReader::NextLine()
{
if(mNext == mLimit)
return PR_FALSE;
mCur = mNext;
mLength = 0;
while(mNext < mLimit)
{
char c = *(mNext);
if(c == '\n' || c == '\r')
{
do
{
*(mNext++) = '\0';
char c = *(mNext);
if(c != '\n' && c != '\r')
return PR_TRUE;
} while(mNext < mLimit);
return PR_TRUE;
}
++mNext;
++mLength;
}
return PR_FALSE;
}
/***************************************************/
static
PRBool ReadSectionHeader(ManifestLineReader& reader,
const char *token, int minCount,
char* name, int* count)
{
while(1)
{
if(!reader.NextLine())
break;
if(*reader.LinePtr() == '[')
{
if(reader.LineLength() > g_MAX_LINE_LEN)
break;
if(2 == PR_sscanf(reader.LinePtr(), "[%[^','],%d]",
name, count) &&
0 == PL_strcmp(name, token) &&
*count >= minCount)
{
return PR_TRUE;
}
break;
}
}
return PR_FALSE;
}
// static
PRBool xptiManifest::Read(xptiInterfaceInfoManager* aMgr,
xptiWorkingSet& aWorkingSet)
{
char* whole = nsnull;
char* name = nsnull;
char* iidStr = nsnull;
PRBool succeeded = PR_FALSE;
PRUint32 flen;
ManifestLineReader reader;
int headerCount = 0;
int fileCount = 0;
int zipItemCount = -1;
int interfaceCount = 0;
int i;
int index;
int major;
int minor;
PRInt64 size;
PRInt64 date;
whole = ReadManifestIntoMemory(aMgr, &flen);
if(!whole)
return PR_FALSE;
reader.Init(whole, flen);
// all exits from on here should be via 'goto out'
// We are going to scanf into these buffers, let's make them big.
name = new char[g_MAX_LINE_LEN];
if(!name)
goto out;
iidStr = new char[g_MAX_LINE_LEN];
if(!iidStr)
goto out;
// Look for "Header" section
// This version accepts only version 1,0. We also freak if the header
// has more than one entry. The rationale is that we want to force an
// autoreg if the xpti.dat file was written by *any* other version of
// the software. Future versions may wish to support updating older
// manifests in some interesting way.
if(!ReadSectionHeader(reader, g_TOKEN_Header, 1, name, &headerCount))
goto out;
// get the version
if(headerCount != 1)
goto out;
if(!reader.NextLine())
goto out;
if(reader.LineLength() > g_MAX_LINE_LEN)
goto out;
if(4 != PR_sscanf(reader.LinePtr(), "%d,%[^','],%d,%d",
&index, name, &major, &minor) ||
0 != index ||
0 != PL_strcmp(name, g_TOKEN_Version) ||
major != g_VERSION_MAJOR ||
minor != g_VERSION_MINOR)
{
goto out;
}
// Look for "Files" section
if(!ReadSectionHeader(reader, g_TOKEN_Files, 1, name, &fileCount))
goto out;
// Alloc room in the WorkingSet for the filearray.
if(!aWorkingSet.NewFileArray(fileCount))
goto out;
// Read the file records
for(i = 0; i < fileCount; ++i)
{
if(!reader.NextLine())
goto out;
if(reader.LineLength() > g_MAX_LINE_LEN)
goto out;
if(4 != PR_sscanf(reader.LinePtr(), "%d,%[^','],%lld,%lld",
&index, name, &size, &date) ||
i != index ||
!*name)
{
goto out;
}
// Append a new file record to the array.
aWorkingSet.AppendFile(
xptiFile(nsInt64(size), nsInt64(date), name, &aWorkingSet));
}
// Look for "ZipItems" section
if(!ReadSectionHeader(reader, g_TOKEN_ArchiveItems, 0, name, &zipItemCount))
goto out;
// Alloc room in the WorkingSet for the zipItemarray.
if(zipItemCount)
if(!aWorkingSet.NewZipItemArray(zipItemCount))
goto out;
// Read the zipItem records
for(i = 0; i < zipItemCount; ++i)
{
if(!reader.NextLine())
goto out;
if(reader.LineLength() > g_MAX_LINE_LEN)
goto out;
if(2 != PR_sscanf(reader.LinePtr(), "%d,%[^',']",
&index, name) ||
i != index ||
!*name)
{
goto out;
}
// Append a new zipItem record to the array.
aWorkingSet.AppendZipItem(xptiZipItem(name, &aWorkingSet));
}
// Look for "Interfaces" section
if(!ReadSectionHeader(reader, g_TOKEN_Interfaces, 1, name, &interfaceCount))
goto out;
// Read the interface records
for(i = 0; i < interfaceCount; ++i)
{
int fileIndex;
int zipItemIndex;
nsIID iid;
xptiInterfaceInfo* info;
xptiTypelib typelibRecord;
if(!reader.NextLine())
goto out;
if(reader.LineLength() > g_MAX_LINE_LEN)
goto out;
if(5 != PR_sscanf(reader.LinePtr(), "%d,%[^','],%[^','],%d,%d",
&index, name, iidStr, &fileIndex, &zipItemIndex) ||
i != index ||
!*name ||
!*iidStr ||
!iid.Parse(iidStr) ||
fileIndex < 0 ||
fileIndex >= fileCount ||
(zipItemIndex != -1 && zipItemIndex >= zipItemCount))
{
goto out;
}
// Build an InterfaceInfo and hook it in.
if(zipItemIndex == -1)
typelibRecord.Init(fileIndex);
else
typelibRecord.Init(fileIndex, zipItemIndex);
info = new xptiInterfaceInfo(name, iid, typelibRecord, aWorkingSet);
if(!info)
{
goto out;
}
NS_ADDREF(info);
if(!info->IsValid())
{
// XXX bad!
NS_RELEASE(info);
goto out;
}
// The name table now owns the reference we AddRef'd above
PL_HashTableAdd(aWorkingSet.mNameTable, info->GetTheName(), info);
PL_HashTableAdd(aWorkingSet.mIIDTable, info->GetTheIID(), info);
}
// success!
succeeded = PR_TRUE;
out:
if(whole)
delete [] whole;
if(name)
delete [] name;
if(iidStr)
delete [] iidStr;
if(!succeeded)
{
// Cleanup the WorkingSet on failure.
aWorkingSet.InvalidateInterfaceInfos();
aWorkingSet.ClearHashTables();
aWorkingSet.ClearFiles();
}
return succeeded;
}

View File

@@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Implementation of xptiTypelibGuts. */
#include "xptiprivate.h"
xptiTypelibGuts::xptiTypelibGuts(XPTHeader* aHeader)
: mHeader(aHeader),
mInfoArray(nsnull)
{
NS_ASSERTION(mHeader, "bad param");
if(mHeader->num_interfaces)
{
mInfoArray = new xptiInterfaceInfo*[GetInfoCount()];
if(mInfoArray)
memset(mInfoArray, 0, sizeof(xptiInterfaceInfo*) * GetInfoCount());
else
mHeader = nsnull;
}
}
xptiTypelibGuts::~xptiTypelibGuts()
{
if(mHeader && mInfoArray)
for(PRUint16 i = 0; i < GetInfoCount(); ++i)
NS_IF_RELEASE(mInfoArray[i]);
delete [] mInfoArray;
}
xptiTypelibGuts*
xptiTypelibGuts::Clone()
{
xptiTypelibGuts* clone = new xptiTypelibGuts(mHeader);
if(clone && clone->IsValid())
for(PRUint16 i = 0; i < GetInfoCount(); ++i)
clone->SetInfoAt(i, GetInfoAtNoAddRef(i));
return clone;
}
nsresult
xptiTypelibGuts::GetInfoAt(PRUint16 i, xptiInterfaceInfo** ptr)
{
NS_ASSERTION(mHeader,"bad state!");
NS_ASSERTION(mInfoArray,"bad state!");
NS_ASSERTION(i < GetInfoCount(),"bad param!");
NS_ASSERTION(ptr,"bad param!");
NS_IF_ADDREF(*ptr = mInfoArray[i]);
return NS_OK;
}
xptiInterfaceInfo*
xptiTypelibGuts::GetInfoAtNoAddRef(PRUint16 i)
{
NS_ASSERTION(mHeader,"bad state!");
NS_ASSERTION(mInfoArray,"bad state!");
NS_ASSERTION(i < GetInfoCount(),"bad param!");
return mInfoArray[i];
}
nsresult
xptiTypelibGuts::SetInfoAt(PRUint16 i, xptiInterfaceInfo* ptr)
{
NS_ASSERTION(mHeader,"bad state!");
NS_ASSERTION(mInfoArray,"bad state!");
NS_ASSERTION(i < GetInfoCount(),"bad param!");
NS_IF_ADDREF(ptr);
NS_IF_RELEASE(mInfoArray[i]);
mInfoArray[i] = ptr;
return NS_OK;
}

View File

@@ -0,0 +1,244 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Implementation of xptiWorkingSet. */
#include "xptiprivate.h"
#define XPTI_STRING_ARENA_BLOCK_SIZE (1024 * 1)
#define XPTI_STRUCT_ARENA_BLOCK_SIZE (1024 * 1)
#define XPTI_HASHTABLE_SIZE 128
static PR_CALLBACK PLHashNumber
xpti_HashIID(const void *key)
{
return ((nsID*)key)->m0;
}
static PR_CALLBACK PRIntn
xpti_CompareIIDs(const void *v1, const void *v2)
{
return (PRIntn) ((const nsID*)v1)->Equals(*((const nsID*)v2));
}
xptiWorkingSet::xptiWorkingSet()
: mFileCount(0),
mMaxFileCount(0),
mFileArray(nsnull),
mZipItemCount(0),
mMaxZipItemCount(0),
mZipItemArray(nsnull),
mStringArena(XPT_NewArena(XPTI_STRING_ARENA_BLOCK_SIZE, sizeof(char),
"xptiWorkingSet strings")),
mStructArena(XPT_NewArena(XPTI_STRUCT_ARENA_BLOCK_SIZE, sizeof(double),
"xptiWorkingSet structs")),
mNameTable(PL_NewHashTable(XPTI_HASHTABLE_SIZE, PL_HashString,
PL_CompareStrings, PL_CompareValues,
nsnull, nsnull)),
mIIDTable(PL_NewHashTable(XPTI_HASHTABLE_SIZE, xpti_HashIID,
xpti_CompareIIDs, PL_CompareValues,
nsnull, nsnull)),
mMergeOffsetMap(nsnull)
{
// do nothing else...
}
PRBool
xptiWorkingSet::IsValid() const
{
return (mFileCount == 0 || mFileArray) &&
(mZipItemCount == 0 || mZipItemArray) &&
mStringArena &&
mStructArena &&
mNameTable &&
mIIDTable;
}
static PR_CALLBACK PRIntn
xpti_Remover(PLHashEntry *he, PRIntn i, void *arg)
{
return HT_ENUMERATE_REMOVE;
}
static PR_CALLBACK PRIntn
xpti_ReleaseAndRemover(PLHashEntry *he, PRIntn i, void *arg)
{
nsIInterfaceInfo* ii = (nsIInterfaceInfo*) he->value;
NS_RELEASE(ii);
return HT_ENUMERATE_REMOVE;
}
static PR_CALLBACK PRIntn
xpti_Invalidator(PLHashEntry *he, PRIntn i, void *arg)
{
((xptiInterfaceInfo*)he->value)->Invalidate();
return HT_ENUMERATE_NEXT;
}
void
xptiWorkingSet::InvalidateInterfaceInfos()
{
if(mNameTable)
PL_HashTableEnumerateEntries(mNameTable, xpti_Invalidator, nsnull);
}
void
xptiWorkingSet::ClearHashTables()
{
if(mNameTable)
PL_HashTableEnumerateEntries(mNameTable, xpti_Remover, nsnull);
if(mIIDTable)
PL_HashTableEnumerateEntries(mIIDTable, xpti_ReleaseAndRemover, nsnull);
}
void
xptiWorkingSet::ClearFiles()
{
if(mFileArray)
delete [] mFileArray;
mFileArray = nsnull;
mMaxFileCount = 0;
mFileCount = 0;
}
void
xptiWorkingSet::ClearZipItems()
{
if(mZipItemArray)
delete [] mZipItemArray;
mZipItemArray = nsnull;
mMaxZipItemCount = 0;
mZipItemCount = 0;
}
xptiWorkingSet::~xptiWorkingSet()
{
ClearFiles();
ClearZipItems();
ClearHashTables();
if(mNameTable)
PL_HashTableDestroy(mNameTable);
if(mIIDTable)
PL_HashTableDestroy(mIIDTable);
if(mFileArray)
delete [] mFileArray;
if(mZipItemArray)
delete [] mZipItemArray;
// Destroy arenas last in case they are referenced in other members' dtors.
if(mStringArena)
{
#ifdef DEBUG
XPT_DumpStats(mStringArena);
#endif
XPT_DestroyArena(mStringArena);
}
if(mStructArena)
{
#ifdef DEBUG
XPT_DumpStats(mStructArena);
#endif
XPT_DestroyArena(mStructArena);
}
}
PRBool
xptiWorkingSet::NewFileArray(PRUint32 count)
{
if(mFileArray)
delete [] mFileArray;
mFileCount = 0;
mFileArray = new xptiFile[count];
if(!mFileArray)
{
mMaxFileCount = 0;
return PR_FALSE;
}
mMaxFileCount = count;
return PR_TRUE;
}
PRBool
xptiWorkingSet::ExtendFileArray(PRUint32 count)
{
if(mFileArray && count < mMaxFileCount)
return PR_TRUE;
xptiFile* newArray = new xptiFile[count];
if(!newArray)
return PR_FALSE;
if(mFileArray)
{
for(PRUint32 i = 0; i < mFileCount; ++i)
newArray[i] = mFileArray[i];
delete [] mFileArray;
}
mFileArray = newArray;
mMaxFileCount = count;
return PR_TRUE;
}
PRBool
xptiWorkingSet::NewZipItemArray(PRUint32 count)
{
if(mZipItemArray)
delete [] mZipItemArray;
mZipItemCount = 0;
mZipItemArray = new xptiZipItem[count];
if(!mZipItemArray)
{
mMaxZipItemCount = 0;
return PR_FALSE;
}
mMaxZipItemCount = count;
return PR_TRUE;
}
PRBool
xptiWorkingSet::ExtendZipItemArray(PRUint32 count)
{
if(mZipItemArray && count < mMaxZipItemCount)
return PR_TRUE;
xptiZipItem* newArray = new xptiZipItem[count];
if(!newArray)
return PR_FALSE;
if(mZipItemArray)
{
for(PRUint32 i = 0; i < mZipItemCount; ++i)
newArray[i] = mZipItemArray[i];
delete [] mZipItemArray;
}
mZipItemArray = newArray;
mMaxZipItemCount = count;
return PR_TRUE;
}

View File

@@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Implementation of xptiZipItem. */
#include "xptiprivate.h"
xptiZipItem::xptiZipItem()
: mName(nsnull),
mGuts(nsnull)
{
// empty
}
xptiZipItem::xptiZipItem(const char* aName,
xptiWorkingSet* aWorkingSet,
XPTHeader* aHeader /*= nsnull */)
: mName(aName),
mGuts(nsnull)
{
NS_ASSERTION(aWorkingSet,"bad param");
mName = XPT_STRDUP(aWorkingSet->GetStringArena(), aName);
if(aHeader)
SetHeader(aHeader);
}
xptiZipItem::xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet,
PRBool cloneGuts)
: mName(nsnull),
mGuts(nsnull)
{
NS_ASSERTION(aWorkingSet,"bad param");
mName = XPT_STRDUP(aWorkingSet->GetStringArena(), r.mName);
if(cloneGuts && r.mGuts)
mGuts = r.mGuts->Clone();
}
xptiZipItem::~xptiZipItem()
{
if(mGuts)
delete mGuts;
}
PRBool
xptiZipItem::SetHeader(XPTHeader* aHeader)
{
NS_ASSERTION(!mGuts,"bad state");
NS_ASSERTION(aHeader,"bad param");
mGuts = new xptiTypelibGuts(aHeader);
if(mGuts && !mGuts->IsValid())
{
delete mGuts;
mGuts = nsnull;
}
return mGuts != nsnull;
}

View File

@@ -0,0 +1,536 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* 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 "nsIServiceManager.h"
#include "nsIFile.h"
#include "nsILocalFile.h"
#include "nsSpecialSystemDirectory.h"
#include "nsISupportsArray.h"
#include "nsInt64.h"
#include "nsQuickSort.h"
#include "nsIZipReader.h"
#include "nsIInputStream.h"
#include "plstr.h"
#include "prprf.h"
#include <stdio.h>
#include <stdarg.h>
/***************************************************************************/
class xptiFile;
class xptiInterfaceInfo;
class xptiInterfaceInfoManager;
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;
};
/***************************************************************************/
class xptiTypelibGuts
{
public:
xptiTypelibGuts(); // not implemented
xptiTypelibGuts(XPTHeader* aHeader);
~xptiTypelibGuts();
PRBool IsValid() const {return mHeader != nsnull;}
XPTHeader* GetHeader() {return mHeader;}
PRUint16 GetInfoCount() const {return mHeader->num_interfaces;}
nsresult SetInfoAt(PRUint16 i, xptiInterfaceInfo* ptr);
nsresult GetInfoAt(PRUint16 i, xptiInterfaceInfo** ptr);
xptiInterfaceInfo* GetInfoAtNoAddRef(PRUint16 i);
xptiTypelibGuts* Clone();
private:
XPTHeader* mHeader; // hold pointer into arena
xptiInterfaceInfo** mInfoArray;
};
/***************************************************************************/
class xptiFile
{
public:
const nsInt64& GetSize() const {return mSize;}
const nsInt64& GetDate() const {return mDate;}
const char* GetName() const {return mName;}
xptiTypelibGuts* GetGuts() {return mGuts;}
xptiFile();
xptiFile(const nsInt64& aSize,
const nsInt64& aDate,
const char* aName,
xptiWorkingSet* aWorkingSet,
XPTHeader* aHeader = nsnull);
xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet,
PRBool cloneGuts);
~xptiFile();
PRBool SetHeader(XPTHeader* aHeader);
PRBool Equals(const xptiFile& r) const
{
return 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)
{
mSize = r.mSize;
mDate = r.mDate;
mName = r.mName;
if(mGuts)
delete mGuts;
if(r.mGuts)
mGuts = r.mGuts->Clone();
else
mGuts = nsnull;
}
private:
nsInt64 mSize;
nsInt64 mDate;
const char* mName; // hold pointer into arena from initializer
xptiTypelibGuts* mGuts; // new/delete
};
/***************************************************************************/
class xptiZipItem
{
public:
const char* GetName() const {return mName;}
xptiTypelibGuts* GetGuts() {return mGuts;}
xptiZipItem();
xptiZipItem(const char* aName,
xptiWorkingSet* aWorkingSet,
XPTHeader* aHeader = nsnull);
xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet,
PRBool cloneGuts);
~xptiZipItem();
PRBool SetHeader(XPTHeader* aHeader);
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)
{
mName = r.mName;
if(mGuts)
delete mGuts;
if(r.mGuts)
mGuts = r.mGuts->Clone();
else
mGuts = nsnull;
}
private:
const char* mName; // hold pointer into arena from initializer
xptiTypelibGuts* mGuts; // new/delete
};
/***************************************************************************/
class xptiWorkingSet
{
public:
xptiWorkingSet();
~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();
}
// FileArray stuff...
PRUint32 GetFileCount() const {return mFileCount;}
PRUint32 GetFileFreeSpace()
{return mFileArray ? mMaxFileCount - mFileCount : 0;}
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;}
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);
// 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;
public:
// XXX make these private with accessors
PLHashTable* mNameTable;
PLHashTable* mIIDTable;
PRUint32* mMergeOffsetMap; // always in an arena
};
/***************************************************************************/
// XXX could move this class to xptiInterfaceInfo.cpp.
class xptiInterfaceGuts
{
public:
uint16 mMethodBaseIndex;
uint16 mConstantBaseIndex;
nsIInterfaceInfo* mParent;
XPTInterfaceDescriptor* mDescriptor;
xptiTypelib mTypelib;
xptiWorkingSet* mWorkingSet;
xptiInterfaceGuts(XPTInterfaceDescriptor* aDescriptor,
const xptiTypelib& aTypelib,
xptiWorkingSet* aWorkingSet)
: mMethodBaseIndex(0),
mConstantBaseIndex(0),
mParent(nsnull),
mDescriptor(aDescriptor),
mTypelib(aTypelib),
mWorkingSet(aWorkingSet) {}
~xptiInterfaceGuts() {NS_IF_RELEASE(mParent);}
};
/***************************************************************************/
class xptiInterfaceInfo : public nsIInterfaceInfo
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIINTERFACEINFO
public:
xptiInterfaceInfo(); // not implemented
xptiInterfaceInfo(const char* name,
const nsID& iid,
const xptiTypelib& typelib,
xptiWorkingSet& aWorkingSet);
virtual ~xptiInterfaceInfo();
enum {
NOT_RESOLVED = 0,
PARTIALLY_RESOLVED = 1,
FULLY_RESOLVED = 2,
RESOLVE_FAILED = 3
};
PRBool IsValid() const
{return mName != nsnull;}
char GetResolveState() const
{return IsValid() ? mName[-1] : (char) RESOLVE_FAILED;}
PRBool IsFullyResolved() const
{return GetResolveState() == (char) 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;}
const nsID* GetTheIID() const {return &mIID;}
const char* GetTheName() const {return mName;}
PRBool PartiallyResolve(XPTInterfaceDescriptor* aDescriptor,
xptiWorkingSet* aWorkingSet);
void Invalidate()
{
if(IsValid())
{
xptiTypelib typelib = GetTypelibRecord();
mTypelib = typelib;
mName = nsnull;
}
}
private:
void SetResolvedState(int state)
{NS_ASSERTION(IsValid(),"bad state"); mName[-1] = (char) state;}
PRBool Resolve(xptiWorkingSet* aWorkingSet = nsnull);
PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
{return IsFullyResolved() ? PR_TRUE : Resolve(aWorkingSet);}
NS_IMETHOD GetTypeInArray(const nsXPTParamInfo* param,
uint16 dimension,
const XPTTypeDescriptor** type);
private:
nsID mIID;
char* mName; // This is in arena (not free'd) and mName[-1] is a flag.
union {
xptiTypelib mTypelib; // Valid only until resolved.
xptiInterfaceGuts* mInterface; // Valid only after resolved.
};
};
/***************************************************************************/
class xptiManifest
{
public:
static PRBool Read(xptiInterfaceInfoManager* aMgr,
xptiWorkingSet& aWorkingSet);
static PRBool Write(xptiInterfaceInfoManager* aMgr,
xptiWorkingSet& aWorkingSet);
xptiManifest(); // no implementation
};
/***************************************************************************/
class xptiInterfaceInfoManager : public nsIInterfaceInfoManager
{
NS_DECL_ISUPPORTS
NS_DECL_NSIINTERFACEINFOMANAGER
public:
virtual ~xptiInterfaceInfoManager();
static xptiInterfaceInfoManager* GetInterfaceInfoManager();
static void FreeInterfaceInfoManager();
xptiWorkingSet* GetWorkingSet() {return &mWorkingSet;}
PRBool LoadFile(const xptiTypelib& aTypelibRecord,
xptiWorkingSet* aWorkingSet = nsnull);
PRBool GetComponentsDir(nsILocalFile** aDir);
private:
xptiInterfaceInfoManager();
enum AutoRegMode {
NO_FILES_CHANGED = 0,
MAYBE_ONLY_ADDITIONS,
FULL_VALIDATION_REQUIRED
};
PRBool BuildFileList(nsISupportsArray** aFileList);
PRBool PopulateWorkingSetFromManifest(xptiWorkingSet& aWorkingSet);
PRBool WriteManifest(xptiWorkingSet& aWorkingSet);
XPTHeader* ReadXPTFile(nsILocalFile* aFile, xptiWorkingSet& aWorkingSet);
XPTHeader* ReadXPTFileFromZip(nsILocalFile* file,
const char* itemName,
xptiWorkingSet& aWorkingSet);
XPTHeader* ReadXPTFileFromOpenZip(nsIZipReader * zip,
nsIZipEntry* entry,
const char* itemName,
xptiWorkingSet& aWorkingSet);
AutoRegMode DetermineAutoRegStrategy(nsISupportsArray* aFileList,
xptiWorkingSet& aWorkingSet);
PRBool AttemptAddOnlyFromFileList(nsISupportsArray* aFileList,
xptiWorkingSet& aWorkingSet,
AutoRegMode* pmode);
PRBool DoFullValidationMergeFromFileList(nsISupportsArray* aFileList,
xptiWorkingSet& aWorkingSet);
PRBool VerifyAndAddInterfaceIfNew(xptiWorkingSet& aWorkingSet,
XPTInterfaceDirectoryEntry* iface,
const xptiTypelib& typelibRecord,
xptiInterfaceInfo** infoAdded);
PRBool MergeWorkingSets(xptiWorkingSet& aDestWorkingSet,
xptiWorkingSet& aSrcWorkingSet);
PRBool DEBUG_DumpFileList(nsISupportsArray* aFileList);
PRBool DEBUG_DumpFileListInWorkingSet(xptiWorkingSet& aWorkingSet);
private:
xptiWorkingSet mWorkingSet;
};
#if 0
#endif
#endif /* xptiprivate_h___ */

View File

@@ -0,0 +1,113 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* Simple arena allocator for xpt (which avoids using NSPR).
*/
#ifndef __xpt_arena_h__
#define __xpt_arena_h__
#include "prtypes.h"
#include <assert.h>
#include <stdlib.h>
/*
* The linkage of XPT API functions differs depending on whether the file is
* used within the XPT library or not. Any source file within the XPT
* library should define EXPORT_XPT_API whereas any client of the library
* should not.
*/
#ifdef EXPORT_XPT_API
#define XPT_PUBLIC_API(t) PR_IMPLEMENT(t)
#define XPT_PUBLIC_DATA(t) PR_IMPLEMENT_DATA(t)
#else
#ifdef _WIN32
# define XPT_PUBLIC_API(t) _declspec(dllimport) t
# define XPT_PUBLIC_DATA(t) _declspec(dllimport) t
#else
# define XPT_PUBLIC_API(t) PR_IMPLEMENT(t)
# define XPT_PUBLIC_DATA(t) t
#endif
#endif
#define XPT_FRIEND_API(t) XPT_PUBLIC_API(t)
#define XPT_FRIEND_DATA(t) XPT_PUBLIC_DATA(t)
PR_BEGIN_EXTERN_C
/*
* Simple Arena support. Use with caution!
*/
typedef struct XPTArena XPTArena;
XPT_PUBLIC_API(XPTArena *)
XPT_NewArena(PRUint32 block_size, size_t alignment, const char* name);
XPT_PUBLIC_API(void)
XPT_DestroyArena(XPTArena *arena);
XPT_PUBLIC_API(void)
XPT_DumpStats(XPTArena *arena);
XPT_PUBLIC_API(void *)
XPT_ArenaMalloc(XPTArena *arena, size_t size);
XPT_PUBLIC_API(char *)
XPT_ArenaStrDup(XPTArena *arena, const char * s);
XPT_PUBLIC_API(void)
XPT_NotifyDoneLoading(XPTArena *arena);
XPT_PUBLIC_API(void)
XPT_ArenaFree(XPTArena *arena, void* block);
/* --------------------------------------------------------- */
#define XPT_MALLOC(_arena, _bytes) \
XPT_ArenaMalloc((_arena), (_bytes))
#ifdef DEBUG
#define XPT_FREE(_arena, _ptr) \
XPT_ArenaFree((_arena), (_ptr))
#else
#define XPT_FREE(_arena, _ptr) \
((void)0)
#endif
#define XPT_STRDUP(_arena, _s) \
XPT_ArenaStrDup((_arena), (_s))
#define XPT_CALLOC(_arena, _size) XPT_MALLOC((_arena), (_size))
#define XPT_NEW(_arena, _struct) ((_struct *) XPT_MALLOC((_arena), sizeof(_struct)))
#define XPT_NEWZAP(_arena, _struct) XPT_NEW((_arena), _struct)
#define XPT_DELETE(_arena, _ptr) do{XPT_FREE((_arena), (_ptr)); ((_ptr)) = NULL;}while(0)
#define XPT_FREEIF(_arena, _ptr) do{if ((_ptr)) XPT_FREE((_arena), (_ptr));}while(0)
/* --------------------------------------------------------- */
#define XPT_ASSERT(_expr) assert(_expr)
PR_END_EXTERN_C
#endif /* __xpt_arena_h__ */

View File

@@ -0,0 +1,315 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Quick arena hack for xpt. */
/* XXX This exists because we don't want to drag in NSPR. It *seemed*
* to make more sense to write a quick and dirty arena than to clone
* plarena (like js/src did). This is not optimal, but it works.
* Half of the code here is instrumentation.
*/
#include "xpt_arena.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
/*************************/
/* logging stats support */
#ifdef DEBUG_jband
#define XPT_ARENA_LOGGING 1
#endif
#ifdef XPT_ARENA_LOGGING
#define LOG_MALLOC(_a, _req, _used) \
do{ \
XPT_ASSERT((_a)); \
++(_a)->LOG_MallocCallCount; \
(_a)->LOG_MallocTotalBytesRequested += (_req); \
(_a)->LOG_MallocTotalBytesUsed += (_used); \
} while(0)
#define LOG_REAL_MALLOC(_a, _size) \
do{ \
XPT_ASSERT((_a)); \
++(_a)->LOG_RealMallocCallCount; \
(_a)->LOG_RealMallocTotalBytesRequested += (_size); \
} while(0)
#define LOG_FREE(_a) \
do{ \
XPT_ASSERT((_a)); \
++(_a)->LOG_FreeCallCount; \
} while(0)
#define LOG_DONE_LOADING(_a) \
do{ \
XPT_ASSERT((_a)); \
(_a)->LOG_LoadingFreeCallCount = (_a)->LOG_FreeCallCount; \
} while(0)
#define PRINT_STATS(_a) xpt_DebugPrintArenaStats((_a))
static void xpt_DebugPrintArenaStats(XPTArena *arena);
#else /* !XPT_ARENA_LOGGING */
#define LOG_MALLOC(_a, _req, _used) ((void)0)
#define LOG_REAL_MALLOC(_a, _size) ((void)0)
#define LOG_FREE(_a) ((void)0)
#define LOG_DONE_LOADING(_a) ((void)0)
#define PRINT_STATS(_a) ((void)0)
#endif /* XPT_ARENA_LOGGING */
/****************************************************/
/* Block header for each block in the arena */
typedef struct BLK_HDR BLK_HDR;
struct BLK_HDR
{
BLK_HDR *next;
size_t size;
};
#define XPT_MIN_BLOCK_SIZE 32
/* XXX this is lame. Should clone the code to do this bitwise */
#define ALIGN_RND(s,a) ((a)==1?(s):((((s)+(a)-1)/(a))*(a)))
struct XPTArena
{
BLK_HDR *first;
PRUint8 *next;
size_t space;
size_t alignment;
size_t block_size;
char *name;
#ifdef XPT_ARENA_LOGGING
PRUint32 LOG_MallocCallCount;
PRUint32 LOG_MallocTotalBytesRequested;
PRUint32 LOG_MallocTotalBytesUsed;
PRUint32 LOG_FreeCallCount;
PRUint32 LOG_LoadingFreeCallCount;
PRUint32 LOG_RealMallocCallCount;
PRUint32 LOG_RealMallocTotalBytesRequested;
#endif /* XPT_ARENA_LOGGING */
};
XPT_PUBLIC_API(XPTArena *)
XPT_NewArena(PRUint32 block_size, size_t alignment, const char* name)
{
XPTArena *arena = calloc(1, sizeof(XPTArena));
if (arena) {
XPT_ASSERT(alignment);
if (alignment > sizeof(double))
alignment = sizeof(double);
arena->alignment = alignment;
if (block_size < XPT_MIN_BLOCK_SIZE)
block_size = XPT_MIN_BLOCK_SIZE;
arena->block_size = ALIGN_RND(block_size, alignment);
/* must have room for at least one item! */
XPT_ASSERT(arena->block_size >=
ALIGN_RND(sizeof(BLK_HDR), alignment) +
ALIGN_RND(1, alignment));
if (name) {
arena->name = XPT_STRDUP(arena, name);
#ifdef XPT_ARENA_LOGGING
/* fudge the stats since we are using space in the arena */
arena->LOG_MallocCallCount = 0;
arena->LOG_MallocTotalBytesRequested = 0;
arena->LOG_MallocTotalBytesUsed = 0;
#endif /* XPT_ARENA_LOGGING */
}
}
return arena;
}
XPT_PUBLIC_API(void)
XPT_DestroyArena(XPTArena *arena)
{
BLK_HDR* cur;
BLK_HDR* next;
cur = arena->first;
while (cur) {
next = cur->next;
free(cur);
cur = next;
}
free(arena);
}
XPT_PUBLIC_API(void)
XPT_DumpStats(XPTArena *arena)
{
PRINT_STATS(arena);
}
/*
* Our alignment rule is that we always round up the size of each allocation
* so that the 'arena->next' pointer one will point to properly aligned space.
*/
XPT_PUBLIC_API(void *)
XPT_ArenaMalloc(XPTArena *arena, size_t size)
{
PRUint8 *cur;
size_t bytes;
if (!size)
return NULL;
if (!arena) {
XPT_ASSERT(0);
return NULL;
}
bytes = ALIGN_RND(size, arena->alignment);
LOG_MALLOC(arena, size, bytes);
if (bytes > arena->space) {
BLK_HDR* new_block;
size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), arena->alignment);
size_t new_space = arena->block_size;
if (bytes > new_space - block_header_size)
new_space += bytes;
new_block = (BLK_HDR*) calloc(new_space/arena->alignment,
arena->alignment);
if (!new_block) {
arena->next = NULL;
arena->space = 0;
return NULL;
}
LOG_REAL_MALLOC(arena, new_space);
/* link block into the list of blocks for use when we destroy */
new_block->next = arena->first;
arena->first = new_block;
/* save other block header info */
new_block->size = new_space;
/* set info for current block */
arena->next = ((PRUint8*)new_block) + block_header_size;
arena->space = new_space - block_header_size;
#ifdef DEBUG
/* mark block for corruption check */
memset(arena->next, 0xcd, arena->space);
#endif
}
#ifdef DEBUG
{
/* do corruption check */
size_t i;
for (i = 0; i < bytes; ++i) {
XPT_ASSERT(arena->next[i] == 0xcd);
}
/* we guarantee that the block will be filled with zeros */
memset(arena->next, 0, bytes);
}
#endif
cur = arena->next;
arena->next += bytes;
arena->space -= bytes;
return cur;
}
XPT_PUBLIC_API(char *)
XPT_ArenaStrDup(XPTArena *arena, const char * s)
{
size_t len;
char* cur;
if (!s)
return NULL;
len = strlen(s)+1;
cur = XPT_ArenaMalloc(arena, len);
memcpy(cur, s, len);
return cur;
}
XPT_PUBLIC_API(void)
XPT_NotifyDoneLoading(XPTArena *arena)
{
#ifdef XPT_ARENA_LOGGING
if (arena) {
LOG_DONE_LOADING(arena);
}
#endif
}
XPT_PUBLIC_API(void)
XPT_ArenaFree(XPTArena *arena, void *block)
{
LOG_FREE(arena);
}
#ifdef XPT_ARENA_LOGGING
static void xpt_DebugPrintArenaStats(XPTArena *arena)
{
printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n");
printf("Start xpt arena stats for \"%s\"\n",
arena->name ? arena->name : "unnamed arena");
printf("\n");
printf("%d times arena malloc called\n", (int) arena->LOG_MallocCallCount);
printf("%d total bytes requested from arena malloc\n", (int) arena->LOG_MallocTotalBytesRequested);
printf("%d average bytes requested per call to arena malloc\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0);
printf("%d average bytes used per call (accounts for alignment overhead)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0);
printf("%d average bytes used per call (accounts for all overhead and waste)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_RealMallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0);
printf("\n");
printf("%d during loading times arena free called\n", (int) arena->LOG_LoadingFreeCallCount);
printf("%d during loading approx total bytes not freed\n", (int) arena->LOG_LoadingFreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0));
printf("\n");
printf("%d total times arena free called\n", (int) arena->LOG_FreeCallCount);
printf("%d approx total bytes not freed until arena destruction\n", (int) arena->LOG_FreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0 ));
printf("\n");
printf("%d times arena called system malloc\n", (int) arena->LOG_RealMallocCallCount);
printf("%d total bytes arena requested from system\n", (int) arena->LOG_RealMallocTotalBytesRequested);
printf("%d byte block size specified at arena creation time\n", (int) arena->block_size);
printf("%d byte block alignment specified at arena creation time\n", (int) arena->alignment);
printf("\n");
printf("End xpt arena stats\n");
printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n");
}
#endif
/***************************************************************************/