mirror of https://github.com/OpenTTD/OpenTTD
(svn r13516) -Codechange: Move MemCpyT to a fitting core header
-Codechange: Split the sorting code from the sortlist to an appropriate headerrelease/0.7
parent
bf9a32b475
commit
96fc91baf3
|
@ -1123,6 +1123,10 @@
|
||||||
RelativePath=".\..\src\md5.h"
|
RelativePath=".\..\src\md5.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\core\mem_func.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\minilzo.h"
|
RelativePath=".\..\src\minilzo.h"
|
||||||
>
|
>
|
||||||
|
@ -1443,6 +1447,10 @@
|
||||||
RelativePath=".\..\src\slope_type.h"
|
RelativePath=".\..\src\slope_type.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\core\sort_func.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\sortlist_type.h"
|
RelativePath=".\..\src\sortlist_type.h"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1120,6 +1120,10 @@
|
||||||
RelativePath=".\..\src\md5.h"
|
RelativePath=".\..\src\md5.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\core\mem_func.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\minilzo.h"
|
RelativePath=".\..\src\minilzo.h"
|
||||||
>
|
>
|
||||||
|
@ -1440,6 +1444,10 @@
|
||||||
RelativePath=".\..\src\slope_type.h"
|
RelativePath=".\..\src\slope_type.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\core\sort_func.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\sortlist_type.h"
|
RelativePath=".\..\src\sortlist_type.h"
|
||||||
>
|
>
|
||||||
|
|
|
@ -206,6 +206,7 @@ map_func.h
|
||||||
map_type.h
|
map_type.h
|
||||||
core/math_func.hpp
|
core/math_func.hpp
|
||||||
md5.h
|
md5.h
|
||||||
|
core/mem_func.hpp
|
||||||
minilzo.h
|
minilzo.h
|
||||||
mixer.h
|
mixer.h
|
||||||
music.h
|
music.h
|
||||||
|
@ -286,6 +287,7 @@ signs_func.h
|
||||||
signs_type.h
|
signs_type.h
|
||||||
slope_func.h
|
slope_func.h
|
||||||
slope_type.h
|
slope_type.h
|
||||||
|
core/sort_func.hpp
|
||||||
sortlist_type.h
|
sortlist_type.h
|
||||||
sound_func.h
|
sound_func.h
|
||||||
sound_type.h
|
sound_type.h
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/** @file mem_func.hpp Functions related to memory operations. */
|
||||||
|
|
||||||
|
#ifndef MEM_FUNC_HPP
|
||||||
|
#define MEM_FUNC_HPP
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#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 <typename T>
|
||||||
|
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<typename T>
|
||||||
|
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<typename T>
|
||||||
|
FORCEINLINE void MemReverseT(T *ptr, uint num)
|
||||||
|
{
|
||||||
|
assert(ptr != NULL);
|
||||||
|
|
||||||
|
MemReverseT(ptr, ptr + (num - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MEM_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 <stdlib.h>
|
||||||
|
#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<typename T>
|
||||||
|
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<typename T>
|
||||||
|
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 */
|
|
@ -6,16 +6,7 @@
|
||||||
#define BLOB_HPP
|
#define BLOB_HPP
|
||||||
|
|
||||||
#include "../core/alloc_func.hpp"
|
#include "../core/alloc_func.hpp"
|
||||||
|
#include "../core/mem_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 <class Titem_>
|
|
||||||
FORCEINLINE void MemCpyT(Titem_* d, const Titem_* s, int num_items = 1)
|
|
||||||
{
|
|
||||||
memcpy(d, s, num_items * sizeof(Titem_));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Base class for simple binary blobs.
|
/** Base class for simple binary blobs.
|
||||||
* Item is byte.
|
* Item is byte.
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include "core/enum_type.hpp"
|
#include "core/enum_type.hpp"
|
||||||
#include "core/bitmath_func.hpp"
|
#include "core/bitmath_func.hpp"
|
||||||
|
#include "core/mem_func.hpp"
|
||||||
|
#include "core/sort_func.hpp"
|
||||||
#include "misc/smallvec.h"
|
#include "misc/smallvec.h"
|
||||||
#include "date_type.h"
|
#include "date_type.h"
|
||||||
|
|
||||||
|
@ -55,21 +57,6 @@ public: // Temporary: public for conversion only
|
||||||
this->resort_timer = DAY_TICKS * 10;
|
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:
|
public:
|
||||||
GUIList() :
|
GUIList() :
|
||||||
func_list(NULL),
|
func_list(NULL),
|
||||||
|
@ -174,25 +161,23 @@ public:
|
||||||
* Since that is the worst condition for the sort function
|
* Since that is the worst condition for the sort function
|
||||||
* reverse the list here.
|
* reverse the list here.
|
||||||
*/
|
*/
|
||||||
FORCEINLINE void ToggleSortOrder()
|
void ToggleSortOrder()
|
||||||
{
|
{
|
||||||
this->flags ^= VL_DESC;
|
this->flags ^= VL_DESC;
|
||||||
|
|
||||||
if (this->IsSortable()) this->Reverse();
|
if (this->IsSortable()) MemReverseT(this->data, this->items);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GnomeSort algorithm
|
* Sort the list.
|
||||||
* This sorting uses a slightly modifyied Gnome search.
|
* For the first sorting we use qsort since it is
|
||||||
* The basic Gnome search trys to sort already sorted
|
* faster for irregular sorted data. After that we
|
||||||
* list parts. The modification skips these. For the first
|
* use gsort.
|
||||||
* sorting we use qsort since it is faster for irregular
|
|
||||||
* sorted data.
|
|
||||||
*
|
*
|
||||||
* @param compare The function to compare two list items
|
* @param compare The function to compare two list items
|
||||||
* @return true if the list sequence has been altered
|
* @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 */
|
/* Do not sort if the resort bit is not set */
|
||||||
if (!HASBITS(this->flags, VL_RESORT)) return false;
|
if (!HASBITS(this->flags, VL_RESORT)) return false;
|
||||||
|
@ -208,40 +193,12 @@ public:
|
||||||
|
|
||||||
if (HASBITS(this->flags, VL_FIRST_SORT)) {
|
if (HASBITS(this->flags, VL_FIRST_SORT)) {
|
||||||
CLRBITS(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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *a = this->data;
|
GSortT(this->data, this->items, compare, desc);
|
||||||
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--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue