Bug 297315 - sorts the XPCOM implementation of nsICategoryManager.enumerateCategory alphabetically r=darin a=asa

This commit is contained in:
bsmedberg%covad.net 2005-06-13 18:39:19 +00:00
parent f593d8de64
commit 84a2c9fc02
5 changed files with 92 additions and 78 deletions

View File

@ -85,8 +85,12 @@ public:
protected:
~nsCommandLine() { }
typedef nsresult (*EnumerateCallback)(nsICommandLineHandler* aHandler,
nsICommandLine* aThis,
void *aClosure);
void appendArg(const char* arg);
nsresult getHandlers(nsCStringArray& handlers, nsICategoryManager* catman);
nsresult EnumerateHandlers(EnumerateCallback aCallback, void *aClosure);
nsStringArray mArgs;
PRUint32 mState;
@ -532,10 +536,14 @@ nsCommandLine::Init(PRInt32 argc, char** argv, nsIFile* aWorkingDir,
}
nsresult
nsCommandLine::getHandlers(nsCStringArray &handlers, nsICategoryManager* catman)
nsCommandLine::EnumerateHandlers(EnumerateCallback aCallback, void *aClosure)
{
nsresult rv;
nsCOMPtr<nsICategoryManager> catman
(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsISimpleEnumerator> entenum;
rv = catman->EnumerateCategory("command-line-handler",
getter_AddRefs(entenum));
@ -548,37 +556,32 @@ nsCommandLine::getHandlers(nsCStringArray &handlers, nsICategoryManager* catman)
PRBool hasMore;
while (NS_SUCCEEDED(strenum->HasMore(&hasMore)) && hasMore) {
strenum->GetNext(entry);
handlers.AppendCString(entry);
nsXPIDLCString contractID;
rv = catman->GetCategoryEntry("command-line-handler",
entry.get(),
getter_Copies(contractID));
if (!contractID)
continue;
nsCOMPtr<nsICommandLineHandler> clh(do_GetService(contractID.get()));
if (!clh)
continue;
rv = (aCallback)(clh, this, aClosure);
if (rv = NS_ERROR_ABORT)
break;
rv = NS_OK;
}
handlers.Sort();
return NS_OK;
return rv;
}
struct RunClosure
static nsresult
EnumRun(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void*)
{
nsICommandLine* cl;
nsICategoryManager* catman;
};
static PRBool
EnumRun(nsCString& aEntry, void* aData)
{
nsresult rv;
RunClosure* closure = NS_STATIC_CAST(RunClosure*, aData);
nsXPIDLCString value;
rv = closure->catman->GetCategoryEntry("command-line-handler",
aEntry.get(),
getter_Copies(value));
NS_ENSURE_SUCCESS(rv, PR_TRUE);
nsCOMPtr<nsICommandLineHandler> clh (do_GetService(value));
NS_ENSURE_TRUE(clh, PR_TRUE);
rv = clh->Handle(closure->cl);
return rv != NS_ERROR_ABORT;
return aHandler->Handle(aThis);
}
NS_IMETHODIMP
@ -586,74 +589,36 @@ nsCommandLine::Run()
{
nsresult rv;
nsCOMPtr<nsICategoryManager> catman
(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED);
nsCStringArray handlers;
rv = getHandlers(handlers, catman);
NS_ENSURE_SUCCESS(rv, rv);
RunClosure closure = { this, catman };
if (!handlers.EnumerateForwards(&EnumRun, &closure))
return NS_ERROR_ABORT;
rv = EnumerateHandlers(EnumRun, nsnull);
if (rv == NS_ERROR_ABORT)
return rv;
return NS_OK;
}
struct HelpClosure
{
HelpClosure(nsACString& aText, nsICategoryManager* aCatman) :
text(aText), catman(aCatman) { }
nsACString& text;
nsICategoryManager* catman;
};
static PRBool
EnumHelp(nsCString& aEntry, void* aData)
EnumHelp(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void* aClosure)
{
nsresult rv;
HelpClosure* closure = NS_STATIC_CAST(HelpClosure*, aData);
nsXPIDLCString value;
rv = closure->catman->GetCategoryEntry("command-line-handler",
aEntry.get(),
getter_Copies(value));
NS_ENSURE_SUCCESS(rv, PR_TRUE);
nsCOMPtr<nsICommandLineHandler> clh (do_GetService(value));
NS_ENSURE_TRUE(clh, PR_TRUE);
nsCString text;
rv = clh->GetHelpInfo(text);
rv = aHandler->GetHelpInfo(text);
if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(text.Length() == 0 || text.Last() == '\n',
"Help text from command line handlers should end in a newline.");
closure->text.Append(text);
nsACString* totalText = NS_REINTERPRET_CAST(nsACString*, aClosure);
totalText->Append(text);
}
return PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsCommandLine::GetHelpText(nsACString& aResult)
{
nsresult rv;
EnumerateHandlers(EnumRun, &aResult);
nsCOMPtr<nsICategoryManager> catman
(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED);
nsCStringArray handlers;
rv = getHandlers(handlers, catman);
NS_ENSURE_SUCCESS(rv, rv);
HelpClosure closure (aResult, catman);
handlers.EnumerateForwards(EnumHelp, &closure);
return NS_OK;
}

View File

@ -65,6 +65,9 @@
* XPCOM Category Manager Contract ID
* The contract supports the nsICategoryManager interface. The
* category manager is a singleton.
* The "enumerateCategory" method of nsICategoryManager will return an object
* that implements nsIUTF8StringEnumerator. In addition, the enumerator will
* return the entries in sorted order (sorted by byte comparison).
*/
#define NS_CATEGORYMANAGER_CONTRACTID "@mozilla.org/categorymanager;1"

View File

@ -55,6 +55,7 @@
#include "nsIObserver.h"
#include "nsReadableUtils.h"
#include "nsCRT.h"
#include "nsQuickSort.h"
#include "nsEnumeratorUtils.h"
class nsIComponentLoaderManager;
@ -90,6 +91,9 @@ public:
NS_DECL_NSIUTF8STRINGENUMERATOR
protected:
// Callback function for NS_QuickSort to sort mArray
static int SortCallback(const void *, const void *, void *);
BaseStringEnumerator()
: mArray(nsnull),
mCount(0),
@ -105,6 +109,8 @@ protected:
delete[] mArray;
}
void Sort();
const char** mArray;
PRUint32 mCount;
PRUint32 mSimpleCurItem;
@ -155,6 +161,21 @@ BaseStringEnumerator::GetNext(nsACString& _retval)
return NS_OK;
}
int
BaseStringEnumerator::SortCallback(const void *e1, const void *e2,
void * /*unused*/)
{
char const *const *s1 = NS_REINTERPRET_CAST(char const *const *, e1);
char const *const *s2 = NS_REINTERPRET_CAST(char const *const *, e2);
return strcmp(*s1, *s2);
}
void
BaseStringEnumerator::Sort()
{
NS_QuickSort(mArray, mCount, sizeof(mArray[0]), SortCallback, nsnull);
}
//
// EntryEnumerator is the wrapper that allows nsICategoryManager::EnumerateCategory
@ -195,6 +216,8 @@ EntryEnumerator::Create(nsTHashtable<CategoryLeaf>& aTable)
aTable.EnumerateEntries(enumfunc_createenumerator, enumObj);
enumObj->Sort();
return enumObj;
}

View File

@ -80,11 +80,27 @@ NS_IMETHODIMP EmptyEnumeratorImpl::HasMoreElements(PRBool* aResult)
return NS_OK;
}
NS_IMETHODIMP EmptyEnumeratorImpl::HasMore(PRBool* aResult)
{
*aResult = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsISupports** aResult)
{
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsACString& aResult)
{
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsAString& aResult)
{
return NS_ERROR_UNEXPECTED;
}
static EmptyEnumeratorImpl* gEmptyEnumerator = nsnull;
extern "C" NS_COM nsresult

View File

@ -42,11 +42,14 @@
*/
#include "nsIEnumerator.h"
#include "nsISimpleEnumerator.h"
#include "nsIStringEnumerator.h"
////////////////////////////////////////////////////////////////////////
class EmptyEnumeratorImpl : public nsISimpleEnumerator
class EmptyEnumeratorImpl : public nsISimpleEnumerator,
public nsIUTF8StringEnumerator,
public nsIStringEnumerator
{
public:
EmptyEnumeratorImpl(void);
@ -56,6 +59,10 @@ public:
// nsISimpleEnumerator
NS_DECL_NSISIMPLEENUMERATOR
NS_DECL_NSIUTF8STRINGENUMERATOR
// can't use NS_DECL_NSISTRINGENUMERATOR because they share the
// HasMore() signature
NS_IMETHOD GetNext(nsAString& aResult);
static void Shutdown();