Made GameList use quicksort instead of selection sort, resulting in approx.

12-15X speedup on large folders.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1032 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2006-03-10 00:29:46 +00:00
parent 0578b45112
commit f6c8c52684
3 changed files with 94 additions and 35 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: GameList.cxx,v 1.8 2006-03-09 00:29:52 stephena Exp $
// $Id: GameList.cxx,v 1.9 2006-03-10 00:29:46 stephena Exp $
//
// Based on code from KStella - Stella frontend
// Copyright (C) 2003-2005 Stephen Anthony
@ -33,44 +33,97 @@ GameList::GameList()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GameList::~GameList()
{
myArray.clear();
clear();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameList::appendGame(const string& name, const string& path,
const string& note, bool isDir)
{
Entry g;
g._name = name;
g._path = path;
g._note = note;
g._isdir = isDir;
Entry* g = new Entry;
g->_name = name;
g->_path = path;
g->_note = note;
g->_isdir = isDir;
myArray.push_back(g);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameList::clear()
{
for(unsigned int i = 0; i < myArray.size(); ++i)
delete myArray[i];
myArray.clear();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameList::sortByName()
{
if(myArray.size() <= 1)
return;
// Simple selection sort
for (unsigned int i = 0; i < myArray.size()-1; i++)
{
unsigned int min = i;
for (unsigned int j = i+1; j < myArray.size(); j++)
{
// TODO - add option for this
string atJ = myArray[j]._name;
string atMin = myArray[min]._name;
transform(atJ.begin(), atJ.end(), atJ.begin(), (int(*)(int)) toupper);
transform(atMin.begin(), atMin.end(), atMin.begin(), (int(*)(int)) toupper);
if (atJ < atMin)
min = j;
}
if (min != i)
SWAP(myArray[min], myArray[i]);
}
QuickSort(myArray, 0, myArray.size()-1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameList::QuickSort(EntryList& a, int left, int right)
{
int l_hold = left;
int r_hold = right;
Entry* pivot_entry = a[left];
while (left < right)
{
while ((compare(a[right]->_name, pivot_entry->_name) >= 0) && (left < right))
right--;
if (left != right)
{
a[left] = a[right];
left++;
}
while ((compare(a[left]->_name, pivot_entry->_name) <= 0) && (left < right))
left++;
if (left != right)
{
a[right] = a[left];
right--;
}
}
a[left] = pivot_entry;
int pivot = left;
left = l_hold;
right = r_hold;
if (left < pivot)
QuickSort(a, left, pivot-1);
if (right > pivot)
QuickSort(a, pivot+1, right);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int GameList::compare(const string& s1, const string& s2)
{
string::const_iterator it1=s1.begin();
string::const_iterator it2=s2.begin();
// Stop when either string's end has been reached
while( (it1 != s1.end()) && (it2 != s2.end()) )
{
if(::toupper(*it1) != ::toupper(*it2)) // letters differ?
// return -1 to indicate smaller than, 1 otherwise
return (::toupper(*it1) < ::toupper(*it2)) ? -1 : 1;
// proceed to the next character in each string
++it1;
++it2;
}
size_t size1 = s1.size(), size2 = s2.size(); // cache lengths
// return -1,0 or 1 according to strings' lengths
if (size1 == size2)
return 0;
else
return (size1 < size2) ? -1 : 1;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: GameList.hxx,v 1.9 2006-03-09 00:29:52 stephena Exp $
// $Id: GameList.hxx,v 1.10 2006-03-10 00:29:46 stephena Exp $
//
// Based on code from KStella - Stella frontend
// Copyright (C) 2003-2005 Stephen Anthony
@ -38,24 +38,32 @@ class GameList
bool _isdir;
};
typedef Common::Array<Entry> EntryList;
typedef Common::Array<Entry*> EntryList;
EntryList myArray;
public:
GameList();
~GameList();
inline const string& name(int i) { return myArray[i]._name; }
inline const string& path(int i) { return myArray[i]._path; }
inline const string& note(int i) { return myArray[i]._note; }
inline const bool isDir(int i) { return myArray[i]._isdir; }
inline const string& name(int i)
{ return i < (int)myArray.size() ? myArray[i]->_name : EmptyString; }
inline const string& path(int i)
{ return i < (int)myArray.size() ? myArray[i]->_path : EmptyString; }
inline const string& note(int i)
{ return i < (int)myArray.size() ? myArray[i]->_note : EmptyString; }
inline const bool isDir(int i)
{ return i < (int)myArray.size() ? myArray[i]->_isdir: false; }
inline int size() { return myArray.size(); }
void clear();
void clear() { myArray.clear(); }
void appendGame(const string& name, const string& path, const string& note,
bool isDir = false);
void sortByName();
private:
static void QuickSort(EntryList& list, int l, int r);
inline static int compare(const string& s1, const string& s2);
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: LauncherDialog.cxx,v 1.45 2006-03-09 17:04:01 stephena Exp $
// $Id: LauncherDialog.cxx,v 1.46 2006-03-10 00:29:46 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -279,8 +279,6 @@ void LauncherDialog::updateListing(bool fullReload)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherDialog::loadDirListing()
{
cerr << "browse path = " << myCurrentDir << endl;
FilesystemNode dir(myCurrentDir);
FSList files = dir.listDir(FilesystemNode::kListAll);