зеркало из https://github.com/mozilla/gecko-dev.git
Bug 972593 - Convert nsStreamConverterService hashtables to something modern. r=mcmanus
This commit is contained in:
Родитель
b27d710233
Коммит
23a110bafc
|
@ -38,27 +38,17 @@
|
||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
// Breadth-First-Search (BFS) algorithm state classes and types.
|
// Breadth-First-Search (BFS) algorithm state classes and types.
|
||||||
|
|
||||||
// Adjacency list data class.
|
|
||||||
typedef nsCOMArray<nsIAtom> SCTableData;
|
|
||||||
|
|
||||||
// Delete all the entries in the adjacency list
|
|
||||||
static bool DeleteAdjacencyEntry(nsHashKey *aKey, void *aData, void* closure) {
|
|
||||||
SCTableData *entry = (SCTableData*)aData;
|
|
||||||
delete entry;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to establish discovered verticies.
|
// Used to establish discovered verticies.
|
||||||
enum BFScolors {white, gray, black};
|
enum BFScolors {white, gray, black};
|
||||||
|
|
||||||
// BFS hashtable data class.
|
// BFS hashtable data class.
|
||||||
struct BFSTableData {
|
struct BFSTableData {
|
||||||
nsCStringKey *key;
|
nsCString key;
|
||||||
BFScolors color;
|
BFScolors color;
|
||||||
int32_t distance;
|
int32_t distance;
|
||||||
nsAutoPtr<nsCStringKey> predecessor;
|
nsAutoPtr<nsCString> predecessor;
|
||||||
|
|
||||||
explicit BFSTableData(nsCStringKey* aKey)
|
explicit BFSTableData(const nsACString& aKey)
|
||||||
: key(aKey), color(white), distance(-1)
|
: key(aKey), color(white), distance(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -75,7 +65,6 @@ NS_IMPL_ISUPPORTS(nsStreamConverterService, nsIStreamConverterService)
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// nsStreamConverterService methods
|
// nsStreamConverterService methods
|
||||||
nsStreamConverterService::nsStreamConverterService()
|
nsStreamConverterService::nsStreamConverterService()
|
||||||
: mAdjacencyList(nullptr, nullptr, DeleteAdjacencyEntry, nullptr)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,18 +140,16 @@ nsStreamConverterService::AddAdjacency(const char *aContractID) {
|
||||||
// Each MIME-type is a vertex in the graph, so first lets make sure
|
// 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.
|
// each MIME-type is represented as a key in our hashtable.
|
||||||
|
|
||||||
nsCStringKey fromKey(fromStr);
|
nsCOMArray<nsIAtom> *fromEdges = mAdjacencyList.Get(fromStr);
|
||||||
SCTableData *fromEdges = (SCTableData*)mAdjacencyList.Get(&fromKey);
|
|
||||||
if (!fromEdges) {
|
if (!fromEdges) {
|
||||||
// There is no fromStr vertex, create one.
|
// There is no fromStr vertex, create one.
|
||||||
fromEdges = new SCTableData();
|
fromEdges = new nsCOMArray<nsIAtom>();
|
||||||
mAdjacencyList.Put(&fromKey, fromEdges);
|
mAdjacencyList.Put(fromStr, fromEdges);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCStringKey toKey(toStr);
|
if (!mAdjacencyList.Get(toStr)) {
|
||||||
if (!mAdjacencyList.Get(&toKey)) {
|
|
||||||
// There is no toStr vertex, create one.
|
// There is no toStr vertex, create one.
|
||||||
mAdjacencyList.Put(&toKey, new SCTableData());
|
mAdjacencyList.Put(toStr, new nsCOMArray<nsIAtom>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we know the FROM and TO types are represented as keys in the hashtable.
|
// Now we know the FROM and TO types are represented as keys in the hashtable.
|
||||||
|
@ -201,32 +188,29 @@ nsStreamConverterService::ParseFromTo(const char *aContractID, nsCString &aFromR
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef nsClassHashtable<nsCStringHashKey, BFSTableData> BFSHashTable;
|
||||||
|
|
||||||
|
|
||||||
// nsObjectHashtable enumerator functions.
|
// nsObjectHashtable enumerator functions.
|
||||||
|
|
||||||
// Initializes the BFS state table.
|
// Initializes the BFS state table.
|
||||||
static bool InitBFSTable(nsHashKey *aKey, void *aData, void* closure) {
|
static PLDHashOperator
|
||||||
NS_ASSERTION((SCTableData*)aData, "no data in the table enumeration");
|
InitBFSTable(const nsACString &aKey, nsCOMArray<nsIAtom> *aData, void* aClosure) {
|
||||||
|
MOZ_ASSERT(aData, "no data in the table enumeration");
|
||||||
|
|
||||||
nsHashtable *BFSTable = (nsHashtable*)closure;
|
BFSHashTable *bfsTable = static_cast<BFSHashTable*>(aClosure);
|
||||||
if (!BFSTable) return false;
|
if (!bfsTable) return PL_DHASH_STOP;
|
||||||
|
|
||||||
BFSTable->Put(aKey, new BFSTableData(static_cast<nsCStringKey*>(aKey)));
|
BFSTableData *data = new BFSTableData(aKey);
|
||||||
return true;
|
bfsTable->Put(aKey, data);
|
||||||
}
|
return PL_DHASH_NEXT;
|
||||||
|
|
||||||
// cleans up the BFS state table
|
|
||||||
static bool DeleteBFSEntry(nsHashKey *aKey, void *aData, void *closure) {
|
|
||||||
BFSTableData *data = (BFSTableData*)aData;
|
|
||||||
data->key = nullptr;
|
|
||||||
delete data;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CStreamConvDeallocator : public nsDequeFunctor {
|
class CStreamConvDeallocator : public nsDequeFunctor {
|
||||||
public:
|
public:
|
||||||
virtual void* operator()(void* anObject) {
|
virtual void* operator()(void* anObject) {
|
||||||
nsCStringKey *key = (nsCStringKey*)anObject;
|
nsCString *string = (nsCString*)anObject;
|
||||||
delete key;
|
delete string;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -244,12 +228,12 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCStr
|
||||||
|
|
||||||
// walk the graph in search of the appropriate converter.
|
// walk the graph in search of the appropriate converter.
|
||||||
|
|
||||||
int32_t vertexCount = mAdjacencyList.Count();
|
uint32_t vertexCount = mAdjacencyList.Count();
|
||||||
if (0 >= vertexCount) return NS_ERROR_FAILURE;
|
if (0 >= vertexCount) return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
// Create a corresponding color table for each vertex in the graph.
|
// Create a corresponding color table for each vertex in the graph.
|
||||||
nsObjectHashtable lBFSTable(nullptr, nullptr, DeleteBFSEntry, nullptr);
|
BFSHashTable lBFSTable;
|
||||||
mAdjacencyList.Enumerate(InitBFSTable, &lBFSTable);
|
mAdjacencyList.EnumerateRead(InitBFSTable, &lBFSTable);
|
||||||
|
|
||||||
NS_ASSERTION(lBFSTable.Count() == vertexCount, "strmconv BFS table init problem");
|
NS_ASSERTION(lBFSTable.Count() == vertexCount, "strmconv BFS table init problem");
|
||||||
|
|
||||||
|
@ -258,11 +242,8 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCStr
|
||||||
rv = ParseFromTo(aContractID, fromC, toC);
|
rv = ParseFromTo(aContractID, fromC, toC);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
nsCStringKey *source = new nsCStringKey(fromC.get());
|
BFSTableData *data = lBFSTable.Get(fromC);
|
||||||
|
|
||||||
BFSTableData *data = (BFSTableData*)lBFSTable.Get(source);
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
delete source;
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,15 +254,15 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCStr
|
||||||
nsDeque grayQ(dtorFunc);
|
nsDeque grayQ(dtorFunc);
|
||||||
|
|
||||||
// Now generate the shortest path tree.
|
// Now generate the shortest path tree.
|
||||||
grayQ.Push(source);
|
grayQ.Push(new nsCString(fromC));
|
||||||
while (0 < grayQ.GetSize()) {
|
while (0 < grayQ.GetSize()) {
|
||||||
nsCStringKey *currentHead = (nsCStringKey*)grayQ.PeekFront();
|
nsCString *currentHead = (nsCString*)grayQ.PeekFront();
|
||||||
SCTableData *data2 = (SCTableData*)mAdjacencyList.Get(currentHead);
|
nsCOMArray<nsIAtom> *data2 = mAdjacencyList.Get(*currentHead);
|
||||||
if (!data2) return NS_ERROR_FAILURE;
|
if (!data2) return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
// Get the state of the current head to calculate the distance of each
|
// Get the state of the current head to calculate the distance of each
|
||||||
// reachable vertex in the loop.
|
// reachable vertex in the loop.
|
||||||
BFSTableData *headVertexState = (BFSTableData*)lBFSTable.Get(currentHead);
|
BFSTableData *headVertexState = lBFSTable.Get(*currentHead);
|
||||||
if (!headVertexState) return NS_ERROR_FAILURE;
|
if (!headVertexState) return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
int32_t edgeCount = data2->Count();
|
int32_t edgeCount = data2->Count();
|
||||||
|
@ -290,10 +271,10 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCStr
|
||||||
nsIAtom* curVertexAtom = data2->ObjectAt(i);
|
nsIAtom* curVertexAtom = data2->ObjectAt(i);
|
||||||
nsAutoString curVertexStr;
|
nsAutoString curVertexStr;
|
||||||
curVertexAtom->ToString(curVertexStr);
|
curVertexAtom->ToString(curVertexStr);
|
||||||
nsCStringKey *curVertex = new nsCStringKey(ToNewCString(curVertexStr),
|
nsCString *curVertex = nullptr;
|
||||||
curVertexStr.Length(), nsCStringKey::OWN);
|
CopyUTF16toUTF8(curVertexStr, *curVertex);
|
||||||
|
|
||||||
BFSTableData *curVertexState = (BFSTableData*)lBFSTable.Get(curVertex);
|
BFSTableData *curVertexState = lBFSTable.Get(*curVertex);
|
||||||
if (!curVertexState) {
|
if (!curVertexState) {
|
||||||
delete curVertex;
|
delete curVertex;
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
@ -302,11 +283,7 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCStr
|
||||||
if (white == curVertexState->color) {
|
if (white == curVertexState->color) {
|
||||||
curVertexState->color = gray;
|
curVertexState->color = gray;
|
||||||
curVertexState->distance = headVertexState->distance + 1;
|
curVertexState->distance = headVertexState->distance + 1;
|
||||||
curVertexState->predecessor = (nsCStringKey*)currentHead->Clone();
|
curVertexState->predecessor = new nsCString(*currentHead);
|
||||||
if (!curVertexState->predecessor) {
|
|
||||||
delete curVertex;
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
grayQ.Push(curVertex);
|
grayQ.Push(curVertex);
|
||||||
} else {
|
} else {
|
||||||
delete curVertex; // if this vertex has already been discovered, we don't want
|
delete curVertex; // if this vertex has already been discovered, we don't want
|
||||||
|
@ -315,7 +292,7 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCStr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
headVertexState->color = black;
|
headVertexState->color = black;
|
||||||
nsCStringKey *cur = (nsCStringKey*)grayQ.PopFront();
|
nsCString *cur = (nsCString*)grayQ.PopFront();
|
||||||
delete cur;
|
delete cur;
|
||||||
cur = nullptr;
|
cur = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -324,16 +301,15 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCStr
|
||||||
|
|
||||||
// first parse out the FROM and TO MIME-types being registered.
|
// first parse out the FROM and TO MIME-types being registered.
|
||||||
|
|
||||||
nsAutoCString fromStr, toStr;
|
nsAutoCString fromStr, toMIMEType;
|
||||||
rv = ParseFromTo(aContractID, fromStr, toStr);
|
rv = ParseFromTo(aContractID, fromStr, toMIMEType);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
// get the root CONTRACTID
|
// get the root CONTRACTID
|
||||||
nsAutoCString ContractIDPrefix(NS_ISTREAMCONVERTER_KEY);
|
nsAutoCString ContractIDPrefix(NS_ISTREAMCONVERTER_KEY);
|
||||||
nsTArray<nsCString> *shortestPath = new nsTArray<nsCString>();
|
nsTArray<nsCString> *shortestPath = new nsTArray<nsCString>();
|
||||||
|
|
||||||
nsCStringKey toMIMEType(toStr);
|
data = lBFSTable.Get(toMIMEType);
|
||||||
data = (BFSTableData*)lBFSTable.Get(&toMIMEType);
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
// If this vertex isn't in the BFSTable, then no-one has registered for it,
|
// If this vertex isn't in the BFSTable, then no-one has registered for it,
|
||||||
// therefore we can't do the conversion.
|
// therefore we can't do the conversion.
|
||||||
|
@ -342,9 +318,7 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCStr
|
||||||
}
|
}
|
||||||
|
|
||||||
while (data) {
|
while (data) {
|
||||||
nsCStringKey *key = data->key;
|
if (fromStr.Equals(data->key)) {
|
||||||
|
|
||||||
if (fromStr.Equals(key->GetString())) {
|
|
||||||
// found it. We're done here.
|
// found it. We're done here.
|
||||||
*aEdgeList = shortestPath;
|
*aEdgeList = shortestPath;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -353,7 +327,7 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCStr
|
||||||
// reconstruct the CONTRACTID.
|
// reconstruct the CONTRACTID.
|
||||||
// Get the predecessor.
|
// Get the predecessor.
|
||||||
if (!data->predecessor) break; // no predecessor
|
if (!data->predecessor) break; // no predecessor
|
||||||
BFSTableData *predecessorData = (BFSTableData*)lBFSTable.Get(data->predecessor);
|
BFSTableData *predecessorData = lBFSTable.Get(*data->predecessor);
|
||||||
|
|
||||||
if (!predecessorData) break; // no predecessor, chain doesn't exist.
|
if (!predecessorData) break; // no predecessor, chain doesn't exist.
|
||||||
|
|
||||||
|
@ -361,11 +335,10 @@ nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCStr
|
||||||
nsAutoCString newContractID(ContractIDPrefix);
|
nsAutoCString newContractID(ContractIDPrefix);
|
||||||
newContractID.AppendLiteral("?from=");
|
newContractID.AppendLiteral("?from=");
|
||||||
|
|
||||||
nsCStringKey *predecessorKey = predecessorData->key;
|
newContractID.Append(predecessorData->key);
|
||||||
newContractID.Append(predecessorKey->GetString());
|
|
||||||
|
|
||||||
newContractID.AppendLiteral("&to=");
|
newContractID.AppendLiteral("&to=");
|
||||||
newContractID.Append(key->GetString());
|
newContractID.Append(data->key);
|
||||||
|
|
||||||
// Add this CONTRACTID to the chain.
|
// Add this CONTRACTID to the chain.
|
||||||
rv = shortestPath->AppendElement(newContractID) ? NS_OK : NS_ERROR_FAILURE; // XXX this method incorrectly returns a bool
|
rv = shortestPath->AppendElement(newContractID) ? NS_OK : NS_ERROR_FAILURE; // XXX this method incorrectly returns a bool
|
||||||
|
|
|
@ -9,9 +9,12 @@
|
||||||
#include "nsIStreamConverterService.h"
|
#include "nsIStreamConverterService.h"
|
||||||
|
|
||||||
#include "nsHashtable.h"
|
#include "nsHashtable.h"
|
||||||
|
#include "nsClassHashtable.h"
|
||||||
|
#include "nsCOMArray.h"
|
||||||
#include "nsTArrayForwardDeclare.h"
|
#include "nsTArrayForwardDeclare.h"
|
||||||
|
|
||||||
class nsCString;
|
class nsCString;
|
||||||
|
class nsIAtom;
|
||||||
|
|
||||||
class nsStreamConverterService : public nsIStreamConverterService {
|
class nsStreamConverterService : public nsIStreamConverterService {
|
||||||
public:
|
public:
|
||||||
|
@ -37,7 +40,7 @@ private:
|
||||||
nsresult ParseFromTo(const char *aContractID, nsCString &aFromRes, nsCString &aToRes);
|
nsresult ParseFromTo(const char *aContractID, nsCString &aFromRes, nsCString &aToRes);
|
||||||
|
|
||||||
// member variables
|
// member variables
|
||||||
nsObjectHashtable mAdjacencyList;
|
nsClassHashtable<nsCStringHashKey, nsCOMArray<nsIAtom>> mAdjacencyList;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __nsstreamconverterservice__h___
|
#endif // __nsstreamconverterservice__h___
|
||||||
|
|
Загрузка…
Ссылка в новой задаче