Changeset - r9366:1f0aaef04f68
[Not reviewed]
master
0 1 0
skidd13 - 16 years ago 2008-05-26 16:44:48
skidd13@openttd.org
(svn r13267) -Codechange: extend GUIList with a GnomeSort
1 file changed with 244 insertions and 4 deletions:
0 comments (0 inline, 0 general)
src/sortlist_type.h
Show inline comments
 
@@ -6,6 +6,7 @@
 
#define SORTLIST_TYPE_H
 

	
 
#include "misc/smallvec.h"
 
#include "date_type.h"
 

	
 
enum SortListFlags {
 
	VL_NONE    = 0,      ///< no sort
 
@@ -22,10 +23,249 @@ struct Listing {
 
};
 

	
 
template <typename T>
 
struct GUIList : public SmallVector<T, 32> {
 
	SortListFlags flags; ///< used to control sorting/resorting/etc.
 
	uint16 resort_timer; ///< resort list after a given amount of ticks if set
 
	byte sort_type;      ///< what criteria to sort on
 
class GUIList : public SmallVector<T, 32> {
 
public:
 
	typedef int SortFunction(const T*, const T*);
 

	
 
public: // Temporary: public for conversion only
 
	SortFunction* const *func_list; ///< The sort criteria functions
 
	SortListFlags flags;            ///< used to control sorting/resorting/etc.
 
	uint8 sort_type;                ///< what criteria to sort on
 
	uint16 resort_timer;            ///< resort list after a given amount of ticks if set
 

	
 
	/**
 
	 * Check if the list is sortable
 
	 *
 
	 * @return true if we can sort the list
 
	 */
 
	bool IsSortable() const
 
	{
 
		return (this->data != NULL && this->items > 2);
 
	}
 

	
 
	/**
 
	 * Reset the resort timer
 
	 */
 
	void ResetResortTimer()
 
	{
 
		/* Resort every 10 days */
 
		this->resort_timer = DAY_TICKS * 10;
 
	}
 

	
 
public:
 
	GUIList() :
 
		func_list(NULL),
 
		flags(VL_NONE),
 
		sort_type(0),
 
		resort_timer(1)
 
	{};
 

	
 
	/**
 
	 * Get the sorttype of the list
 
	 *
 
	 * @return The current sorttype
 
	 */
 
	uint8 SortType() const
 
	{
 
		return this->sort_type;
 
	}
 

	
 
	/**
 
	 * Set the sorttype of the list
 
	 *
 
	 * @param n_type the new sort type
 
	 */
 
	void SetSortType(uint8 n_type)
 
	{
 
		if (this->sort_type != n_type) {
 
			SETBITS(this->flags, VL_RESORT);
 
			this->sort_type = n_type;
 
		}
 
	}
 

	
 
	/**
 
	 * Export current sort conditions
 
	 *
 
	 * @return the current sort conditions
 
	 */
 
	Listing GetListing() const
 
	{
 
		Listing l;
 
		l.order = HASBITS(this->flags, VL_DESC);
 
		l.criteria = this->sort_type;
 

	
 
		return l;
 
	}
 

	
 
	/**
 
	 * Import sort conditions
 
	 *
 
	 * @param l The sport conditions we want to use
 
	 */
 
	void SetListing(Listing l)
 
	{
 
		if (l.order) {
 
			SETBITS(this->flags, VL_DESC);
 
		} else {
 
			CLRBITS(this->flags, VL_DESC);
 
		}
 
		this->sort_type = l.criteria;
 
	}
 

	
 
	/**
 
	 * Check if a resort is needed next loop
 
	 *  If used the resort timer will decrease every call
 
	 *  till 0. If 0 reached the resort bit will be set and
 
	 *  the timer will be reset.
 
	 *
 
	 * @return true if resort bit is set for next loop
 
	 */
 
	bool NeedResort()
 
	{
 
		if (--this->resort_timer == 0) {
 
			SETBITS(this->flags, VL_RESORT);
 
			this->ResetResortTimer();
 
			return true;
 
		}
 
		return false;
 
	}
 

	
 
	/**
 
	 * Force a resort next Sort call
 
	 *  Reset the resort timer if used too.
 
	 */
 
	void ForceResort()
 
	{
 
		SETBITS(this->flags, VL_RESORT);
 
	}
 

	
 
	/**
 
	 * Check if the sort order is descending
 
	 *
 
	 * @return true if the sort order is descending
 
	 */
 
	bool IsDescSortOrder() const
 
	{
 
		return HASBITS(this->flags, VL_DESC);
 
	}
 

	
 
	/**
 
	 * Toogle the sort order
 
	 *  Since that is the worst condition for the sort function
 
	 *  reverse the list here.
 
	 */
 
	FORCEINLINE void ToggleSortOrder()
 
	{
 
		this->flags ^= VL_DESC;
 

	
 
		if (this->IsSortable()) {
 
			T *a = this->data;
 
			T *b = a + (this->items - 1);
 

	
 
			do {
 
				Swap(*a, *b);
 
			} while (((a + 1) != b) && (++a != --b));
 
		}
 
	}
 

	
 
	/**
 
	 * 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.
 
	 *
 
	 * @param compare The function to compare two list items
 
	 * */
 
	FORCEINLINE void Sort(SortFunction compare)
 
	{
 
		/* Do not sort when the list is not sortable */
 
		if (!this->IsSortable()) return;
 

	
 
		/* Do not sort if the resort bit is not set */
 
		if (!HASBITS(this->flags, VL_RESORT)) return;
 

	
 
		T *a = this->data;
 
		T *b = a + 1;
 

	
 
		uint length = this->items;
 
		uint offset = 0; // Jump variable
 
		const bool desc = HASBITS(this->flags, VL_DESC);
 

	
 
		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--;
 
				}
 
			}
 
		}
 

	
 
		this->ResetResortTimer();
 

	
 
		CLRBITS(this->flags, VL_RESORT);
 
	}
 

	
 
	/**
 
	 * Hand the array of sort function pointers to the sort list
 
	 *
 
	 * @param n_funcs The pointer to the first sort func
 
	 */
 
	void SetSortFuncs(SortFunction* const* n_funcs)
 
	{
 
		this->func_list = n_funcs;
 
	}
 

	
 
	/**
 
	 * Overload of Sort()
 
	 * Overloaded to reduce external code
 
	 */
 
	void Sort()
 
	{
 
		assert(this->func_list != NULL);
 
		this->Sort(this->func_list[this->sort_type]);
 
	}
 

	
 
	/**
 
	 * Check if a rebuild is needed
 
	 * @return true if a rebuild is needed
 
	 */
 
	bool NeedRebuild() const
 
	{
 
		return HASBITS(this->flags, VL_REBUILD);
 
	}
 

	
 
	/**
 
	 * Force that a rebuild is needed
 
	 */
 
	void ForceRebuild()
 
	{
 
		SETBITS(this->flags, VL_REBUILD);
 
	}
 

	
 
	/**
 
	 * Notify the sortlist that the rebuild is done
 
	 *
 
	 * @note This forces a resort
 
	 */
 
	void RebuildDone()
 
	{
 
		CLRBITS(this->flags, VL_REBUILD);
 
		SETBITS(this->flags, VL_RESORT);
 
	}
 
};
 

	
 
#endif /* SORTLIST_TYPE_H */
0 comments (0 inline, 0 general)