merging MiscBranch into Physics with conflict fixes

This commit is contained in:
Dander7BD 2013-11-28 14:52:13 +01:00
parent 4672984b51
commit d241298308
9 changed files with 1581 additions and 0 deletions

View File

@ -0,0 +1,65 @@
#include "..\OResource.h"
#include "..\..\Utilities.h"
#include <fstream>
using namespace Oyster::Resource;
OResource* OResource::CustomLoader(const wchar_t filename[], CustomLoadFunction fnc)
{
<<<<<<< HEAD
const CustomData &data = fnc();
=======
CustomData data;
memset(&data, 0, sizeof(CustomData));
fnc(filename, data);
if(!data.loadedData)
{
return 0;
}
if(!data.resourceUnloadFnc)
{
return 0;
}
/** For some wierd reason that i don't understand when trying to send data.loadedData directly as a
* parameter to OResource constructor, the value is changed when it arrives in the constructor.
* Doing it like this, storing in a temporary variable, the value stays correct. (What the fuck! I must be overloking something...)*/
//OHRESOURCE temp = data.loadedData;
OResource *resource = new OResource(data.loadedData, ResourceType_UNKNOWN, 0, 0, filename);
>>>>>>> origin/MiscBranch
resource->customData = new CustomResourceData();
resource->customData->unloadingFunction = data.resourceUnloadFnc;
resource->customData->loadingFunction = fnc;
return resource;
}
void OResource::CustomUnloader()
{
this->customData->unloadingFunction(this->resourceData);
}
OResource* OResource::CustomReloader()
{
CustomUnloader();
<<<<<<< HEAD
const CustomData &data = this->customData->loadingFunction();
=======
CustomData data;
memset(&data, 0, sizeof(CustomData));
this->customData->loadingFunction(this->resourceFilename.c_str(), data);
>>>>>>> origin/MiscBranch
this->resourceData = (OHRESOURCE)data.loadedData;
if(data.resourceUnloadFnc)
{
this->customData->unloadingFunction = data.resourceUnloadFnc;
}
return this;
}

View File

@ -0,0 +1,258 @@
/////////////////////////////////////////////////////////////////////
// Created by [Dennis Andersen] [2013]
/////////////////////////////////////////////////////////////////////
#include "OysterResource.h"
#include "OResource.h"
#include <string>
#include <map>
using namespace Oyster::Resource;
class ResourcePrivate
{
public:
std::map<std::wstring, OResource*> resources;
OResource* FindResource(const OHRESOURCE& h) const;
OResource* FindResource(const wchar_t c[]) const;
void SaveResource(OResource* r, bool addNew = true);
} resourcePrivate;
OHRESOURCE OysterResource::LoadResource(const wchar_t* filename, ResourceType type, int customID, bool force)
{
if(!filename) return 0;
OResource *resourceData = resourcePrivate.FindResource(filename);
if(resourceData)
{
if(force)
{
return OysterResource::ReloadResource(filename);
}
else
{
//Add new reference
resourcePrivate.SaveResource(resourceData, false);
return resourceData->GetResourceHandle();
}
}
else
{
resourceData = OResource::Load(filename, type);
if(resourceData)
{
resourceData->SetResourceID(customID);
resourcePrivate.SaveResource(resourceData);
}
}
return resourceData->GetResourceHandle();
}
OHRESOURCE OysterResource::LoadResource(const wchar_t filename[], CustomLoadFunction loadFnc, int customId, bool force)
{
if(!filename)
{
return 0;
}
if(!loadFnc)
{
return 0;
}
OResource *resourceData = resourcePrivate.FindResource(filename);
if(resourceData)
{
if(force)
{
return OysterResource::ReloadResource(filename);
}
else
{
//Add new reference
resourcePrivate.SaveResource(resourceData, false);
return resourceData->GetResourceHandle();
}
}
else
{
resourceData = OResource::Load(filename, loadFnc);
if(resourceData)
{
resourceData->SetResourceID(customId);
resourcePrivate.SaveResource(resourceData);
}
}
<<<<<<< HEAD
resourceData = OResource::Load(filename, loadFnc);
if(!resourceData) return 0;
if(resourceData) resourceData->SetResourceID(CustomId);
resourcePrivate.SaveResource(resourceData);
=======
>>>>>>> origin/MiscBranch
return (OHRESOURCE)resourceData->GetResourceHandle();
}
OHRESOURCE OysterResource::ReloadResource(const wchar_t filename[])
{
OResource *resourceData = resourcePrivate.FindResource(filename);
if(!resourceData) return 0; //The resource has not been loaded
return OResource::Reload(resourceData)->GetResourceHandle();
}
OHRESOURCE OysterResource::ReloadResource(OHRESOURCE resource)
{
OResource *resourceData = resourcePrivate.FindResource(resource);
if(!resourceData) return 0; //The resource has not been loaded
return OResource::Reload(resourceData)->GetResourceHandle();
}
void OysterResource::Clean()
{
auto i = resourcePrivate.resources.begin();
auto last = resourcePrivate.resources.end();
for (i; i != last; i++)
{
//Remove all the references
while (!OResource::Release(i->second));
const wchar_t* temp = i->second->GetResourceFilename();
delete resourcePrivate.resources[temp];
resourcePrivate.resources.erase(temp);
}
}
void OysterResource::ReleaseResource(const OHRESOURCE& resourceData)
{
OResource* t = resourcePrivate.FindResource(resourceData);
if(t)
{
if(OResource::Release(t))
{
const wchar_t* temp = t->GetResourceFilename();
delete resourcePrivate.resources[temp];
resourcePrivate.resources.erase(temp);
}
}
}
void OysterResource::ReleaseResource(const wchar_t filename[])
{
OResource* t = resourcePrivate.FindResource(filename);
if(t)
{
if(OResource::Release(t))
{
const wchar_t* temp = t->GetResourceFilename();
delete resourcePrivate.resources[temp];
resourcePrivate.resources.erase(temp);
}
}
}
void OysterResource::SetResourceId (const OHRESOURCE& resourceData, unsigned int id)
{
OResource* t = resourcePrivate.FindResource(resourceData);
if(t) t->SetResourceID(id);
}
void OysterResource::SetResourceId(const wchar_t c[], unsigned int id)
{
OResource* t = resourcePrivate.FindResource(c);
if(t) t->SetResourceID(id);
}
ResourceType OysterResource::GetResourceType (const OHRESOURCE& resourceData)
{
OResource* t = resourcePrivate.FindResource(resourceData);
if(t) return t->GetResourceType();
return ResourceType_INVALID;
}
ResourceType OysterResource::GetResourceType (const wchar_t c[])
{
OResource* t = resourcePrivate.FindResource(c);
if(t) return t->GetResourceType();
return ResourceType_INVALID;
}
const wchar_t* OysterResource::GetResourceFilename (const OHRESOURCE& resourceData)
{
OResource* t = resourcePrivate.FindResource(resourceData);
if(t) return t->GetResourceFilename();
return 0;
}
OHRESOURCE OysterResource::GetResourceHandle(const wchar_t filename[])
{
OResource* t = resourcePrivate.FindResource(filename);
if(t) return t->GetResourceHandle();
return 0;
}
int OysterResource::GetResourceId (const OHRESOURCE& resourceData)
{
OResource* t = resourcePrivate.FindResource(resourceData);
if(t) return t->GetResourceID();
return -1;
}
int OysterResource::GetResourceId(const wchar_t c[])
{
OResource* t = resourcePrivate.FindResource(c);
if(t) return t->GetResourceID();
return -1;
}
OResource* ResourcePrivate::FindResource(const OHRESOURCE& h) const
{
for (auto i = this->resources.begin(); i != this->resources.end() ; i++)
{
if(i->second->GetResourceHandle() == h)
{
return i->second;
}
}
return 0;
}
OResource* ResourcePrivate::FindResource(const wchar_t c[]) const
{
std::wstring temp = c;
auto t = this->resources.find(c);
if(t == this->resources.end()) return 0;
return t->second;
}
void ResourcePrivate::SaveResource( OResource* r, bool addNew )
{
if(!r) return;
if(addNew)
{
this->resources[r->GetResourceFilename()] = r;
}
r->resourceRef.Incref();
}

