mirror of https://github.com/stella-emu/stella.git
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:
parent
0578b45112
commit
f6c8c52684
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue