bug 73308 r=valeski sr=shaver a=brendan patch=tmutreja@netscape.com
This commit is contained in:
badami%netscape.com 2002-03-01 09:28:55 +00:00
Родитель 6ae5af8556
Коммит 00fea02e9e
4 изменённых файлов: 208 добавлений и 63 удалений

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

@ -121,7 +121,7 @@ nsStreamConverterService::BuildGraph() {
if (NS_FAILED(rv)) return rv;
// cobble the entry string w/ the converter key to produce a full contractID.
nsCString contractID(NS_ISTREAMCONVERTER_KEY);
nsCAutoString contractID(NS_ISTREAMCONVERTER_KEY);
contractID.Append((const char *)entryString);
// now we've got the CONTRACTID, let's parse it up.
@ -144,65 +144,63 @@ nsStreamConverterService::AddAdjacency(const char *aContractID) {
nsresult rv;
// first parse out the FROM and TO MIME-types.
nsCString fromStr, toStr;
nsCAutoString fromStr, toStr;
rv = ParseFromTo(aContractID, fromStr, toStr);
if (NS_FAILED(rv)) return rv;
// Each MIME-type is a vertex in the graph, so first lets make sure
// each MIME-type is represented as a key in our hashtable.
nsCStringKey *fromKey = new nsCStringKey(ToNewCString(fromStr), fromStr.Length(), nsCStringKey::OWN);
if (!fromKey) return NS_ERROR_OUT_OF_MEMORY;
SCTableData *fromEdges = (SCTableData*)mAdjacencyList->Get(fromKey);
nsCStringKey fromKey(fromStr);
SCTableData *fromEdges = (SCTableData*)mAdjacencyList->Get(&fromKey);
if (!fromEdges) {
// There is no fromStr vertex, create one.
SCTableData *data = new SCTableData;
nsCStringKey *newFromKey = new nsCStringKey(ToNewCString(fromStr), fromStr.Length(), nsCStringKey::OWN);
if (!newFromKey) return NS_ERROR_OUT_OF_MEMORY;
SCTableData *data = new SCTableData(newFromKey);
if (!data) {
delete fromKey;
delete newFromKey;
return NS_ERROR_OUT_OF_MEMORY;
}
data->key = fromKey;
nsCOMPtr<nsISupportsArray> edgeArray;
rv = NS_NewISupportsArray(getter_AddRefs(edgeArray));
if (NS_FAILED(rv)) {
delete fromKey;
delete newFromKey;
data->key = nsnull;
delete data;
return rv;
}
NS_ADDREF(data->data.edges = edgeArray.get());
mAdjacencyList->Put(fromKey, data);
mAdjacencyList->Put(newFromKey, data);
fromEdges = data;
} else {
delete fromKey;
fromKey = nsnull;
}
nsCStringKey *toKey = new nsCStringKey(ToNewCString(toStr), toStr.Length(), nsCStringKey::OWN);
if (!toKey) return NS_ERROR_OUT_OF_MEMORY;
if (!mAdjacencyList->Get(toKey)) {
nsCStringKey toKey(toStr);
if (!mAdjacencyList->Get(&toKey)) {
// There is no toStr vertex, create one.
SCTableData *data = new SCTableData;
nsCStringKey *newToKey = new nsCStringKey(ToNewCString(toStr), toStr.Length(), nsCStringKey::OWN);
if (!newToKey) return NS_ERROR_OUT_OF_MEMORY;
SCTableData *data = new SCTableData(newToKey);
if (!data) {
delete toKey;
delete newToKey;
return NS_ERROR_OUT_OF_MEMORY;
}
data->key = toKey;
nsCOMPtr<nsISupportsArray> edgeArray;
rv = NS_NewISupportsArray(getter_AddRefs(edgeArray));
if (NS_FAILED(rv)) {
delete toKey;
delete newToKey;
data->key = nsnull;
delete data;
return rv;
}
NS_ADDREF(data->data.edges = edgeArray.get());
mAdjacencyList->Put(toKey, data);
} else {
delete toKey;
toKey = nsnull;
mAdjacencyList->Put(newToKey, data);
}
// Now we know the FROM and TO types are represented as keys in the hashtable.
@ -212,6 +210,9 @@ nsStreamConverterService::AddAdjacency(const char *aContractID) {
if (!vertex) return NS_ERROR_OUT_OF_MEMORY;
NS_ASSERTION(fromEdges, "something wrong in adjacency list construction");
if (!fromEdges)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISupportsArray> adjacencyList = fromEdges->data.edges;
return adjacencyList->AppendElement(vertex) ? NS_OK : NS_ERROR_FAILURE; // XXX this method incorrectly returns a bool
}
@ -219,13 +220,16 @@ nsStreamConverterService::AddAdjacency(const char *aContractID) {
nsresult
nsStreamConverterService::ParseFromTo(const char *aContractID, nsCString &aFromRes, nsCString &aToRes) {
nsCString ContractIDStr(aContractID);
nsCAutoString ContractIDStr(aContractID);
PRInt32 fromLoc = ContractIDStr.Find("from=") + 5;
PRInt32 toLoc = ContractIDStr.Find("to=") + 3;
PRInt32 fromLoc = ContractIDStr.Find("from=");
PRInt32 toLoc = ContractIDStr.Find("to=");
if (-1 == fromLoc || -1 == toLoc ) return NS_ERROR_FAILURE;
nsCString fromStr, toStr;
fromLoc = fromLoc + 5;
toLoc = toLoc + 3;
nsCAutoString fromStr, toStr;
ContractIDStr.Mid(fromStr, fromLoc, toLoc - 4 - fromLoc);
ContractIDStr.Mid(toStr, toLoc, ContractIDStr.Length() - toLoc);
@ -246,15 +250,17 @@ static PRBool PR_CALLBACK InitBFSTable(nsHashKey *aKey, void *aData, void* closu
if (!BFSTable) return PR_FALSE;
BFSState *state = new BFSState;
if (!state) return NS_ERROR_OUT_OF_MEMORY;
if (!state) return PR_FALSE;
state->color = white;
state->distance = -1;
state->predecessor = nsnull;
SCTableData *data = new SCTableData;
if (!data) return NS_ERROR_OUT_OF_MEMORY;
data->key = (nsCStringKey*)aKey->Clone();
SCTableData *data = new SCTableData(NS_STATIC_CAST(nsCStringKey*, aKey));
if (!data) {
delete state;
return PR_FALSE;
}
data->data.state = state;
BFSTable->Put(aKey, data);
@ -264,15 +270,22 @@ static PRBool PR_CALLBACK InitBFSTable(nsHashKey *aKey, void *aData, void* closu
// cleans up the BFS state table
static PRBool PR_CALLBACK DeleteBFSEntry(nsHashKey *aKey, void *aData, void *closure) {
SCTableData *data = (SCTableData*)aData;
delete data->key;
BFSState *state = data->data.state;
if (state->predecessor) // there might not be a predecessor depending on the graph
delete state->predecessor;
delete state;
data->key = nsnull;
delete data;
return PR_TRUE;
}
class CStreamConvDeallocator : public nsDequeFunctor {
public:
virtual void* operator()(void* anObject) {
nsCStringKey *key = (nsCStringKey*)anObject;
delete key;
return 0;
}
};
// walks the graph using a breadth-first-search algorithm which generates a discovered
// verticies tree. This tree is then walked up (from destination vertex, to origin vertex)
// and each link in the chain is added to an nsStringArray. A direct lookup for the given
@ -282,6 +295,7 @@ nsresult
nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray **aEdgeList) {
nsresult rv;
if (!aEdgeList) return NS_ERROR_NULL_POINTER;
*aEdgeList = nsnull;
// walk the graph in search of the appropriate converter.
@ -295,55 +309,80 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray
NS_ASSERTION(lBFSTable.Count() == vertexCount, "strmconv BFS table init problem");
// This is our source vertex; our starting point.
nsCString fromC, toC;
nsCAutoString fromC, toC;
rv = ParseFromTo(aContractID, fromC, toC);
if (NS_FAILED(rv)) return rv;
nsCStringKey *source = new nsCStringKey(fromC.get());
if (!source) return NS_ERROR_OUT_OF_MEMORY;
SCTableData *data = (SCTableData*)lBFSTable.Get(source);
if (!data) return NS_ERROR_FAILURE;
if (!data) {
delete source;
return NS_ERROR_FAILURE;
}
BFSState *state = data->data.state;
state->color = gray;
state->distance = 0;
nsDeque grayQ(0);
CStreamConvDeallocator *dtorFunc = new CStreamConvDeallocator();
if (!dtorFunc) {
delete source;
return NS_ERROR_OUT_OF_MEMORY;
}
nsDeque grayQ(dtorFunc);
// Now generate the shortest path tree.
grayQ.Push(source);
while (0 < grayQ.GetSize()) {
nsHashKey *currentHead = (nsHashKey*)grayQ.PeekFront();
nsCStringKey *currentHead = (nsCStringKey*)grayQ.PeekFront();
SCTableData *data2 = (SCTableData*)mAdjacencyList->Get(currentHead);
if (!data2) return NS_ERROR_FAILURE;
nsCOMPtr<nsISupportsArray> edges = data2->data.edges;
NS_ASSERTION(edges, "something went wrong with BFS strmconv algorithm");
if (!edges) return NS_ERROR_FAILURE;
// Get the state of the current head to calculate the distance of each
// reachable vertex in the loop.
data2 = (SCTableData*)lBFSTable.Get(currentHead);
if (!data2) return NS_ERROR_FAILURE;
BFSState *headVertexState = data2->data.state;
NS_ASSERTION(headVertexState, "problem with the BFS strmconv algorithm");
if (!headVertexState) return NS_ERROR_FAILURE;
PRUint32 edgeCount = 0;
rv = edges->Count(&edgeCount);
if (NS_FAILED(rv)) return rv;
for (PRUint32 i = 0; i < edgeCount; i++) {
nsIAtom *curVertexAtom = (nsIAtom*)edges->ElementAt(i);
nsAutoString curVertexStr;
curVertexAtom->ToString(curVertexStr);
nsCStringKey *curVertex = new nsCStringKey(ToNewCString(curVertexStr),
curVertexStr.Length(), nsCStringKey::OWN);
if (!curVertex) return NS_ERROR_OUT_OF_MEMORY;
SCTableData *data3 = (SCTableData*)lBFSTable.Get(curVertex);
if (!data3) {
delete curVertex;
return NS_ERROR_FAILURE;
}
BFSState *curVertexState = data3->data.state;
NS_ASSERTION(curVertexState, "something went wrong with the BFS strmconv algorithm");
if (!curVertexState) return NS_ERROR_FAILURE;
if (white == curVertexState->color) {
curVertexState->color = gray;
curVertexState->distance = headVertexState->distance + 1;
curVertexState->predecessor = currentHead->Clone();
curVertexState->predecessor = (nsCStringKey*)currentHead->Clone();
if (!curVertexState->predecessor) {
delete curVertex;
return NS_ERROR_OUT_OF_MEMORY;
}
grayQ.Push(curVertex);
} else {
delete curVertex; // if this vertex has already been discovered, we don't want
@ -361,27 +400,28 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray
// first parse out the FROM and TO MIME-types being registered.
nsCString fromStr, toStr;
nsCAutoString fromStr, toStr;
rv = ParseFromTo(aContractID, fromStr, toStr);
if (NS_FAILED(rv)) return rv;
// get the root CONTRACTID
nsCString ContractIDPrefix(NS_ISTREAMCONVERTER_KEY);
nsCAutoString ContractIDPrefix(NS_ISTREAMCONVERTER_KEY);
nsCStringArray *shortestPath = new nsCStringArray();
if (!shortestPath) return NS_ERROR_OUT_OF_MEMORY;
nsCStringKey toMIMEType(toStr);
data = (SCTableData*)lBFSTable.Get(&toMIMEType);
if (!data) {
// If this vertex isn't in the BFSTable, then no-one has registered for it,
// therefore we can't do the conversion.
*aEdgeList = nsnull;
delete shortestPath;
return NS_ERROR_FAILURE;
}
while (data) {
BFSState *curState = data->data.state;
nsCStringKey *key = (nsCStringKey*)data->key;
nsCStringKey *key = data->key;
if (fromStr.Equals(key->GetString())) {
// found it. We're done here.
@ -393,13 +433,14 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray
// Get the predecessor.
if (!curState->predecessor) break; // no predecessor
SCTableData *predecessorData = (SCTableData*)lBFSTable.Get(curState->predecessor);
if (!predecessorData) break; // no predecessor, chain doesn't exist.
// build out the CONTRACTID.
nsCString newContractID(ContractIDPrefix);
nsCAutoString newContractID(ContractIDPrefix);
newContractID.Append("?from=");
nsCStringKey *predecessorKey = (nsCStringKey*)predecessorData->key;
nsCStringKey *predecessorKey = predecessorData->key;
newContractID.Append(predecessorKey->GetString());
newContractID.Append("&to=");
@ -412,10 +453,8 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsCStringArray
// move up the tree.
data = predecessorData;
}
*aEdgeList = nsnull;
delete shortestPath;
return NS_ERROR_FAILURE; // couldn't find a stream converter or chain.
}
@ -432,7 +471,7 @@ nsStreamConverterService::Convert(nsIInputStream *aFromStream,
// first determine whether we can even handle this covnversion
// build a CONTRACTID
nsCString contractID(NS_ISTREAMCONVERTER_KEY);
nsCAutoString contractID(NS_ISTREAMCONVERTER_KEY);
contractID.Append("?from=");
contractID.AppendWithConversion(aFromType);
contractID.Append("&to=");
@ -478,7 +517,7 @@ nsStreamConverterService::Convert(nsIInputStream *aFromStream,
return rv;
}
nsCString fromStr, toStr;
nsCAutoString fromStr, toStr;
rv = ParseFromTo(lContractID, fromStr, toStr);
if (NS_FAILED(rv)) {
delete converterChain;
@ -531,7 +570,7 @@ nsStreamConverterService::AsyncConvertData(const PRUnichar *aFromType,
// first determine whether we can even handle this covnversion
// build a CONTRACTID
nsCString contractID(NS_ISTREAMCONVERTER_KEY);
nsCAutoString contractID(NS_ISTREAMCONVERTER_KEY);
contractID.Append("?from=");
contractID.AppendWithConversion(aFromType);
contractID.Append("&to=");
@ -575,7 +614,7 @@ nsStreamConverterService::AsyncConvertData(const PRUnichar *aFromType,
nsCOMPtr<nsIStreamConverter> converter(do_CreateInstance(lContractID, &rv));
NS_ASSERTION(NS_SUCCEEDED(rv), "graph construction problem, built a contractid that wasn't registered");
nsCString fromStr, toStr;
nsCAutoString fromStr, toStr;
rv = ParseFromTo(lContractID, fromStr, toStr);
if (NS_FAILED(rv)) {
delete converterChain;

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

@ -80,19 +80,25 @@ private:
// used to establish discovered vertecies.
enum BFScolors {white, gray, black};
typedef struct _BFSState {
struct BFSState {
BFScolors color;
PRInt32 distance;
nsHashKey *predecessor;
} BFSState;
nsCStringKey *predecessor;
~BFSState() {
delete predecessor;
}
};
// adjacency list and BFS hashtable data class.
typedef struct _tableData {
struct SCTableData {
nsCStringKey *key;
union _data {
BFSState *state;
nsISupportsArray *edges;
} data;
} SCTableData;
SCTableData(nsCStringKey* aKey) : key(aKey) {
data.state = nsnull;
}
};
#endif // __nsstreamconverterservice__h___

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

@ -522,6 +522,33 @@ nsresult nsIDKey::Write(nsIObjectOutputStream* aStream) const
////////////////////////////////////////////////////////////////////////////////
// Copy Constructor
// We need to free mStr if the object is passed with mOwnership as OWN. As the
// destructor here is freeing mStr in that case, mStr is NOT getting leaked here.
nsCStringKey::nsCStringKey(const nsCStringKey& aKey)
: mStr(aKey.mStr), mStrLen(aKey.mStrLen), mOwnership(aKey.mOwnership)
{
if (mOwnership != NEVER_OWN) {
PRUint32 len = mStrLen * sizeof(char);
char* str = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(len + sizeof(char)));
if (!str) {
// Pray we don't dangle!
mOwnership = NEVER_OWN;
} else {
// Use memcpy in case there are embedded NULs.
memcpy(str, mStr, len);
str[mStrLen] = '\0';
mStr = str;
mOwnership = OWN;
}
}
#ifdef DEBUG
mKeyType = CStringKey;
#endif
MOZ_COUNT_CTOR(nsCStringKey);
}
nsCStringKey::nsCStringKey(const nsAFlatCString& str)
: mStr(NS_CONST_CAST(char*, str.get())),
mStrLen(str.Length()),
@ -620,6 +647,33 @@ nsCStringKey::Write(nsIObjectOutputStream* aStream) const
////////////////////////////////////////////////////////////////////////////////
// Copy Constructor
// We need to free mStr if the object is passed with mOwnership as OWN. As the
// destructor here is freeing mStr in that case, mStr is NOT getting leaked here.
nsStringKey::nsStringKey(const nsStringKey& aKey)
: mStr(aKey.mStr), mStrLen(aKey.mStrLen), mOwnership(aKey.mOwnership)
{
if (mOwnership != NEVER_OWN) {
PRUint32 len = mStrLen * sizeof(PRUnichar);
PRUnichar* str = NS_REINTERPRET_CAST(PRUnichar*, nsMemory::Alloc(len + sizeof(PRUnichar)));
if (!str) {
// Pray we don't dangle!
mOwnership = NEVER_OWN;
} else {
// Use memcpy in case there are embedded NULs.
memcpy(str, mStr, len);
str[mStrLen] = 0;
mStr = str;
mOwnership = OWN;
}
}
#ifdef DEBUG
mKeyType = StringKey;
#endif
MOZ_COUNT_CTOR(nsStringKey);
}
nsStringKey::nsStringKey(const nsAFlatString& str)
: mStr(NS_CONST_CAST(PRUnichar*, str.get())),
mStrLen(str.Length()),
@ -713,6 +767,30 @@ nsStringKey::Write(nsIObjectOutputStream* aStream) const
////////////////////////////////////////////////////////////////////////////////
// Copy Constructor
// We need to free mBuf if the object is passed with mOwnership as OWN. As the
// destructor here is freeing mBuf in that case, mBuf is NOT getting leaked.
nsOpaqueKey::nsOpaqueKey(const nsOpaqueKey& aKey)
: mBuf(aKey.mBuf), mBufLen(aKey.mBufLen), mOwnership(aKey.mOwnership)
{
if (mOwnership != NEVER_OWN) {
char* newBuf = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(mBufLen));
if (!newBuf) {
// Pray we don't dangle!
mOwnership = NEVER_OWN;
} else {
memcpy(newBuf, mBuf, mBufLen);
mBuf = newBuf;
mOwnership = OWN;
}
}
#ifdef DEBUG
mKeyType = OpaqueKey;
#endif
MOZ_COUNT_CTOR(nsOpaqueKey);
}
nsOpaqueKey::nsOpaqueKey(const char* str, PRUint32 strLen, Ownership own)
: mBuf((char*)str), mBufLen(strLen), mOwnership(own)
{

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

@ -205,6 +205,13 @@ class NS_COM nsISupportsKey : public nsHashKey {
nsISupports* mKey;
public:
nsISupportsKey(const nsISupportsKey& aKey) : mKey(aKey.mKey) {
#ifdef DEBUG
mKeyType = SupportsKey;
#endif
NS_IF_ADDREF(mKey);
}
nsISupportsKey(nsISupports* key) {
#ifdef DEBUG
mKeyType = SupportsKey;
@ -267,6 +274,12 @@ class nsVoidKey : public nsHashKey {
void* mKey;
public:
nsVoidKey(const nsVoidKey& aKey) : mKey(aKey.mKey) {
#ifdef DEBUG
mKeyType = aKey.mKeyType;
#endif
}
nsVoidKey(void* key) {
#ifdef DEBUG
mKeyType = VoidKey;
@ -300,6 +313,12 @@ class NS_COM nsIDKey : public nsHashKey {
nsID mID;
public:
nsIDKey(const nsIDKey& aKey) : mID(aKey.mID) {
#ifdef DEBUG
mKeyType = IDKey;
#endif
}
nsIDKey(const nsID &aID) {
#ifdef DEBUG
mKeyType = IDKey;
@ -339,6 +358,7 @@ class NS_COM nsCStringKey : public nsHashKey {
OWN // to be free'd in key dtor. Clones make their own copy.
};
nsCStringKey(const nsCStringKey& aStrKey);
nsCStringKey(const char* str, PRInt32 strLen = -1, Ownership own = OWN_CLONE);
nsCStringKey(const nsAFlatCString& str);
nsCStringKey(const nsACString& str);
@ -372,6 +392,7 @@ class NS_COM nsStringKey : public nsHashKey {
OWN // to be free'd in key dtor. Clones make their own copy.
};
nsStringKey(const nsStringKey& aKey);
nsStringKey(const PRUnichar* str, PRInt32 strLen = -1, Ownership own = OWN_CLONE);
nsStringKey(const nsAFlatString& str);
nsStringKey(const nsAString& str);
@ -405,6 +426,7 @@ class NS_COM nsOpaqueKey : public nsHashKey {
OWN // to be free'd in key dtor. Clones make their own copy.
};
nsOpaqueKey(const nsOpaqueKey& aKey);
nsOpaqueKey(const char* buf, PRUint32 bufLen, Ownership own = OWN_CLONE);
~nsOpaqueKey(void);