View File

@ -0,0 +1,164 @@
/////////////////////////////////////////////////////////////////////
// Created by [Dennis Andersen] [2013]
/////////////////////////////////////////////////////////////////////
#ifndef MISC_OYSTER_RESOURCE_H
#define MISC_OYSTER_RESOURCE_H
namespace Oyster
{
namespace Resource
{
struct CustomData;
/** A Resource handle representing various resources */
<<<<<<< HEAD
typedef unsigned long OHRESOURCE;
typedef void(*CustomUnloadFunction)(void*);
typedef const CustomData&(*CustomLoadFunction)();
=======
typedef void* OHRESOURCE;
/** Typedef on a fuction required for custom unloading */
typedef void(*CustomUnloadFunction)(void* loadedData);
/** Typedef on a fuction required for custom loading */
typedef void(*CustomLoadFunction)(const wchar_t filename[], CustomData& outData);
>>>>>>> origin/MiscBranch
/** An enum class representing all avalible resources that is supported. */
enum ResourceType
{
//Byte
ResourceType_Byte_Raw, /**< Handle can be interpeted as char[] or char* */
ResourceType_Byte_ANSI, /**< Handle can be interpeted as char[] or char* */
ResourceType_Byte_UTF8, /**< Handle can be interpeted as char[] or char* */
ResourceType_Byte_UNICODE, /**< Handle can be interpeted as char[] or char* */
ResourceType_Byte_UTF16LE, /**< Handle can be interpeted as char[] or char* */
ResourceType_COUNT, /**< Handle can be interpeted as ? */
ResourceType_UNKNOWN = -1, /**< Handle can be interpeted as void* */
ResourceType_INVALID = -2, /**< Invalid or non existing resource */
};
/** A struct to fill when doing a custom resource Load. */
struct CustomData
{
void* loadedData; //<! The loaded resource interpeted as a void*.
CustomUnloadFunction resourceUnloadFnc; //<! The function that will be used to free the resource when needed.
};
/** A resource handler interface to interact with when loading resources.
* The resource handler uses the filename to make resources unuiqe.
*/
class OysterResource
{
public:
/**
* Load a resource given a type.
* @param filename The path to the resource.
* @param type The resource type to load.
* @param force If set to true, the resource will be reloaded if it already exists. If it does not, nothing happens.
* @return If function suceeds, a handle to the resource will be returned. If failed 0 is returned.
*/
static OHRESOURCE LoadResource(const wchar_t filename[], ResourceType type, int customId = -1, bool force = false);
/**
* Load a resource with a custom loading function
* @param filename The path to the resource.
* @param loadFnc If set, this gives you the right to do custom resource loading if your recource type is not supported.
* @param customId A custom ID that can be used.
* @param force If set to true, the resource will be reloaded even if exists.
* @return If function suceeds, a handle to the resource will be returned. If failed 0 is returned.
*/
static OHRESOURCE LoadResource(const wchar_t filename[], CustomLoadFunction loadFnc = 0, int customId = -1, bool force = false);
/**
* Reload a resource
* @param filename The path to the resource.
* @return If function suceeds, a handle to the resource will be returned. If failed 0 is returned.
*/
static OHRESOURCE ReloadResource(const wchar_t filename[]);
/**
* Reload a resource
* @param filename The path to the resource.
* @return If function suceeds, a handle to the resource will be returned. If failed 0 is returned.
*/
static OHRESOURCE ReloadResource(OHRESOURCE resource);
/**
* Releases all resources loaded by the resource handler.
* @return Nothing
*/
static void Clean();
/**
* Release a reference to the resource handle
* @param resource The handle to release.
* @return Nothing
*/
static void ReleaseResource(const OHRESOURCE& resource);
/**
* Release a reference to the resource handle
* @param resource The resource filename to release reference.
* @return Nothing
*/
static void ReleaseResource(const wchar_t filename[]);
/** Set a user defined ID
* @param resource A handle to accociate the id with.
* @param id A user defined identifier that the resource handler does not touch.
*/
static void SetResourceId(const OHRESOURCE& resource, unsigned int id);
/** Set a user defined ID
* If the resource is not loaded the id will not be set.
* @param resource A filename to accociate the id with.
* @param id A user defined identifier that the resource handler does not touch.
*/
static void SetResourceId(const wchar_t filename[], unsigned int id);
/** Get a resource type given a OHRESOURCE handle
* @param resource The handle to check
* @return Returns the resource type of the handle
*/
static ResourceType GetResourceType(const OHRESOURCE& resource);
/** Get a resource type given a filename
* If the resource is not loaded the id will not be set.
* @param resource The filename to check
* @return Returns the resource type of the handle
*/
static ResourceType GetResourceType (const wchar_t filename[]);
/** Get a resource filename given a OHRESOURCE handle
* @param resource The handle to check
* @return Returns the accociated filename
*/
static const wchar_t* GetResourceFilename(const OHRESOURCE& resource);
/** Get a resource handle given a filename
* If the resource is not loaded function returns 0.
* @param resource The filename to check
* @return Returns the accociated handle
*/
static OHRESOURCE GetResourceHandle(const wchar_t filename[]);
/** Get a user defined ID accociated with a handle
* @param resource The handle to check
* @return Returns the accociated ID
*/
static int GetResourceId(const OHRESOURCE& resource);
/** Get a user defined ID accociated with a filename
* @param resource The filename to check
* @return Returns the accociated ID
*/
static int GetResourceId(const wchar_t filename[]);
};
}
}
#endif

View File

@ -0,0 +1,67 @@
/////////////////////////////////////////////////////////////////////
// Created by [Dennis Andersen] [2013]
/////////////////////////////////////////////////////////////////////
#include "OysterMutex.h"
#include <chrono>
#include <thread>
#include <future>
using namespace Oyster::Thread;
OysterMutex::OysterMutex()
{}
OysterMutex::OysterMutex(bool initialOwnership)
{
if(initialOwnership)
{
this->mutex.lock();
this->id = std::this_thread::get_id();
}
}
OysterMutex::~OysterMutex()
{
}
void OysterMutex::LockMutex()
{
if(std::this_thread::get_id() == this->id) return;
this->mutex.lock();
this->id = std::this_thread::get_id();
}
void OysterMutex::LockMutex(unsigned int msec)
{
if(std::this_thread::get_id() == this->id) return;
auto start = std::chrono::high_resolution_clock::now();
auto end = start + std::chrono::milliseconds(msec);
do
{
if(this->mutex.try_lock())
{
this->mutex.lock();
this->id = std::this_thread::get_id();
return;
}
} while (std::chrono::high_resolution_clock::now() < end);
this->mutex.lock();
}
void OysterMutex::UnlockMutex()
{
//Let the owner unlock
if(std::this_thread::get_id() != this->id) return;
this->mutex.unlock();
this->id = std::thread::id();
}
bool OysterMutex::IsTaken()
{
return !this->mutex.try_lock();
}

View File

@ -0,0 +1,37 @@
/////////////////////////////////////////////////////////////////////
// Created by [Dennis Andersen] [2013]
/////////////////////////////////////////////////////////////////////
#ifndef MISC_OYSTER_MUTEX_H
#define MISC_OYSTER_MUTEX_H
#include <mutex>
#include <thread>
#include <atomic>
namespace Oyster
{
namespace Thread
{
class OysterMutex
{
public:
OysterMutex();
OysterMutex(bool initialOwnership);
virtual~OysterMutex();
void LockMutex();
void LockMutex(unsigned int timeSpan);
void UnlockMutex();
/** Returns true if mutex is taken */
bool IsTaken();
private:
std::mutex mutex;
std::thread::id id;
OysterMutex(const OysterMutex&);
};
}
}
#endif // !MISC_OYSTER_MUTEX_H

View File

@ -0,0 +1,47 @@
/////////////////////////////////////////////////////////////////////
// Created by [Dennis Andersen] [2013]
/////////////////////////////////////////////////////////////////////
#ifndef MISC_OYSTER_THREAD_H
#define MISC_OYSTER_THREAD_H
#include "IThreadObject.h"
namespace Oyster
{
namespace Thread
{
enum OYSTER_THREAD_ERROR
{
OYSTER_THREAD_ERROR_FAILED,
OYSTER_THREAD_ERROR_SUCCESS,
};
class OysterThread
{
private:
struct PrivateData;
PrivateData *privateData;
public:
OysterThread();
OysterThread(const OysterThread& original);
const OysterThread& operator=(const OysterThread& original);
virtual~OysterThread();
OYSTER_THREAD_ERROR Create(IThreadObject* worker, bool start);
OYSTER_THREAD_ERROR Start();
void Stop();
void Pause();
void Pause(int mSec);
void Resume();
OYSTER_THREAD_ERROR Reset(IThreadObject* worker = 0);
void Terminate();
void Wait();
void Wait(int mSec);
OYSTER_THREAD_ERROR Swap(const OysterThread* other);
bool IsActive();
};
}
}
#endif // !MISC_OYSTER_THREAD_H

