summaryrefslogtreecommitdiff
path: root/ui/sorting.h
diff options
context:
space:
mode:
Diffstat (limited to 'ui/sorting.h')
-rw-r--r--ui/sorting.h259
1 files changed, 135 insertions, 124 deletions
diff --git a/ui/sorting.h b/ui/sorting.h
index 33a6404f..e65344e6 100644
--- a/ui/sorting.h
+++ b/ui/sorting.h
@@ -4,167 +4,178 @@
#include "../fileHierarchy.h"
#include "../shared/systemConstants.h"
#include "../synchronization.h"
+#include "../shared/staticAssert.h"
namespace FreeFileSync
{
- inline
- int compareString(const Zstring& stringA, const Zstring& stringB)
- {
+inline
+int compareString(const Zstring& stringA, const Zstring& stringB)
+{
#ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case
- return stringA.CmpNoCase(stringB);
+ return stringA.CmpNoCase(stringB);
#elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case
- return stringA.Cmp(stringB);
+ return stringA.Cmp(stringB);
#endif
- }
+}
- inline
- bool stringSmallerThan(const Zstring& stringA, const Zstring& stringB)
+template <bool ascending>
+struct Compare
+{
+ template <class T>
+ bool isSmallerThan(T a, T b)
{
- return compareString(stringA, stringB) < 0;
+ assert_static(sizeof(T) <= 2 * sizeof(int)); //use for comparing (small) INTEGRAL types only!
+ return a < b;
}
+};
+template <>
+struct Compare<false>
+{
+ template <class T>
+ bool isSmallerThan(T a, T b)
+ {
+ assert_static(sizeof(T) <= 2 * sizeof(int)); //use for comparing (small) INTEGRAL types only!
+ return a > b;
+ }
+};
+
+
+inline
+bool stringSmallerThan(const Zstring& stringA, const Zstring& stringB)
+{
+ return compareString(stringA, stringB) < 0;
+}
+
+
+template <bool ascending, SelectedSide side>
+inline
+bool sortByFileName(const FileSystemObject& a, const FileSystemObject& b)
+{
+ //presort types: first files, then directories then empty rows
+ if (a.isEmpty<side>())
+ return false; //empty rows always last
+ else if (b.isEmpty<side>())
+ return true; //empty rows always last
- template <bool ascending, SelectedSide side>
- inline
- bool sortByFileName(const FileSystemObject& a, const FileSystemObject& b)
+ if (dynamic_cast<const DirMapping*>(&a)) //sort directories by relative name
{
- //presort types: first files, then directories then empty rows
- if (a.isEmpty<side>())
- return false; //empty rows always last
- else if (b.isEmpty<side>())
- return true; //empty rows always last
-
-
- if (dynamic_cast<const DirMapping*>(&a)) //sort directories by relative name
- {
- if (dynamic_cast<const DirMapping*>(&b))
- return stringSmallerThan(a.getRelativeName<side>(), b.getRelativeName<side>());
- else
- return false;
- }
+ if (dynamic_cast<const DirMapping*>(&b))
+ return stringSmallerThan(a.getRelativeName<side>(), b.getRelativeName<side>());
else
- {
- if (dynamic_cast<const DirMapping*>(&b))
- return true;
- else
- {
- return ascending ?
- stringSmallerThan(a.getShortName<side>(), b.getShortName<side>()) :
- stringSmallerThan(b.getShortName<side>(), a.getShortName<side>());
- }
- }
+ return false;
}
+ else
+ {
+ if (dynamic_cast<const DirMapping*>(&b))
+ return true;
+ else
+ return Compare<ascending>().isSmallerThan(a.getShortName<side>(), b.getShortName<side>());
+ }
+}
- template <bool ascending, SelectedSide side>
- bool sortByRelativeName(const FileSystemObject& a, const FileSystemObject& b)
+template <bool ascending, SelectedSide side>
+bool sortByRelativeName(const FileSystemObject& a, const FileSystemObject& b)
+{
+ if (a.isEmpty<side>())
+ return false; //empty rows always last
+ else if (b.isEmpty<side>())
+ return true; //empty rows always last
+
+ const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a);
+ const Zstring relDirNameA = fileObjA != NULL ?
+ a.getParentRelativeName() : //file
+ a.getRelativeName<side>(); //directory
+
+ const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b);
+ const Zstring relDirNameB = fileObjB != NULL ?
+ b.getParentRelativeName() : //file
+ b.getRelativeName<side>(); //directory
+
+ //compare relative names without filenames first
+ const int rv = compareString(relDirNameA, relDirNameB);
+ if (rv != 0)
+ return Compare<ascending>().isSmallerThan(rv, 0);
+ else //compare the filenames
{
- if (a.isEmpty<side>())
- return false; //empty rows always last
- else if (b.isEmpty<side>())
- return true; //empty rows always last
-
-
- const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a);
- const Zstring relDirNameA = fileObjA != NULL ?
- a.getParentRelativeName<side>() : //file
- a.getRelativeName<side>(); //directory
-
- const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b);
- const Zstring relDirNameB = fileObjB != NULL ?
- b.getParentRelativeName<side>() : //file
- b.getRelativeName<side>(); //directory
-
- //compare relative names without filenames first
- const int rv = compareString(relDirNameA, relDirNameB);
- if (rv != 0)
- return ascending ? rv < 0 : rv > 0;
- else //compare the filenames
- {
- if (fileObjB == NULL) //directories shall appear before files
- return false;
- else if (fileObjA == NULL)
- return true;
-
- return stringSmallerThan(a.getShortName<side>(), b.getShortName<side>());
- }
+ if (fileObjB == NULL) //directories shall appear before files
+ return false;
+ else if (fileObjA == NULL)
+ return true;
+
+ return stringSmallerThan(a.getShortName<side>(), b.getShortName<side>());
}
+}
- template <bool ascending, SelectedSide side>
- inline
- bool sortByFileSize(const FileSystemObject& a, const FileSystemObject& b)
- {
- if (a.isEmpty<side>())
- return false; //empty rows always last
- else if (b.isEmpty<side>())
- return true; //empty rows always last
+template <bool ascending, SelectedSide side>
+inline
+bool sortByFileSize(const FileSystemObject& a, const FileSystemObject& b)
+{
+ if (a.isEmpty<side>())
+ return false; //empty rows always last
+ else if (b.isEmpty<side>())
+ return true; //empty rows always last
- const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a);
- const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b);
+ const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a);
+ const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b);
- if (fileObjA == NULL)
- return false; //directories last
- else if (fileObjB == NULL)
- return true; //directories last
+ if (fileObjA == NULL)
+ return false; //directories last
+ else if (fileObjB == NULL)
+ return true; //directories last
- return ascending ?
- fileObjA->getFileSize<side>() > fileObjB->getFileSize<side>() : //sortAscending shall result in list beginning with largest files first
- fileObjA->getFileSize<side>() < fileObjB->getFileSize<side>();
- }
+ //sortAscending shall result in list beginning with largest files first
+ return Compare<!ascending>().isSmallerThan(fileObjA->getFileSize<side>(), fileObjB->getFileSize<side>());
+}
- template <bool ascending, SelectedSide side>
- inline
- bool sortByDate(const FileSystemObject& a, const FileSystemObject& b)
- {
- if (a.isEmpty<side>())
- return false; //empty rows always last
- else if (b.isEmpty<side>())
- return true; //empty rows always last
+template <bool ascending, SelectedSide side>
+inline
+bool sortByDate(const FileSystemObject& a, const FileSystemObject& b)
+{
+ if (a.isEmpty<side>())
+ return false; //empty rows always last
+ else if (b.isEmpty<side>())
+ return true; //empty rows always last
- const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a);
- const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b);
+ const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a);
+ const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b);
- if (fileObjA == NULL)
- return false; //directories last
- else if (fileObjB == NULL)
- return true; //directories last
+ if (fileObjA == NULL)
+ return false; //directories last
+ else if (fileObjB == NULL)
+ return true; //directories last
- return ascending ?
- fileObjA->getLastWriteTime<side>() > fileObjB->getLastWriteTime<side>() :
- fileObjA->getLastWriteTime<side>() < fileObjB->getLastWriteTime<side>();
- }
+ return Compare<!ascending>().isSmallerThan(fileObjA->getLastWriteTime<side>(), fileObjB->getLastWriteTime<side>());
+}
- template <bool ascending>
- inline
- bool sortByCmpResult(const FileSystemObject& a, const FileSystemObject& b)
- {
- //presort result: equal shall appear at end of list
- if (a.getCategory() == FILE_EQUAL)
- return false;
- if (b.getCategory() == FILE_EQUAL)
- return true;
+template <bool ascending>
+inline
+bool sortByCmpResult(const FileSystemObject& a, const FileSystemObject& b)
+{
+ //presort result: equal shall appear at end of list
+ if (a.getCategory() == FILE_EQUAL)
+ return false;
+ if (b.getCategory() == FILE_EQUAL)
+ return true;
- return ascending ?
- a.getCategory() < b.getCategory() :
- a.getCategory() > b.getCategory();
- }
+ return Compare<ascending>().isSmallerThan(a.getCategory(), b.getCategory());
+}
- template <bool ascending>
- inline
- bool sortBySyncDirection(const FileSystemObject& a, const FileSystemObject& b)
- {
- return ascending ?
- getSyncOperation(a) < getSyncOperation(b) :
- getSyncOperation(a) > getSyncOperation(b);
- }
+template <bool ascending>
+inline
+bool sortBySyncDirection(const FileSystemObject& a, const FileSystemObject& b)
+{
+ return Compare<ascending>().isSmallerThan(a.getSyncOperation(), b.getSyncOperation());
+}
}
#endif // SORTING_H_INCLUDED
bgstack15