Bug 972593 - Convert nsStreamConverterService hashtables to something modern. r=mcmanus

This commit is contained in:
Andrew McCreight 2014-04-30 09:39:34 -07:00
Родитель b27d710233
Коммит 23a110bafc
2 изменённых файлов: 45 добавлений и 69 удалений

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

@ -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___