View File

@ -0,0 +1,281 @@
/////////////////////////////////////////////////////////////////////
// Created by [Dennis Andersen] [2013]
/////////////////////////////////////////////////////////////////////
#include "OysterThread.h"
#include "OysterMutex.h"
#include "..\Utilities.h"
#include <thread>
#include <assert.h>
#include <atomic>
using namespace Oyster::Thread;
using namespace Utility::DynamicMemory::SmartPointer;
#pragma region Declerations
struct ThreadData;
/** A typical Oyster thread function */
typedef void (*ThreadFunction)(StdSmartPointer<ThreadData>&);
enum OYSTER_THREAD_STATE
{
OYSTER_THREAD_STATE_RESET,
OYSTER_THREAD_STATE_RUNNING,
OYSTER_THREAD_STATE_PAUSED,
OYSTER_THREAD_STATE_STOPED,
OYSTER_THREAD_STATE_DEAD,
};
struct ThreadData
{
std::atomic<OYSTER_THREAD_STATE> state; //<! The current thread state.
//OYSTER_THREAD_STATE state; //<! The current thread state.
StdSmartPointer<std::thread> workerThread; //<! The worker thread.
std::thread::id callingThread; //<! The owner thread.
IThreadObject *owner; //<! The owner of the thread as IThread.
std::atomic<int> msec; //<! A timer in miliseconds.
//OysterMutex mutexLock; //<! The lock, locking the member variabls.
ThreadData() {}
~ThreadData() {}
ThreadData(const ThreadData&) {};
};
struct OysterThread::PrivateData
{
StdSmartPointer<ThreadData> threadData;
PrivateData()
:threadData(new ThreadData())
{
threadData->owner = 0;
threadData->workerThread = 0;
threadData->callingThread;
threadData->state = OYSTER_THREAD_STATE_STOPED;
}
PrivateData(const PrivateData& o)
{
threadData = o.threadData;
}
~PrivateData()
{
//@todo TODO: Make detatch avalible.
this->threadData->workerThread->detach();
this->threadData->owner = 0;
this->threadData->state = OYSTER_THREAD_STATE_DEAD;
}
};
#pragma endregion
int tempId = 0;
std::vector<int> IDS;
static void ThreadingFunction(StdSmartPointer<ThreadData> &origin)
{
bool shouldContinue;
StdSmartPointer<ThreadData> w = origin;
theBegining:
while(w->state == OYSTER_THREAD_STATE_STOPED)
{
std::this_thread::yield();
}
// w->mutexLock.LockMutex();
if(w->owner)
{
w->owner->ThreadEntry();
}
// w->mutexLock.UnlockMutex();
while (w->state != OYSTER_THREAD_STATE_STOPED && w->state != OYSTER_THREAD_STATE_DEAD)
{
// w->mutexLock.LockMutex();
{
if(w->owner)
{
shouldContinue = w->owner->DoWork();
}
}
// w->mutexLock.UnlockMutex();
if(!shouldContinue)
{
goto theEnd;
}
if(w->state == OYSTER_THREAD_STATE_DEAD)
{
goto theEnd;
}
else if(w->state == OYSTER_THREAD_STATE_RESET)
{
goto theBegining;
}
else if(w->msec > 0)
{
std::this_thread::sleep_for(std::chrono::milliseconds(w->msec));
}
while (w->state == OYSTER_THREAD_STATE_PAUSED)
{
std::this_thread::yield();
}
}
if(w->state == OYSTER_THREAD_STATE_DEAD)
{
w->workerThread->detach();
return;
}
theEnd:
// w->mutexLock.LockMutex();
if(w->owner)
{
w->owner->ThreadExit();
}
// w->mutexLock.UnlockMutex();
w->state = OYSTER_THREAD_STATE_DEAD;
}
OysterThread::OysterThread()
{
this->privateData = new PrivateData();
}
OysterThread::OysterThread(const OysterThread& original)
{
this->privateData = new PrivateData(*original.privateData);
}
const OysterThread& OysterThread::operator=(const OysterThread& original)
{
return *this;
}
OysterThread::~OysterThread()
{
delete this->privateData;
this->privateData = 0;
}
OYSTER_THREAD_ERROR OysterThread::Create(IThreadObject* worker, bool start)
{
if(!this->privateData) return OYSTER_THREAD_ERROR_FAILED;
if(this->privateData->threadData->workerThread) return OYSTER_THREAD_ERROR_FAILED;
this->privateData->threadData->owner = worker;
ThreadFunction fnc = ThreadingFunction;
//Maby move this thread creation to a seperate Start() function because std::thread fires the thread when it is created. :(
this->privateData->threadData->workerThread = new std::thread(fnc, this->privateData->threadData);
if(!this->privateData->threadData->workerThread)
return OYSTER_THREAD_ERROR_FAILED;
if(start)
{
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
}
return OYSTER_THREAD_ERROR_SUCCESS;
}
OYSTER_THREAD_ERROR OysterThread::Start()
{
if(!this->privateData->threadData->owner)
return OYSTER_THREAD_ERROR_FAILED;
if(!this->privateData->threadData->workerThread)
return OYSTER_THREAD_ERROR_FAILED;
if(this->privateData->threadData->state == OYSTER_THREAD_STATE_DEAD)
return OYSTER_THREAD_ERROR_FAILED;
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
return OYSTER_THREAD_ERROR_SUCCESS;
}
void OysterThread::Stop()
{
//this->privateData->threadData->mutexLock.LockMutex();
this->privateData->threadData->state = OYSTER_THREAD_STATE_STOPED;
//this->privateData->threadData->mutexLock.UnlockMutex();
}
void OysterThread::Pause()
{
//this->privateData->threadData->mutexLock.LockMutex();
this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED;
//this->privateData->threadData->mutexLock.UnlockMutex();
}
void OysterThread::Pause(int msec)
{
if(std::this_thread::get_id() == this->privateData->threadData->workerThread->get_id())
{
this->privateData->threadData->msec = msec;
}
else
{
//this->privateData->threadData->mutexLock.LockMutex();
this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED;
this->privateData->threadData->msec = msec;
//this->privateData->threadData->mutexLock.UnlockMutex();
}
}
void OysterThread::Resume()
{
// this->privateData->threadData->mutexLock.LockMutex();
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
// this->privateData->threadData->mutexLock.UnlockMutex();
}
OYSTER_THREAD_ERROR OysterThread::Reset(IThreadObject* worker)
{
// this->privateData->threadData->mutexLock.LockMutex();
if(worker)
{
this->privateData->threadData->owner = worker;
}
this->privateData->threadData->callingThread = std::this_thread::get_id();
this->privateData->threadData->msec = 0;
// this->privateData->threadData->mutexLock.UnlockMutex();
return OYSTER_THREAD_ERROR_SUCCESS;
}
void OysterThread::Terminate()
{
this->privateData->threadData->state = OYSTER_THREAD_STATE_DEAD;
}
void OysterThread::Wait()
{
if(this->privateData->threadData->state == OYSTER_THREAD_STATE_DEAD)
{
return;
}
if(this->privateData->threadData->workerThread->get_id() == std::this_thread::get_id()) return;
this->privateData->threadData->workerThread->join();
}
void OysterThread::Wait(int msec)
{
if(this->privateData->threadData->workerThread->get_id() == std::this_thread::get_id()) return;
std::this_thread::sleep_for(std::chrono::milliseconds(msec));
}
OYSTER_THREAD_ERROR OysterThread::Swap(const OysterThread* other)
{
this->privateData->threadData->workerThread->swap(*other->privateData->threadData->workerThread);
return OYSTER_THREAD_ERROR_SUCCESS;
}
bool OysterThread::IsActive()
{
if (this->privateData->threadData->state == OYSTER_THREAD_STATE_RUNNING)
return true;
return false;
}

