diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -1124,6 +1124,10 @@
>
+
+
@@ -1444,6 +1448,10 @@
>
+
+
diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -1121,6 +1121,10 @@
>
+
+
@@ -1441,6 +1445,10 @@
>
+
+
diff --git a/source.list b/source.list
--- a/source.list
+++ b/source.list
@@ -206,6 +206,7 @@ map_func.h
map_type.h
core/math_func.hpp
md5.h
+core/mem_func.hpp
minilzo.h
mixer.h
music.h
@@ -286,6 +287,7 @@ signs_func.h
signs_type.h
slope_func.h
slope_type.h
+core/sort_func.hpp
sortlist_type.h
sound_func.h
sound_type.h
diff --git a/src/core/mem_func.hpp b/src/core/mem_func.hpp
new file mode 100644
--- /dev/null
+++ b/src/core/mem_func.hpp
@@ -0,0 +1,57 @@
+/* $Id$ */
+
+/** @file mem_func.hpp Functions related to memory operations. */
+
+#ifndef MEM_FUNC_HPP
+#define MEM_FUNC_HPP
+
+#include
+#include "math_func.hpp"
+
+/**
+ * Type-safe version of memcpy().
+ *
+ * @param destination Pointer to the destination buffer
+ * @param source Pointer to the source buffer
+ * @param num number of items to be copied. (!not number of bytes!)
+ */
+template
+FORCEINLINE void MemCpyT(T *destination, const T *source, uint num = 1)
+{
+ memcpy(destination, source, num * sizeof(T));
+}
+
+/**
+ * Type safe memory reverse operation.
+ * Reverse a block of memory in steps given by the
+ * type of the pointers.
+ *
+ * @param ptr1 Start-pointer to the block of memory.
+ * @param ptr2 End-pointer to the block of memory.
+ */
+template
+FORCEINLINE void MemReverseT(T *ptr1, T *ptr2)
+{
+ assert(ptr1 != NULL && ptr2 != NULL);
+ assert(ptr1 < ptr2);
+
+ do {
+ Swap(*ptr1, *ptr2);
+ } while (++ptr1 < --ptr2);
+}
+
+/**
+ * Type safe memory reverse operation (overloaded)
+ *
+ * @param ptr Pointer to the block of memory.
+ * @param num The number of items we want to reverse.
+ */
+template
+FORCEINLINE void MemReverseT(T *ptr, uint num)
+{
+ assert(ptr != NULL);
+
+ MemReverseT(ptr, ptr + (num - 1));
+}
+
+#endif /* MEM_FUNC_HPP */
diff --git a/src/core/sort_func.hpp b/src/core/sort_func.hpp
new file mode 100644
--- /dev/null
+++ b/src/core/sort_func.hpp
@@ -0,0 +1,85 @@
+/* $Id$ */
+
+/** @file sort_func.hpp Functions related to sorting operations. */
+
+#ifndef SORT_FUNC_HPP
+#define SORT_FUNC_HPP
+
+#include
+#include "math_func.hpp"
+#include "mem_func.hpp"
+
+/**
+ * Type safe qsort()
+ *
+ * @todo replace the normal qsort with this one
+ * @note Use this sort for irregular sorted data.
+ *
+ * @param base Pointer to the first element of the array to be sorted.
+ * @param num Number of elements in the array pointed by base.
+ * @param comparator Function that compares two elements.
+ * @param desc Sort descending.
+ */
+template
+FORCEINLINE void QSortT(T *base, uint num, int (CDECL *comparator)(const T*, const T*), bool desc = false)
+{
+ if (num < 2) return;
+
+ qsort(base, num, sizeof(T), (int (CDECL *)(const void *, const void *))comparator);
+
+ if (desc) MemReverseT(base, num);
+}
+
+/**
+ * Type safe Gnome Sort.
+ *
+ * This is a slightly modifyied Gnome search. The basic
+ * Gnome search trys to sort already sorted list parts.
+ * The modification skips these.
+ *
+ * @note Use this sort for presorted / regular sorted data.
+ *
+ * @param base Pointer to the first element of the array to be sorted.
+ * @param num Number of elements in the array pointed by base.
+ * @param comparator Function that compares two elements.
+ * @param desc Sort descending.
+ */
+template
+FORCEINLINE void GSortT(T *base, uint num, int (CDECL *comparator)(const T*, const T*), bool desc = false)
+{
+ if (num < 2) return;
+
+ assert(base != NULL);
+ assert(comparator != NULL);
+
+ T *a = base;
+ T *b = base + 1;
+ uint offset = 0;
+
+ while (num > 1) {
+ const int diff = comparator(a, b);
+ if ((!desc && diff <= 0) || (desc && diff >= 0)) {
+ if (offset != 0) {
+ /* Jump back to the last direction switch point */
+ a += offset;
+ b += offset;
+ offset = 0;
+ continue;
+ }
+
+ a++;
+ b++;
+ num--;
+ } else {
+ Swap(*a, *b);
+
+ if (a == base) continue;
+
+ a--;
+ b--;
+ offset++;
+ }
+ }
+}
+
+#endif /* SORT_FUNC_HPP */
diff --git a/src/misc/blob.hpp b/src/misc/blob.hpp
--- a/src/misc/blob.hpp
+++ b/src/misc/blob.hpp
@@ -6,16 +6,7 @@
#define BLOB_HPP
#include "../core/alloc_func.hpp"
-
-/** Type-safe version of memcpy().
- * @param d destination buffer
- * @param s source buffer
- * @param num_items number of items to be copied (!not number of bytes!) */
-template
-FORCEINLINE void MemCpyT(Titem_* d, const Titem_* s, int num_items = 1)
-{
- memcpy(d, s, num_items * sizeof(Titem_));
-}
+#include "../core/mem_func.hpp"
/** Base class for simple binary blobs.
* Item is byte.
diff --git a/src/sortlist_type.h b/src/sortlist_type.h
--- a/src/sortlist_type.h
+++ b/src/sortlist_type.h
@@ -7,6 +7,8 @@
#include "core/enum_type.hpp"
#include "core/bitmath_func.hpp"
+#include "core/mem_func.hpp"
+#include "core/sort_func.hpp"
#include "misc/smallvec.h"
#include "date_type.h"
@@ -55,21 +57,6 @@ public: // Temporary: public for convers
this->resort_timer = DAY_TICKS * 10;
}
- /**
- * Reverse the list
- */
- void Reverse()
- {
- assert(this->IsSortable());
-
- T *a = this->data;
- T *b = a + (this->items - 1);
-
- do {
- Swap(*a, *b);
- } while (++a < --b);
- }
-
public:
GUIList() :
func_list(NULL),
@@ -174,25 +161,23 @@ public:
* Since that is the worst condition for the sort function
* reverse the list here.
*/
- FORCEINLINE void ToggleSortOrder()
+ void ToggleSortOrder()
{
this->flags ^= VL_DESC;
- if (this->IsSortable()) this->Reverse();
+ if (this->IsSortable()) MemReverseT(this->data, this->items);
}
/**
- * GnomeSort algorithm
- * This sorting uses a slightly modifyied Gnome search.
- * The basic Gnome search trys to sort already sorted
- * list parts. The modification skips these. For the first
- * sorting we use qsort since it is faster for irregular
- * sorted data.
+ * Sort the list.
+ * For the first sorting we use qsort since it is
+ * faster for irregular sorted data. After that we
+ * use gsort.
*
* @param compare The function to compare two list items
* @return true if the list sequence has been altered
* */
- FORCEINLINE bool Sort(SortFunction *compare)
+ bool Sort(SortFunction *compare)
{
/* Do not sort if the resort bit is not set */
if (!HASBITS(this->flags, VL_RESORT)) return false;
@@ -208,40 +193,12 @@ public:
if (HASBITS(this->flags, VL_FIRST_SORT)) {
CLRBITS(this->flags, VL_FIRST_SORT);
- qsort(this->data, this->items, sizeof(T), (int (CDECL *)(const void *, const void *))compare);
- if (desc) this->Reverse();
+ QSortT(this->data, this->items, compare, desc);
return true;
}
- T *a = this->data;
- T *b = a + 1;
-
- uint length = this->items;
- uint offset = 0; // Jump variable
-
- while (length > 1) {
- const int diff = compare(a, b);
- if ((!desc && diff <= 0) || (desc && diff >= 0)) {
- if (offset != 0) {
- /* Jump back to the last direction switch point */
- a += offset;
- b += offset;
- offset = 0;
- continue;
- }
- a++;
- b++;
- length--;
- } else {
- Swap(*a, *b);
- if (a != this->data) {
- offset++;
- a--;
- b--;
- }
- }
- }
+ GSortT(this->data, this->items, compare, desc);
return true;
}