Initial commit
This commit is contained in:
383
Lib/Include/ZSTL/ZSTLCommon.hpp
Normal file
383
Lib/Include/ZSTL/ZSTLCommon.hpp
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
ZSTLCommon.hpp
|
||||
Author: James Russell <jcrussell@762studios.com>
|
||||
Created: 9/13/2011
|
||||
|
||||
Purpose:
|
||||
|
||||
Common include file used by all ZSTL components.
|
||||
|
||||
License:
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What The Fuck You Want
|
||||
To Public License, Version 2, as published by Sam Hocevar. See
|
||||
http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _ZSTLCOMMON_HPP
|
||||
#define _ZSTLCOMMON_HPP
|
||||
|
||||
#include <pstdint.h> //Need this for our int types
|
||||
#include <new> //This gives us (std::nothrow)
|
||||
#include <assert.h> //This gives us assert
|
||||
#include <stdlib.h> //This gives us a definition for NULL
|
||||
|
||||
//Hash Value Type
|
||||
typedef uint64_t ZHashValue;
|
||||
|
||||
//Used to get rid of the (/W4 or -Wall) warning 'Unreferenced Formal Parameter'
|
||||
#ifndef URFP
|
||||
#define URFP(x) ((void)x)
|
||||
#endif
|
||||
|
||||
//Default allocation macro used by ZSTL default allocators
|
||||
#ifndef ZSTL_NEW
|
||||
#define ZSTL_NEW(_type) new (std::nothrow) _type()
|
||||
#endif
|
||||
|
||||
//Default delete macro used by ZSTL default allocators
|
||||
#ifndef ZSTL_DEL
|
||||
#define ZSTL_DEL(_object) delete _object
|
||||
#endif
|
||||
|
||||
//Default array allocation macro used by ZSTL default allocators
|
||||
#ifndef ZSTL_NEW_ARRAY
|
||||
#define ZSTL_NEW_ARRAY(_type, _size) new (std::nothrow) _type[_size]
|
||||
#endif
|
||||
|
||||
//Default array delete macro used by ZSTL default allocators
|
||||
#ifndef ZSTL_DEL_ARRAY
|
||||
#define ZSTL_DEL_ARRAY(_ptr, _size) ((void)_size); delete[] _ptr
|
||||
#endif
|
||||
|
||||
//Default assert macro used by ZSTL
|
||||
#ifndef ZSTL_ASSERT
|
||||
#define ZSTL_ASSERT(condition, message) (assert(condition && message))
|
||||
#endif
|
||||
|
||||
//Error condition macro used by ZSTL
|
||||
#ifndef ZSTL_ERROR
|
||||
#define ZSTL_ERROR(message) (assert(0 && message))
|
||||
#endif
|
||||
|
||||
//Swap used in array quicksort (takes array, first index, second index)
|
||||
#define ZSTL_ARRAY_ELEMENT_SWAP(_a, _i, _j) temp = _a[_j]; _a[_j] = _a[_i]; _a[_i] = temp
|
||||
|
||||
//Push used in list mergesort (takes list node and new node)
|
||||
#define ZSTL_LIST_ELEMENT_PUSH(_l, _n) if (_l == NULL) { _l = _n; } else { _l->Next = _n; _n->Previous = _l; _l = _n; }
|
||||
|
||||
/*
|
||||
public BoundsCheck<I>
|
||||
|
||||
Function that checks the provided index against the provided boundary, asserting if an
|
||||
out of bounds access occurs. Calls to this will be compiled out if ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
is not zero.
|
||||
|
||||
@param I - the type of index
|
||||
@param _index - index to check
|
||||
@param _boundary - the (exclusive) boundary to use for bounds checking
|
||||
@return (size_t) - unsigned index
|
||||
@assert - if the index is not less than boundary
|
||||
*/
|
||||
template <typename I>
|
||||
size_t BoundsCheck(I _index, I _boundary)
|
||||
{
|
||||
#if !ZSTL_DISABLE_RUNTIME_CHECKS
|
||||
ZSTL_ASSERT(_index < _boundary, "ZSTL: Out of bounds access!");
|
||||
#endif
|
||||
|
||||
return (size_t)_index;
|
||||
}
|
||||
|
||||
/*
|
||||
Node class, which is used by ZList to contain list data and previous / next pointers. Could
|
||||
be used by other classes that also need basic list-like functionality.
|
||||
|
||||
The template parameter T is the type contained by the list node.
|
||||
*/
|
||||
template <typename T>
|
||||
struct ZListNode
|
||||
{
|
||||
//Default Constructor
|
||||
ZListNode()
|
||||
: Next(NULL), Previous(NULL), Element() { }
|
||||
|
||||
//Parameterized Constructor
|
||||
ZListNode(ZListNode<T>* _next, ZListNode<T>* _previous)
|
||||
: Next(_next), Previous(_previous), Element() { }
|
||||
|
||||
//Parameterized Constructor
|
||||
ZListNode(ZListNode<T>* _next, ZListNode<T>* _previous, const T& _value)
|
||||
: Next(_next), Previous(_previous), Element(_value) { }
|
||||
|
||||
//The next node
|
||||
ZListNode* Next;
|
||||
|
||||
//The previous node
|
||||
ZListNode* Previous;
|
||||
|
||||
//The contained element
|
||||
T Element;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
Comparator functor, used when a delegate is needed to provide comparison information on
|
||||
elements. This implementation uses operator < on elements.
|
||||
|
||||
The template parameter T is the type we will be comparing to each other.
|
||||
*/
|
||||
template <typename T>
|
||||
struct ZComparator
|
||||
{
|
||||
ZComparator() { } //Silence Sun C++ warnings about uninitialized structs
|
||||
|
||||
//operator overload which returns -1 if a < b, 0 if a == b, and 1 if a > b
|
||||
int operator () (const T& _a, const T& _b) const
|
||||
{
|
||||
if (_a < _b)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (_b < _a)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Array quicksort functor. Uses a recursive in-place sort. This implementation is
|
||||
not a stable sort.
|
||||
|
||||
The template parameter T is the type contained by the array we will be sorting.
|
||||
*/
|
||||
template <typename T>
|
||||
struct ZArrayQuickSort
|
||||
{
|
||||
ZArrayQuickSort() { } //Silence Sun C++ warnings about uninitialized structs
|
||||
|
||||
//Helper function which partitions the array
|
||||
template <typename CF>
|
||||
inline size_t Partition(CF& _comparator, T* _array, size_t _left, size_t _right, size_t _pivot)
|
||||
{
|
||||
size_t i, j;
|
||||
T temp;
|
||||
|
||||
//Get the value at the pivot point
|
||||
T pivotValue = _array[_pivot];
|
||||
|
||||
//Move pivot to end
|
||||
ZSTL_ARRAY_ELEMENT_SWAP(_array, _pivot, _right);
|
||||
|
||||
//Check values from left up to pivot
|
||||
for (i = _left, j = _left; i < _right; i++)
|
||||
{
|
||||
//If less than the pivot value
|
||||
if (_comparator(_array[i], pivotValue) < 0)
|
||||
{
|
||||
//Swap back and increment our 'target' index j
|
||||
ZSTL_ARRAY_ELEMENT_SWAP(_array, i, j);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
//Move pivot to final location (all values with index < j are < pivotValue)
|
||||
ZSTL_ARRAY_ELEMENT_SWAP(_array, j, _right);
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
//Helper function which performs the sorting
|
||||
template <typename CF>
|
||||
void QuickSort(CF& _comparator, T* _array, size_t _left, size_t _right)
|
||||
{
|
||||
size_t pivot;
|
||||
|
||||
if (_right > _left)
|
||||
{
|
||||
//Center pivot point (guarded against overflow)
|
||||
pivot = _left + (_right - _left) / 2;
|
||||
|
||||
//Get our next pivot after partitioning around the current
|
||||
pivot = Partition(_comparator, _array, _left, _right, pivot);
|
||||
|
||||
//Sort the left partition
|
||||
if (pivot != 0)
|
||||
QuickSort(_comparator, _array, _left, pivot - 1);
|
||||
|
||||
//Sort the right partition
|
||||
QuickSort(_comparator, _array, pivot + 1, _right);
|
||||
}
|
||||
}
|
||||
|
||||
//Functor operator () override
|
||||
template <typename CF>
|
||||
void operator () (CF& _comparator, T* _array, size_t _size)
|
||||
{
|
||||
QuickSort(_comparator, _array, 0, _size - 1);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
List merge sort functor. This implementation is a 'stable' sort.
|
||||
|
||||
The template parameter T is the type contained by the underlying list we will be sorting.
|
||||
*/
|
||||
template <typename T>
|
||||
struct ZListMergeSort
|
||||
{
|
||||
ZListMergeSort() { } //Silence Sun C++ warnings about initialized structs
|
||||
|
||||
//Special 'Len' function which uses no end node
|
||||
inline size_t Length(ZListNode<T>* _list)
|
||||
{
|
||||
size_t i = 0;
|
||||
ZListNode<T>* node;
|
||||
|
||||
//for (i = 0, node = _list; node != NULL; i++, node = node->Next);
|
||||
|
||||
node = _list;
|
||||
while (node != NULL)
|
||||
{
|
||||
node = node->Next;
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
//Helper function which merges two lists, returns the last node
|
||||
template <typename CF>
|
||||
inline ZListNode<T>* Merge(CF& _comparator, ZListNode<T>* _left, ZListNode<T>* _right)
|
||||
{
|
||||
ZListNode<T>* merged = NULL;
|
||||
|
||||
//While left and right still have elements
|
||||
while (_left != NULL && _right != NULL)
|
||||
{
|
||||
//Compare first elements
|
||||
if (_comparator(_left->Element, _right->Element) < 0)
|
||||
{
|
||||
//Add the left element
|
||||
ZSTL_LIST_ELEMENT_PUSH(merged, _left);
|
||||
_left = _left->Next;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Add the right element
|
||||
ZSTL_LIST_ELEMENT_PUSH(merged, _right);
|
||||
_right = _right->Next;
|
||||
}
|
||||
}
|
||||
|
||||
//While the left still has elements
|
||||
while (_left != NULL)
|
||||
{
|
||||
//Add them
|
||||
ZSTL_LIST_ELEMENT_PUSH(merged, _left);
|
||||
_left = _left->Next;
|
||||
}
|
||||
|
||||
//While the right still has elements
|
||||
while (_right != NULL)
|
||||
{
|
||||
//Add them
|
||||
ZSTL_LIST_ELEMENT_PUSH(merged, _right);
|
||||
_right = _right->Next;
|
||||
}
|
||||
|
||||
//Return the end node
|
||||
return merged;
|
||||
}
|
||||
|
||||
//Helper function which merge sorts a list, returns the last node
|
||||
template <typename CF>
|
||||
inline ZListNode<T>* MergeSort(CF& _comparator, ZListNode<T>* _start)
|
||||
{
|
||||
size_t i;
|
||||
size_t middle;
|
||||
|
||||
ZListNode<T>* left;
|
||||
ZListNode<T>* right;
|
||||
|
||||
//If none or one element
|
||||
if (_start == NULL || _start->Next == NULL)
|
||||
return _start;
|
||||
|
||||
//Determine midpoint
|
||||
middle = Length(_start) / 2;
|
||||
|
||||
//Set our left and right
|
||||
left = right = _start;
|
||||
|
||||
//Set right to midpoint
|
||||
for (i = 0; i < middle; i++)
|
||||
right = right->Next;
|
||||
|
||||
//Seperate the list
|
||||
right->Previous->Next = NULL;
|
||||
right->Previous = NULL;
|
||||
|
||||
//Sort left and right recursively
|
||||
MergeSort(_comparator, left);
|
||||
MergeSort(_comparator, right);
|
||||
|
||||
//Set back our left list pointer
|
||||
while (left != NULL && left->Previous != NULL)
|
||||
left = left->Previous;
|
||||
|
||||
//Set back our right list pointer
|
||||
while (right != NULL && right->Previous != NULL)
|
||||
right = right->Previous;
|
||||
|
||||
//Return the last node from the merged lists
|
||||
return Merge(_comparator, left, right);
|
||||
}
|
||||
|
||||
//Functor operator () override
|
||||
template <typename CF>
|
||||
void operator () (CF& _comparator, ZListNode<T>* _start, ZListNode<T>* _end)
|
||||
{
|
||||
ZListNode<T>* prev;
|
||||
|
||||
//Check to see if list is empty
|
||||
if (_start == _end)
|
||||
return;
|
||||
|
||||
//Get the node before the starting node
|
||||
prev = _start->Previous;
|
||||
|
||||
//Split the end node off
|
||||
_end->Previous->Next = NULL;
|
||||
_start->Previous = NULL;
|
||||
//Reset the end node back
|
||||
_end->Previous = MergeSort(_comparator, _start);
|
||||
|
||||
//Attach
|
||||
_end->Previous->Next = _end;
|
||||
|
||||
//Reattach the node before _start
|
||||
if (prev != NULL)
|
||||
{
|
||||
ZListNode<T>* current = _end;
|
||||
|
||||
while (current->Previous != NULL)
|
||||
current = current->Previous;
|
||||
|
||||
current->Previous = prev;
|
||||
prev->Next = current;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user