View File

@ -0,0 +1,315 @@
/////////////////////////////////////////////////////////////////////
// Inline and template implementations for
// the Utility Collection of Miscellanious Handy Functions
// © Dan Andersson 2013
/////////////////////////////////////////////////////////////////////
#ifndef UTILITIES_INLINE_IMPL_H
#define UTILITIES_INLINE_IMPL_H
#include "Utilities.h"
namespace Utility
{
namespace DynamicMemory
{
template<typename Type>
inline void SafeDeleteInstance( Type *dynamicInstance )
{
if( dynamicInstance )
{
delete dynamicInstance;
}
}
template<typename Type>
void SafeDeleteArray( Type dynamicArray[] )
{
if( dynamicArray )
{
delete [] dynamicArray;
}
}
template<typename Type>
UniquePointer<Type>::UniquePointer( Type *assignedInstance )
{
this->ownedInstance = assignedInstance;
}
template<typename Type>
UniquePointer<Type>::UniquePointer( const UniquePointer<Type> &donor )
{
this->ownedInstance = donor.ownedInstance;
donor.ownedInstance = NULL;
}
template<typename Type>
UniquePointer<Type>::~UniquePointer()
{
SafeDeleteInstance( this->ownedInstance );
}
template<typename Type>
UniquePointer<Type> & UniquePointer<Type>::operator = ( Type *assignedInstance )
{
SafeDeleteInstance( this->ownedInstance );
this->ownedInstance = assignedInstance;
return *this;
}
template<typename Type>
UniquePointer<Type> & UniquePointer<Type>::operator = ( const UniquePointer<Type> &donor )
{
SafeDeleteInstance( this->ownedInstance );
this->ownedInstance = donor.ownedInstance;
donor.ownedInstance = NULL;
return *this;
}
template<typename Type>
UniquePointer<Type>::operator Type* ()
{
return this->ownedInstance;
}
template<typename Type>
UniquePointer<Type>::operator const Type* () const
{
return this->ownedInstance;
}
template<typename Type>
Type * UniquePointer<Type>::operator -> ()
{
return this->ownedInstance;
}
template<typename Type>
const Type * UniquePointer<Type>::operator -> () const
{
return this->ownedInstance;
}
template<typename Type>
UniquePointer<Type>::operator bool() const
{
return this->ownedInstance != NULL;
}
template<typename Type>
bool UniquePointer<Type>::operator == ( Type *stray ) const
{
return this->ownedInstance == stray;
}
template<typename Type>
bool UniquePointer<Type>::operator != ( Type *stray ) const
{
return this->ownedInstance != stray;
}
template<typename Type>
Type* UniquePointer<Type>::Release()
{
Type *copy = this->ownedInstance;
this->ownedInstance = NULL;
return copy;
}
template<typename Type>
inline bool UniquePointer<Type>::HaveOwnership() const
{
return this->operator bool();
}
template<typename Type>
UniqueArray<Type>::UniqueArray( Type assignedArray[] )
{
this->ownedArray = assignedArray;
}
template<typename Type>
UniqueArray<Type>::UniqueArray( const UniqueArray<Type> &donor )
{
this->ownedArray = donor.ownedArray;
donor.ownedArray = NULL;
}
template<typename Type>
UniqueArray<Type>::~UniqueArray()
{
SafeDeleteArray( this->ownedArray );
}
template<typename Type>
UniqueArray<Type> & UniqueArray<Type>::operator = ( Type assignedArray[] )
{
SafeDeleteArray( this->ownedArray );
this->ownedArray = assignedArray;
}
template<typename Type>
UniqueArray<Type> & UniqueArray<Type>::operator = ( const UniqueArray<Type> &donor )
{
SafeDeleteArray( this->ownedArray );
this->ownedArray = donor.ownedInstance;
donor.owned = NULL;
}
template<typename Type> template<typename Index>
Type & UniqueArray<Type>::operator [] ( Index i )
{
return this->ownedArray[i];
}
template<typename Type> template<typename Index>
const Type & UniqueArray<Type>::operator [] ( Index i ) const
{
return this->ownedArray[i];
}
template<typename Type>
UniqueArray<Type>::operator bool () const
{
return this->ownedArray != NULL;
}
template<typename Type>
bool UniqueArray<Type>::operator == ( Type *stray ) const
{
return this->ownedArray == stray;
}
template<typename Type>
bool UniqueArray<Type>::operator != ( Type *stray ) const
{
return this->ownedArray != stray;
}
template<typename Type>
Type* UniqueArray<Type>::Release()
{
Type *copy = this->ownedArray;
this->ownedArray = NULL;
return copy;
}
template<typename Type>
inline bool UniqueArray<Type>::HaveOwnership() const
{
return this->operator bool();
}
<<<<<<< HEAD
=======
namespace SmartPointer
{
template<typename T> void StdSmartPointer<T>::Destroy()
{
delete this->_rc;
this->_rc = NULL;
delete this->_ptr;
this->_ptr = NULL;
}
template<typename T> StdSmartPointer<T>::StdSmartPointer()
:_rc(0), _ptr(0)
{ }
template<typename T> StdSmartPointer<T>::StdSmartPointer(T* p)
:_ptr(p)
{
this->_rc = new ReferenceCount();
this->_rc->Incref();
}
template<typename T> StdSmartPointer<T>::StdSmartPointer(const StdSmartPointer& d)
:_ptr(d._ptr), _rc(d._rc)
{
if(this->_rc)
this->_rc->Incref();
}
template<typename T> StdSmartPointer<T>::~StdSmartPointer()
{
if (this->_rc && this->_rc->Decref() == 0)
{
Destroy();
}
}
template<typename T> StdSmartPointer<T>& StdSmartPointer<T>::operator= (const StdSmartPointer<T>& p)
{
if (this != &p)
{
//Last to go?
if(this->_rc && this->_rc->Decref() == 0)
{
//Call child specific
Destroy();
}
this->_ptr = p._ptr;
this->_rc = p._rc;
this->_rc->Incref();
}
return *this;
}
template<typename T> StdSmartPointer<T>& StdSmartPointer<T>::operator= (T* p)
{
if (this->_ptr != p)
{
//Last to go?
if(this->_rc)
{
if(this->_rc->Decref() == 0)
{
//Call child specific
Destroy();
this->_rc = new ReferenceCount();
}
}
else
this->_rc = new ReferenceCount();
this->_ptr = p;
this->_rc->Incref();
}
return *this;
}
template<typename T> inline bool StdSmartPointer<T>::operator== (const StdSmartPointer<T>& d)
{
return d._ptr == this->_ptr;
}
template<typename T> inline bool StdSmartPointer<T>::operator== (const T& p)
{
return &p == this->_ptr;
}
template<typename T> inline T& StdSmartPointer<T>::operator* ()
{
return *this->_ptr;
}
template<typename T> inline T* StdSmartPointer<T>::operator-> ()
{
return this->_ptr;
}
template<typename T> inline StdSmartPointer<T>::operator T* ()
{
return this->_ptr;
}
template<typename T> inline StdSmartPointer<T>::operator bool()
{
return (this->_ptr != 0);
}
template<typename T> inline T* StdSmartPointer<T>::Get()
{
return this->_ptr;
}
template<typename T> inline bool StdSmartPointer<T>::IsValid()
{
return (this->_ptr != NULL) ? true : false;
}
}
>>>>>>> origin/MiscBranch
}
}
#endif

347
Code/Misc/Utilities.h.orig Normal file
View File

@ -0,0 +1,347 @@
//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!
// Utility Collection of Miscellanious Handy Functions
// © Dan Andersson 2013
//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!//!
#ifndef UTILITIES_H
#define UTILITIES_H
#include <string>
#include <istream>
#include <vector>
#include <locale>
#include <limits>
#include <atomic>
namespace Utility
{
namespace DynamicMemory
{
//! If dynamicInstance is not NULL, then delete
template<typename Type> void SafeDeleteInstance( Type *dynamicInstance );
//! If dynamicArray is not NULL, then delete []
template<typename Type> void SafeDeleteArray( Type dynamicArray[] );
//! Wrapper to safely transfer dynamic ownership/responsibility
template<typename Type> struct UniquePointer
{
public:
//! Assigns assignedInstance ownership to this UniquePonter, old owned instance will be deleted.
//! If NULL is assigned is equivalent with clearing all responsibilities from this UniquePointer.
UniquePointer( Type *assignedInstance = NULL );
//! Transfers assignedInstance ownership from donor to this UniquePonter, old owned instance will be deleted.
//! If donor had nothing, is equivalent with clearing all responsibilities from this UniquePointer.
UniquePointer( const UniquePointer<Type> &donor );
//! Will auto delete assigned dynamic instance.
~UniquePointer();
//! Assigns assignedInstance ownership to this UniquePonter, old owned instance will be deleted.
//! If NULL is assigned is equivalent with clearing all responsibilities from this UniquePointer.
UniquePointer<Type> & operator = ( Type *assignedInstance );
//! Transfers assignedInstance ownership from donor to this UniquePonter, old owned instance will be deleted.
//! If donor had nothing, is equivalent with clearing all responsibilities from this UniquePointer.
UniquePointer<Type> & operator = ( const UniquePointer<Type> &donor );
//! Access the assigned dynamic instance. Will crash if nothing there
operator Type* ();
//! Access the assigned dynamic instance. Will crash if nothing there
operator const Type* () const;
//! Access members of the assigned dynamic instance. Will crash if nothing there
Type * operator -> ();
//! Access members of the assigned dynamic instance. Will crash if nothing there
const Type * operator -> () const;
//! If true, this UniquePointer have a current ownership/responsibility of a dynamic instance.
operator bool () const;
//! @return true if this ownedInstance matches with stray
bool operator == ( Type *stray ) const;
//! @return false if this ownedInstance matches with stray
bool operator != ( Type *stray ) const;
//! This UniquePointer drops all claims of ownership/responsibility and returns the dynamic instance. Now it is your responsibility to delete.
Type* Release();
//! (inline) If true, this UniquePointer have a current ownership/responsibility of a dynamic instance.
bool HaveOwnership() const;
private:
mutable Type *ownedInstance;
};
template<typename Type>
struct UniqueArray
{ //! Wrapper to safely transfer dynamic ownership/responsibility
public:
//! Assigns assignedInstance ownership to this UniquePonter, old owned array will be deleted.
//! If NULL is assigned is equivalent with clearing all responsibilities from this UniqueArray.
UniqueArray( Type assignedArray[] = NULL );
//! Transfers assignedInstance ownership from donor to this UniquePonter, old owned array will be deleted.
//! If donor had nothing, is equivalent with clearing all responsibilities from this UniqueArray.
UniqueArray( const UniqueArray<Type> &donor );
//! Will auto delete assigned dynamic array.
~UniqueArray();
//! Assigns assignedInstance ownership to this UniquePonter, old owned array will be deleted.
//! If NULL is assigned is equivalent with clearing all responsibilities from this UniqueArray.
UniqueArray<Type> & operator = ( Type assignedArray[] );
//! Transfers assignedInstance ownership from donor to this UniquePonter, old owned array will be deleted.
//! If donor had nothing, is equivalent with clearing all responsibilities from this UniqueArray.
UniqueArray<Type> & operator = ( const UniqueArray<Type> &donor );
//! Accesses the instance at index i of this UniqeArray's owned dynamic array.
//! Will crash if out-of-bound or there is no assigned array.
template<typename Index> Type & operator [] ( Index i );
//! Accesses the instance at index i of this UniqeArray's owned dynamic array.
//! Will crash if out-of-bound or there is no assigned array.
template<typename Index> const Type & operator [] ( Index i ) const;
//! If true, this UniqueArray have a current ownership/responsibility of a dynamic instance.
operator bool () const;
//! @return true if this ownedInstance matches with stray
bool operator == ( Type *stray ) const;
//! @return false if this ownedInstance matches with stray
bool operator != ( Type *stray ) const;
//! This UniqueArray drops all claims of ownership/responsibility and returns the dynamic array. Now it is your responsibility to delete.
Type* Release();
//! (inline) If true, this UniqueArray have a current ownership/responsibility of a dynamic array.
bool HaveOwnership() const;
private:
mutable Type *ownedArray;
};
struct RefCount
{
private:
std::atomic<int> count;
public:
<<<<<<< HEAD
RefCount() :count(0) { }
RefCount(const RefCount& o) { count = o.count; }
const RefCount& operator=(const RefCount& o) { count = o.count; return *this;}
void Incref() { this->count++; }
void Incref(int c) { this->count += c; }
int Decref() { return --this->count;}
void Reset() { this->count = 0; }
};
=======
ReferenceCount() :count(0) { }
ReferenceCount(const ReferenceCount& o) { count.store(o.count); }
inline const ReferenceCount& operator=(const ReferenceCount& o) { count.store(o.count); return *this;}
inline void Incref() { this->count++; }
inline void Incref(int c) { this->count += c; }
inline int Decref() { return --this->count;}
inline void Reset() { this->count = 0; }
};
namespace SmartPointer
{
//! Smart pointer for a regular object.
/**
* Regular objects, objects that is deleted normaly (ie not COM objects, or array pointers)
* can use this class to easy the use of dynamic memory
*/
template<typename T>
struct StdSmartPointer
{
private:
ReferenceCount *_rc;
T *_ptr;
/** Destroys the pointer and returns the memory allocated. */
void Destroy();
public:
StdSmartPointer();
StdSmartPointer(T* p);
StdSmartPointer(const StdSmartPointer& d);
virtual~StdSmartPointer();
StdSmartPointer<T>& operator= (const StdSmartPointer<T>& p);
StdSmartPointer<T>& operator= (T* p);
bool operator== (const StdSmartPointer<T>& d);
bool operator== (const T& p);
T& operator* ();
T* operator-> ();
operator T* ();
operator bool();
/**
* Returns the connected pointer */
T* Get();
/** Checks if the pointer is valid (not NULL)
Returns true for valid, else false. */
bool IsValid();
};
}
>>>>>>> origin/MiscBranch
}
namespace String
{
// string
::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, char delim, ::std::string::size_type offset = 0 );
::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::string &delim, ::std::string::size_type offset = 0 );
::std::vector<::std::string> & Split( ::std::vector<::std::string> &output, const ::std::string &str, const ::std::vector<::std::string> &delim, ::std::string::size_type offset = 0 );
::std::string Trim( const ::std::string &str );
::std::string & ToLowerCase( ::std::string &output, const ::std::string &str );
::std::string & ToLowerCase( ::std::string &str );
::std::string & ToUpperCase( ::std::string &output, const ::std::string &str );
::std::string & ToUpperCase( ::std::string &str );
::std::string & ExtractDirPath( ::std::string &output, const ::std::string &file, char dirDelimeter );
::std::string & ExtractDirPath( ::std::string &output, const ::std::string &file, const ::std::string &dirDelimeter );
::std::string & ReplaceCharacters( ::std::string &str, char characterToReplace, char newCharacter, const ::std::string::size_type &offset = 0, const ::std::string::size_type &end = ::std::string::npos );
// wstring
::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, char delim, ::std::wstring::size_type offset = 0 );
::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, const ::std::wstring &delim, ::std::wstring::size_type offset = 0 );
::std::vector<::std::wstring> & Split( ::std::vector<::std::wstring> &output, const ::std::wstring &str, const ::std::vector<::std::wstring> &delim, ::std::wstring::size_type offset = 0 );
::std::wstring & wToLowerCase( ::std::wstring &output, const ::std::wstring &str );
::std::wstring & wToLowerCase( ::std::wstring &str );
//To wstring
::std::wstring & StringToWstring( const ::std::string &str, ::std::wstring &wstr );
::std::string & WStringToString( const ::std::wstring &wstr, ::std::string &str );
}
namespace Stream
{
float* ReadFloats( float *output, ::std::istream &input, unsigned int numFloats );
}
namespace StaticArray
{
template<typename ScalarType, unsigned int num>
inline unsigned int NumElementsOf( const ScalarType(&)[num] )
{ return num; }
template<typename ScalarType, unsigned int num>
inline ScalarType & FirstElementOf( ScalarType (&arr)[num] )
{ return arr[0]; }
template<typename ScalarType, unsigned int num>
inline ScalarType & LastElementOf( ScalarType (&arr)[num] )
{ return arr[num-1]; }
}
namespace Element
{
template<typename ScalarType>
inline void Swap( ScalarType &elementA, ScalarType &elementB, ScalarType &swapSpace )
{ swapSpace = elementA; elementA = elementB; elementB = swapSpace; }
template<typename ScalarType>
inline void Swap( ScalarType &elementA, ScalarType &elementB )
{ ScalarType swapSpace; Swap( elementA, elementB, swapSpace ); }
}
namespace Value
{
using ::std::numeric_limits;
template<typename ValueType>
inline ValueType Abs( const ValueType &value )
{ return value < 0 ? value * -1 : value; }
template<typename ValueType>
inline ValueType Max( const ValueType &valueA, const ValueType &valueB )
{ return valueA > valueB ? valueA : valueB; }
template<typename ValueType>
inline ValueType Min( const ValueType &valueA, const ValueType &valueB )
{ return valueA < valueB ? valueA : valueB; }
template<typename ValueType>
inline ValueType Average( const ValueType &valueA, const ValueType &valueB )
{ return (valueA + valueB) * 0.5f; }
template<typename ValueType>
inline ValueType AverageWithDelta( const ValueType &origin, const ValueType &delta )
{ return origin + (delta * 0.5f); }
template<typename ValueType>
inline ValueType Radian( const ValueType &degree )
{ return degree * (3.1415926535897932384626433832795f / 180.0f); }
template<typename ValueType>
inline ValueType Degree( const ValueType &radian )
{ return radian * (180.0f / 3.1415926535897932384626433832795f); }
// SPECIALIZATIONS //!//!//!//!//!//!//!//!//!//!//!//!//!//!
template<> inline char Average<char>( const char &valueA, const char &valueB )
{ return (valueA + valueB) >> 1; }
template<> inline unsigned char Average<unsigned char>( const unsigned char &valueA, const unsigned char &valueB )
{ return (valueA + valueB) >> 1; }
template<> inline int Average<int>( const int &valueA, const int &valueB )
{ return (valueA + valueB) >> 1; }
template<> inline unsigned int Average<unsigned int>( const unsigned int &valueA, const unsigned int &valueB )
{ return (valueA + valueB) >> 1; }
template<> inline long Average<long>( const long &valueA, const long &valueB )
{ return (valueA + valueB) >> 1; }
template<> inline unsigned long Average<unsigned long>( const unsigned long &valueA, const unsigned long &valueB )
{ return (valueA + valueB) >> 1; }
template<> inline long long Average<long long>( const long long &valueA, const long long &valueB )
{ return (valueA + valueB) >> 1; }
template<> inline unsigned long long Average<unsigned long long>( const unsigned long long &valueA, const unsigned long long &valueB )
{ return (valueA + valueB) >> 1; }
template<> inline char AverageWithDelta<char>( const char &origin, const char &delta )
{ return origin + (delta >> 1); }
template<> inline unsigned char AverageWithDelta<unsigned char>( const unsigned char &origin, const unsigned char &delta )
{ return origin + (delta >> 1); }
template<> inline int AverageWithDelta<int>( const int &origin, const int &delta )
{ return origin + (delta >> 1); }
template<> inline unsigned int AverageWithDelta<unsigned int>( const unsigned int &origin, const unsigned int &delta )
{ return origin + (delta >> 1); }
template<> inline long AverageWithDelta<long>( const long &origin, const long &delta )
{ return origin + (delta >> 1); }
template<> inline unsigned long AverageWithDelta<unsigned long>( const unsigned long &origin, const unsigned long &delta )
{ return origin + (delta >> 1); }
template<> inline long long AverageWithDelta<long long>( const long long &origin, const long long &delta )
{ return origin + (delta >> 1); }
template<> inline unsigned long long AverageWithDelta<unsigned long long>( const unsigned long long &origin, const unsigned long long &delta )
{ return origin + (delta >> 1); }
}
}
#include "Utilities-InlineImpl.h"
#endif