first commit
This commit is contained in:
218
include/platform/alloc/ialloc.h
Normal file
218
include/platform/alloc/ialloc.h
Normal file
@ -0,0 +1,218 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NALLOCATOR_INTERFACE__
|
||||
#define __NALLOCATOR_INTERFACE__
|
||||
|
||||
|
||||
#include "ntypes.h"
|
||||
#include <new>
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Alloc {
|
||||
|
||||
// Allocator systems.
|
||||
enum System
|
||||
{
|
||||
General,
|
||||
|
||||
ListItem,
|
||||
StringBuffer,
|
||||
|
||||
Filesystem,
|
||||
Metatag,
|
||||
|
||||
Curve,
|
||||
Motion,
|
||||
AnimationSource,
|
||||
|
||||
Vector,
|
||||
Matrix,
|
||||
|
||||
Physics,
|
||||
|
||||
Item3d,
|
||||
|
||||
Geometry,
|
||||
Material,
|
||||
Texture,
|
||||
Picture,
|
||||
|
||||
Mixer,
|
||||
Sound,
|
||||
|
||||
Renderer,
|
||||
RendererJob,
|
||||
RendererTerrain,
|
||||
|
||||
VertexBuffer,
|
||||
|
||||
Global,
|
||||
SystemCount
|
||||
};
|
||||
|
||||
struct SystemDesc
|
||||
{
|
||||
const char *group;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/*
|
||||
Allocators can be changed per system by editing the following defines.
|
||||
*/
|
||||
#define MemAllocListItem GS::Alloc::DefaultAllocator
|
||||
#define MemAllocStringBuffer GS::Alloc::DefaultAllocator
|
||||
|
||||
#define MemAllocFilesystem GS::Alloc::DefaultAllocator
|
||||
#define MemAllocMetatag GS::Alloc::DefaultAllocator
|
||||
|
||||
#define MemAllocCurve GS::Alloc::DefaultAllocator
|
||||
#define MemAllocMotion GS::Alloc::DefaultAllocator
|
||||
#define MemAllocAnimationSource GS::Alloc::DefaultAllocator
|
||||
|
||||
#define MemAllocVector GS::Alloc::DefaultAllocator
|
||||
#define MemAllocMatrix GS::Alloc::DefaultAllocator
|
||||
|
||||
#define MemAllocPhysics GS::Alloc::DefaultAllocator
|
||||
|
||||
#define MemAllocItem3d GS::Alloc::DefaultAllocator
|
||||
|
||||
#define MemAllocGeometry GS::Alloc::DefaultAllocator
|
||||
#define MemAllocMaterial GS::Alloc::DefaultAllocator
|
||||
#define MemAllocTexture GS::Alloc::DefaultAllocator
|
||||
#define MemAllocPicture GS::Alloc::DefaultAllocator
|
||||
|
||||
#define MemAllocMixer GS::Alloc::DefaultAllocator
|
||||
#define MemAllocSound GS::Alloc::DefaultAllocator
|
||||
|
||||
#define MemAllocRenderer GS::Alloc::DefaultAllocator
|
||||
#define MemAllocRendererJob GS::Alloc::DefaultAllocator
|
||||
#define MemAllocRendererTerrain GS::Alloc::DefaultAllocator
|
||||
|
||||
#define MemAllocVertexBuffer GS::Alloc::DefaultAllocator
|
||||
|
||||
#if __ENABLE_ALLOCATION_STAT__
|
||||
|
||||
struct Header
|
||||
{
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct Stat
|
||||
{
|
||||
uint alloc_count, alloc_avg;
|
||||
uint alive_count, alive_count_peak;
|
||||
size_t size, size_peak;
|
||||
|
||||
Stat() : alloc_count(0), alloc_avg(0), alive_count(0), alive_count_peak(0), size(0), size_peak(0) {}
|
||||
};
|
||||
|
||||
/// Per system statistics.
|
||||
extern Stat system_stat[SystemCount];
|
||||
extern SystemDesc system_desc[SystemCount];
|
||||
|
||||
size_t GetAdjustedAllocationSize(size_t);
|
||||
void *SetupAllocationStat(void *, size_t);
|
||||
void *GetAllocationStat(void *, Header *&);
|
||||
|
||||
void UpdateStatAlloc(size_t, System);
|
||||
void UpdateStatDelete(size_t, System);
|
||||
|
||||
#endif
|
||||
|
||||
/// Standard C++ allocator.
|
||||
struct DefaultAllocator
|
||||
{
|
||||
static void *Alloc(size_t size, System sys = General);
|
||||
static void Delete(void *addr, System sys = General);
|
||||
};
|
||||
|
||||
} // Alloc
|
||||
} // GS
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#if __ENABLE_ALLOCATION_STAT__
|
||||
|
||||
#define __NSTAT_WRAPALLOC(__WRAPPED_CALL, __SYSTEM)\
|
||||
GS::Alloc::UpdateStatAlloc(size, __SYSTEM);\
|
||||
size_t __raw_size = size;\
|
||||
size = GS::Alloc::GetAdjustedAllocationSize(size);\
|
||||
return GS::Alloc::SetupAllocationStat(__WRAPPED_CALL, __raw_size);
|
||||
|
||||
#define __NSTAT_WRAPDELETE(__WRAPPED_CALL, __SYSTEM)\
|
||||
if (addr)\
|
||||
{\
|
||||
GS::Alloc::Header *h;\
|
||||
addr = GS::Alloc::GetAllocationStat(addr, h);\
|
||||
GS::Alloc::UpdateStatDelete(h->size, __SYSTEM);\
|
||||
__WRAPPED_CALL;\
|
||||
}
|
||||
|
||||
#define __NSTAT_ALLOC(__SIZE, __SYSTEM) GS::Alloc::UpdateStatAlloc(__SIZE, __SYSTEM)
|
||||
#define __NSTAT_DELETE(__SIZE, __SYSTEM) GS::Alloc::UpdateStatDelete(__SIZE, __SYSTEM)
|
||||
|
||||
#else
|
||||
|
||||
#define __NSTAT_WRAPALLOC(__WRAPPED_CALL, __SYSTEM) return __WRAPPED_CALL;
|
||||
#define __NSTAT_WRAPDELETE(__WRAPPED_CALL, __SYSTEM) __WRAPPED_CALL;
|
||||
|
||||
#define __NSTAT_ALLOC(__SIZE, __SYSTEM)
|
||||
#define __NSTAT_DELETE(__SIZE, __SYSTEM)
|
||||
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#if __PLATFORM_EMSCRIPTEN__
|
||||
|
||||
#define NPLACEMENT_NEW(__SYSTEM)
|
||||
|
||||
#else
|
||||
|
||||
#define NPLACEMENT_NEW(__SYSTEM)\
|
||||
void *operator new (size_t size)\
|
||||
{ return MemAlloc##__SYSTEM::Alloc(size, GS::Alloc::__SYSTEM); }\
|
||||
void operator delete(void *addr)\
|
||||
{ MemAlloc##__SYSTEM::Delete(addr, GS::Alloc::__SYSTEM); }\
|
||||
void *operator new [] (size_t size)\
|
||||
{ return MemAlloc##__SYSTEM::Alloc(size, GS::Alloc::__SYSTEM); }\
|
||||
void operator delete [] (void *addr)\
|
||||
{ MemAlloc##__SYSTEM::Delete(addr, GS::Alloc::__SYSTEM); }
|
||||
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void *_align_alloc(size_t, size_t);
|
||||
void _align_free(void *);
|
||||
|
||||
template <class T> T *_align_new(size_t align)
|
||||
{ return ::new (_align_alloc(sizeof(T), align)) T(); }
|
||||
template <class T, typename P0> T *_align_new(P0 &p0, size_t align)
|
||||
{ return ::new (_align_alloc(sizeof(T), align)) T(p0); }
|
||||
template <class T> void _align_delete(T *p)
|
||||
{
|
||||
p->~T();
|
||||
_align_free(p);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <class T> void _safe_delete(T *&p)
|
||||
{
|
||||
delete p;
|
||||
p = 0;
|
||||
}
|
||||
template <class T> void _safe_delete_array(T *&p)
|
||||
{
|
||||
delete [] p;
|
||||
p = 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // __NALLOCATOR_INTERFACE__
|
||||
30
include/platform/analytics/analytics.h
Normal file
30
include/platform/analytics/analytics.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __ANALYTICS__
|
||||
#define __ANALYTICS__
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short Analytics system interface.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
struct IAnalytics
|
||||
{
|
||||
/// Log an analytics event.
|
||||
virtual void logEvent(const char *) = 0;
|
||||
/// Serve a fullscreen advertisement.
|
||||
virtual void serveFullscreenAd(const char *) = 0;
|
||||
|
||||
virtual ~IAnalytics() {}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __ANALYTICS__
|
||||
35
include/platform/assert/nassert.h
Normal file
35
include/platform/assert/nassert.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NASSERT__
|
||||
#define __NASSERT__
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Assert {
|
||||
|
||||
/// Trigger a system assertion.
|
||||
extern void Trigger(const char *source, int line, const char *condition, const char *message = 0);
|
||||
|
||||
} // Assert
|
||||
} // GS
|
||||
|
||||
// Portable assert.
|
||||
#ifdef _DEBUG
|
||||
#define __ASSERT__(_EXP_) if (!(_EXP_)) GS::Assert::Trigger(__FILE__, __LINE__, #_EXP_)
|
||||
#define __ASSERT_MSG__(_EXP_, _MSG_) if (!(_EXP_)) GS::Assert::Trigger(__FILE__, __LINE__, #_EXP_, _MSG_)
|
||||
#define __ASSERT_ALWAYS__ GS::Assert::Trigger(__FILE__, __LINE__, "Unconditional")
|
||||
#else
|
||||
#define __ASSERT__(_EXP_)
|
||||
#define __ASSERT_MSG__(_EXP_, _MSG_)
|
||||
#define __ASSERT_ALWAYS__
|
||||
#endif
|
||||
|
||||
#define __RASSERT__(_EXP_) if (!(_EXP_)) GS::Assert::Trigger(__FILE__, __LINE__, #_EXP_)
|
||||
#define __RASSERT_MSG__(_EXP_, _MSG_) if (!(_EXP_)) GS::Assert::Trigger(__FILE__, __LINE__, #_EXP_, _MSG_)
|
||||
|
||||
|
||||
#endif // __NASSERT__
|
||||
201
include/platform/async/async_call_queue.h
Normal file
201
include/platform/async/async_call_queue.h
Normal file
@ -0,0 +1,201 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __ASYNC_CALL_QUEUE__
|
||||
#define __ASYNC_CALL_QUEUE__
|
||||
|
||||
|
||||
#include "async/future.h"
|
||||
#include "thread/thread.h"
|
||||
#include "thread/mutex.h"
|
||||
#include "container/nlist.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace ASync {
|
||||
|
||||
/*!
|
||||
@short Asynchronous call queue.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
class CallQueue
|
||||
{
|
||||
struct BaseCall
|
||||
{
|
||||
virtual void Execute() = 0;
|
||||
virtual ~BaseCall() {}
|
||||
};
|
||||
|
||||
Threading::Mutex queue_mutex;
|
||||
List <BaseCall *> call_queue;
|
||||
|
||||
/// Post a call to the queue.
|
||||
void Queue(BaseCall *m)
|
||||
{
|
||||
Threading::MutexLock lock(&queue_mutex);
|
||||
call_queue.Append(m);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Call a member function, ignore the return value.
|
||||
template <typename I, typename F> struct MemberCall : public BaseCall
|
||||
{
|
||||
I i; F fn;
|
||||
void Execute() { (i->*fn)(); }
|
||||
MemberCall(I _i, F _fn) : i(_i), fn(_fn) {}
|
||||
};
|
||||
template <typename I, typename F, typename A1> struct MemberCall1 : public BaseCall
|
||||
{
|
||||
I i; F fn; A1 a1;
|
||||
void Execute() { (i->*fn)(a1); }
|
||||
MemberCall1(I _i, F _fn, const A1 &_a1) : i(_i), fn(_fn), a1(_a1) {}
|
||||
};
|
||||
template <typename I, typename F, typename A1, typename A2> struct MemberCall2 : public BaseCall
|
||||
{
|
||||
I i; F fn; A1 a1; A2 a2;
|
||||
void Execute() { (i->*fn)(a1, a2); }
|
||||
MemberCall2(I _i, F _fn, const A1 &_a1, const A2 &_a2) : i(_i), fn(_fn), a1(_a1), a2(_a2) {}
|
||||
};
|
||||
template <typename I, typename F, typename A1, typename A2, typename A3> struct MemberCall3 : public BaseCall
|
||||
{
|
||||
I i; F fn; A1 a1; A2 a2; A3 a3;
|
||||
void Execute() { (i->*fn)(a1, a2, a3); }
|
||||
MemberCall3(I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3) : i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3) {}
|
||||
};
|
||||
template <typename I, typename F, typename A1, typename A2, typename A3, typename A4> struct MemberCall4 : public BaseCall
|
||||
{
|
||||
I i; F fn; A1 a1; A2 a2; A3 a3; A4 a4;
|
||||
void Execute() { (i->*fn)(a1, a2, a3, a4); }
|
||||
MemberCall4(I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3, const A4 &_a4) : i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3), a4(_a4) {}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
template <typename I, typename F> void QueueMemberCall(I i, F fn)
|
||||
{ Queue(new MemberCall <I, F> (i, fn)); }
|
||||
template <typename I, typename F, typename A1> void QueueMemberCall(I i, F fn, const A1 &a1)
|
||||
{ Queue(new MemberCall1 <I, F, A1> (i, fn, a1)); }
|
||||
template <typename I, typename F, typename A1, typename A2> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2)
|
||||
{ Queue(new MemberCall2 <I, F, A1, A2> (i, fn, a1, a2)); }
|
||||
template <typename I, typename F, typename A1, typename A2, typename A3> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3)
|
||||
{ Queue(new MemberCall3 <I, F, A1, A2, A3> (i, fn, a1, a2, a3)); }
|
||||
template <typename I, typename F, typename A1, typename A2, typename A3, typename A4> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
|
||||
{ Queue(new MemberCall4 <I, F, A1, A2, A3, A4> (i, fn, a1, a2, a3, a4)); }
|
||||
|
||||
private:
|
||||
|
||||
// Generic return value calls.
|
||||
template <typename R, typename I, typename F> struct RValMemberCall : public BaseCall
|
||||
{
|
||||
Future <R> &future; I i; F fn;
|
||||
void Execute() { future.Set((i->*fn)()); }
|
||||
RValMemberCall(Future <R> &_future, I _i, F _fn) : future(_future), i(_i), fn(_fn) {}
|
||||
};
|
||||
template <typename R, typename I, typename F, typename A1> struct RValMemberCall1 : public BaseCall
|
||||
{
|
||||
Future <R> &future; I i; F fn; A1 a1;
|
||||
void Execute() { future.Set((i->*fn)(a1)); }
|
||||
RValMemberCall1(Future <R> &_future, I _i, F _fn, const A1 &_a1) : future(_future), i(_i), fn(_fn), a1(_a1) {}
|
||||
};
|
||||
template <typename R, typename I, typename F, typename A1, typename A2> struct RValMemberCall2 : public BaseCall
|
||||
{
|
||||
Future <R> &future; I i; F fn; A1 a1; A2 a2;
|
||||
void Execute() { future.Set((i->*fn)(a1, a2)); }
|
||||
RValMemberCall2(Future <R> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2) {}
|
||||
};
|
||||
template <typename R, typename I, typename F, typename A1, typename A2, typename A3> struct RValMemberCall3 : public BaseCall
|
||||
{
|
||||
Future <R> &future; I i; F fn; A1 a1; A2 a2; A3 a3;
|
||||
void Execute() { future.Set((i->*fn)(a1, a2, a3)); }
|
||||
RValMemberCall3(Future <R> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3) {}
|
||||
};
|
||||
template <typename R, typename I, typename F, typename A1, typename A2, typename A3, typename A4> struct RValMemberCall4 : public BaseCall
|
||||
{
|
||||
Future <R> &future; I i; F fn; A1 a1; A2 a2; A3 a3; A4 a4;
|
||||
void Execute() { future.Set((i->*fn)(a1, a2, a3, a4)); }
|
||||
RValMemberCall4(Future <R> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3, const A4 &_a4) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3), a4(_a4) {}
|
||||
};
|
||||
|
||||
// No return value specialized calls.
|
||||
template <typename I, typename F> struct RValMemberCall <void, I, F> : public BaseCall
|
||||
{
|
||||
Future <void> &future; I i; F fn;
|
||||
void Execute() { (i->*fn)(); future.Set(); }
|
||||
RValMemberCall(Future <void> &_future, I _i, F _fn) : future(_future), i(_i), fn(_fn) {}
|
||||
};
|
||||
template <typename I, typename F, typename A1> struct RValMemberCall1 <void, I, F, A1> : public BaseCall
|
||||
{
|
||||
Future <void> &future; I i; F fn; A1 a1;
|
||||
void Execute() { (i->*fn)(a1); future.Set(); }
|
||||
RValMemberCall1(Future <void> &_future, I _i, F _fn, const A1 &_a1) : future(_future), i(_i), fn(_fn), a1(_a1) {}
|
||||
};
|
||||
template <typename I, typename F, typename A1, typename A2> struct RValMemberCall2 <void, I, F, A1, A2> : public BaseCall
|
||||
{
|
||||
Future <void> &future; I i; F fn; A1 a1; A2 a2;
|
||||
void Execute() { (i->*fn)(a1, a2); future.Set(); }
|
||||
RValMemberCall2(Future <void> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2) {}
|
||||
};
|
||||
template <typename I, typename F, typename A1, typename A2, typename A3> struct RValMemberCall3 <void, I, F, A1, A2, A3> : public BaseCall
|
||||
{
|
||||
Future <void> &future; I i; F fn; A1 a1; A2 a2; A3 a3;
|
||||
void Execute() { (i->*fn)(a1, a2, a3); future.Set(); }
|
||||
RValMemberCall3(Future <void> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3) {}
|
||||
};
|
||||
template <typename I, typename F, typename A1, typename A2, typename A3, typename A4> struct RValMemberCall4 <void, I, F, A1, A2, A3, A4> : public BaseCall
|
||||
{
|
||||
Future <void> &future; I i; F fn; A1 a1; A2 a2; A3 a3; A4 a4;
|
||||
void Execute() { (i->*fn)(a1, a2, a3, a4); future.Set(); }
|
||||
RValMemberCall4(Future <void> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3, const A4 &_a4) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3), a4(_a4) {}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/// Queue a member call, return the value in a future.
|
||||
template <typename R, typename I, typename F> void QueueMemberCall(Future <R> &f, I i, F fn)
|
||||
{ Queue(new RValMemberCall <R, I, F> (f, i, fn)); }
|
||||
template <typename R, typename I, typename F, typename A1> void QueueMemberCall(Future <R> &f, I i, F fn, const A1 &a1)
|
||||
{ Queue(new RValMemberCall1 <R, I, F, A1> (f, i, fn, a1)); }
|
||||
template <typename R, typename I, typename F, typename A1, typename A2> void QueueMemberCall(Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2)
|
||||
{ Queue(new RValMemberCall2 <R, I, F, A1, A2> (f, i, fn, a1, a2)); }
|
||||
template <typename R, typename I, typename F, typename A1, typename A2, typename A3> void QueueMemberCall(Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3)
|
||||
{ Queue(new RValMemberCall3 <R, I, F, A1, A2, A3> (f, i, fn, a1, a2, a3)); }
|
||||
template <typename R, typename I, typename F, typename A1, typename A2, typename A3, typename A4> void QueueMemberCall(Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
|
||||
{ Queue(new RValMemberCall4 <R, I, F, A1, A2, A3, A4> (f, i, fn, a1, a2, a3, a4)); }
|
||||
|
||||
public:
|
||||
|
||||
bool Execute()
|
||||
{
|
||||
BaseCall *c = NULL;
|
||||
{
|
||||
Threading::MutexLock lock(&queue_mutex);
|
||||
|
||||
if (call_queue.GetCount() == 0)
|
||||
return false;
|
||||
|
||||
c = call_queue[0];
|
||||
call_queue.RemoveAt(0);
|
||||
}
|
||||
|
||||
if (c)
|
||||
{
|
||||
c->Execute();
|
||||
delete c;
|
||||
}
|
||||
return asbool(c);
|
||||
}
|
||||
void ExecuteAll()
|
||||
{
|
||||
while (Execute() == true) {}
|
||||
}
|
||||
};
|
||||
|
||||
} // ASync
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __ASYNC_CALL_QUEUE__
|
||||
84
include/platform/async/async_call_queue_thread.h
Normal file
84
include/platform/async/async_call_queue_thread.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __ASYNC_CALL_QUEUE_THREAD__
|
||||
#define __ASYNC_CALL_QUEUE_THREAD__
|
||||
|
||||
|
||||
#include "async/async_call_queue.h"
|
||||
#include "thread/thread_event.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
/*!
|
||||
@short A worker thread whose sole purpose is to process its async call queue.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
class ASyncCallQueueThread : public Thread
|
||||
{
|
||||
Atomic32 acqt_running;
|
||||
Event queue_event;
|
||||
|
||||
ASync::CallQueue call_queue;
|
||||
|
||||
public:
|
||||
|
||||
virtual void OnIdle() {}
|
||||
|
||||
virtual void Execute()
|
||||
{
|
||||
for (acqt_running.Set(1); acqt_running.Get() != 2; )
|
||||
{
|
||||
call_queue.ExecuteAll();
|
||||
OnIdle();
|
||||
queue_event.Wait();
|
||||
}
|
||||
acqt_running.Set(0);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (acqt_running.Get() != 0)
|
||||
{
|
||||
acqt_running.Set(2);
|
||||
queue_event.Trigger();
|
||||
while (acqt_running.Get() != 0); // spinlock
|
||||
}
|
||||
}
|
||||
|
||||
template <typename I, typename F> void QueueMemberCall(I i, F fn)
|
||||
{ call_queue.QueueMemberCall(i, fn); queue_event.Trigger(); }
|
||||
template <typename I, typename F, typename A1> void QueueMemberCall(I i, F fn, const A1 &a1)
|
||||
{ call_queue.QueueMemberCall(i, fn, a1); queue_event.Trigger(); }
|
||||
template <typename I, typename F, typename A1, typename A2> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2)
|
||||
{ call_queue.QueueMemberCall(i, fn, a1, a2); queue_event.Trigger(); }
|
||||
template <typename I, typename F, typename A1, typename A2, typename A3> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3)
|
||||
{ call_queue.QueueMemberCall(i, fn, a1, a2, a3); queue_event.Trigger(); }
|
||||
template <typename I, typename F, typename A1, typename A2, typename A3, typename A4> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
|
||||
{ call_queue.QueueMemberCall(i, fn, a1, a2, a3, a4); queue_event.Trigger(); }
|
||||
|
||||
/// Queue a member call, return the value in a future.
|
||||
template <typename R, typename I, typename F> void QueueMemberCall(ASync::Future <R> &f, I i, F fn)
|
||||
{ call_queue.QueueMemberCall(f, i, fn); queue_event.Trigger(); }
|
||||
template <typename R, typename I, typename F, typename A1> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1)
|
||||
{ call_queue.QueueMemberCall(f, i, fn, a1); queue_event.Trigger(); }
|
||||
template <typename R, typename I, typename F, typename A1, typename A2> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2)
|
||||
{ call_queue.QueueMemberCall(f, i, fn, a1, a2); queue_event.Trigger(); }
|
||||
template <typename R, typename I, typename F, typename A1, typename A2, typename A3> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3)
|
||||
{ call_queue.QueueMemberCall(f, i, fn, a1, a2, a3); queue_event.Trigger(); }
|
||||
template <typename R, typename I, typename F, typename A1, typename A2, typename A3, typename A4> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
|
||||
{ call_queue.QueueMemberCall(f, i, fn, a1, a2, a3, a4); queue_event.Trigger(); }
|
||||
|
||||
virtual ~ASyncCallQueueThread()
|
||||
{ Stop(); }
|
||||
};
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __ASYNC_CALL_QUEUE_THREAD__
|
||||
67
include/platform/async/future.h
Normal file
67
include/platform/async/future.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NFUTURE__
|
||||
#define __NFUTURE__
|
||||
|
||||
|
||||
#include "thread/atomic_value.h"
|
||||
#include "memory/nshared_ptr.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace ASync {
|
||||
|
||||
/*
|
||||
@short Future.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
template <class T> class Future
|
||||
{
|
||||
T value;
|
||||
Threading::Atomic32 set;
|
||||
|
||||
public:
|
||||
|
||||
bool IsSet() const
|
||||
{ return set.Get() == 1; }
|
||||
void Set(const T &_value)
|
||||
{
|
||||
value = _value;
|
||||
set.Set(1);
|
||||
}
|
||||
|
||||
void Wait()
|
||||
{ while (!IsSet()); }
|
||||
|
||||
T &Get()
|
||||
{
|
||||
Wait();
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
template <> class Future <void>
|
||||
{
|
||||
Threading::Atomic32 set;
|
||||
|
||||
public:
|
||||
|
||||
bool IsSet() const
|
||||
{ return set.Get() == 1; }
|
||||
void Set()
|
||||
{ set.Set(1); }
|
||||
|
||||
void Wait()
|
||||
{ while (!IsSet()); }
|
||||
};
|
||||
|
||||
} // ASync
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NFUTURE__
|
||||
131
include/platform/async/job.h
Normal file
131
include/platform/async/job.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __JOB_SYSTEM__
|
||||
#define __JOB_SYSTEM__
|
||||
|
||||
|
||||
#define __USE_LOCK_FREE_JOB_QUEUE__ 1
|
||||
|
||||
#include "thread/thread_event.h"
|
||||
#include "thread/thread.h"
|
||||
#include "thread/mutex.h"
|
||||
#include "container/nlist.h"
|
||||
#if __USE_LOCK_FREE_JOB_QUEUE__
|
||||
#include "container/mpmc_bounded_queue.h"
|
||||
#else
|
||||
#include "container/nstack.h"
|
||||
#endif
|
||||
#include "container/narray.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "time/ntime.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace ASync {
|
||||
class JobManager;
|
||||
|
||||
//
|
||||
class JobWorkerThread : public Threading::Thread
|
||||
{
|
||||
protected:
|
||||
|
||||
JobManager &manager;
|
||||
|
||||
Threading::Atomic32 running;
|
||||
uint worker_id;
|
||||
|
||||
public:
|
||||
|
||||
/// Get worker id.
|
||||
int GetWorkerId() const { return worker_id; }
|
||||
/// Worker loop.
|
||||
virtual void Execute();
|
||||
|
||||
/// Stop worker thread.
|
||||
void Stop();
|
||||
/// Is the worker thread running.
|
||||
bool IsRunning() const;
|
||||
|
||||
JobWorkerThread(JobManager &m, uint id) : manager(m), worker_id(id) {}
|
||||
};
|
||||
|
||||
/// Parallel job.
|
||||
struct Job
|
||||
{
|
||||
String name;
|
||||
Time time_start, time_end;
|
||||
|
||||
Threading::Atomic32 done;
|
||||
|
||||
/// Execute job.
|
||||
virtual void Execute(uint worker_id) = 0;
|
||||
|
||||
Job(const char *_name) : name(_name), done(1) {}
|
||||
virtual ~Job() {}
|
||||
};
|
||||
|
||||
/// Job group.
|
||||
class JobGroup
|
||||
{
|
||||
friend class JobManager;
|
||||
|
||||
AutoPtr <Threading::Mutex> job_list_mutex;
|
||||
List <Job *> job_list;
|
||||
|
||||
public:
|
||||
|
||||
JobGroup();
|
||||
};
|
||||
|
||||
//
|
||||
class JobManager
|
||||
{
|
||||
friend class JobWorkerThread;
|
||||
|
||||
protected:
|
||||
|
||||
Array <JobWorkerThread *> pool;
|
||||
|
||||
#if __USE_LOCK_FREE_JOB_QUEUE__
|
||||
mpmc_bounded_queue <Job *> pending_queue;
|
||||
#else
|
||||
AutoPtr <Mutex> pending_queue_mutex;
|
||||
Stack <Job *> pending_queue;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
Threading::Event job_queued_event;
|
||||
|
||||
/// Wait for a job to complete.
|
||||
bool JoinJob(Job *, bool blocking = true);
|
||||
/// Wait for a job group to complete.
|
||||
bool JoinGroup(JobGroup *, bool blocking = true);
|
||||
|
||||
/// Execute a pending job on the caller thread.
|
||||
bool ExecutePendingJob(uint worker_id);
|
||||
|
||||
bool EnqueueJob(Job * = 0, JobGroup * = 0);
|
||||
|
||||
/// Get the number of worker.
|
||||
uint GetWorkerPoolSize() const;
|
||||
|
||||
/// Create the job worker thread pool.
|
||||
bool CreateJobThreadPool(uint count = 0);
|
||||
/// Free the job worker thread pool.
|
||||
void FreeJobThreadPool();
|
||||
|
||||
JobManager();
|
||||
~JobManager();
|
||||
};
|
||||
|
||||
} // ASync
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __JOB_SYSTEM__
|
||||
55
include/platform/async/job_perf.h
Normal file
55
include/platform/async/job_perf.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __JOB_PERF__
|
||||
#define __JOB_PERF__
|
||||
|
||||
|
||||
#include "async/job.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace ASync {
|
||||
|
||||
//
|
||||
struct JobPerf
|
||||
{
|
||||
Time slice_duration;
|
||||
Time tasks_duration;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
slice_duration.setSec(0);
|
||||
tasks_duration.setSec(0);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
template <class Container> void CollectJobsPerf(const Container &jobs, uint count, JobPerf &perf)
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
Time slice_start = jobs[0]->time_start, slice_end = jobs[0]->time_end;
|
||||
|
||||
perf.tasks_duration += jobs[0]->time_end - jobs[0]->time_start;
|
||||
|
||||
for (uint n = 1; n < count; ++n)
|
||||
{
|
||||
slice_start = Types::Min(jobs[n]->time_start, slice_start);
|
||||
slice_end = Types::Max(jobs[n]->time_end, slice_end);
|
||||
|
||||
perf.tasks_duration += jobs[n]->time_end - jobs[n]->time_start;
|
||||
}
|
||||
|
||||
perf.slice_duration += slice_end - slice_start;
|
||||
};
|
||||
|
||||
} // ASync
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __JOB_PERF__
|
||||
40
include/platform/async/task_loop.h
Normal file
40
include/platform/async/task_loop.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NTASKLOOP__
|
||||
#define __NTASKLOOP__
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#define StartTaskLoop(_CONDITION, _TIMEOUT)\
|
||||
{\
|
||||
using namespace GS;\
|
||||
\
|
||||
int ref_clock = Platform::Get().GetClock();\
|
||||
bool timeout = false;\
|
||||
\
|
||||
while (_CONDITION)\
|
||||
{\
|
||||
if ((Platform::Get().GetClock() - ref_clock) >= _TIMEOUT)\
|
||||
{\
|
||||
timeout = true;\
|
||||
break;\
|
||||
}
|
||||
|
||||
#define EndTaskLoop } }
|
||||
|
||||
#define EndTaskLoopOnTimeout(_ON_TIMEOUT)\
|
||||
}\
|
||||
\
|
||||
if (timeout)\
|
||||
{\
|
||||
_ON_TIMEOUT\
|
||||
}\
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // __NTASKLOOP__
|
||||
37
include/platform/billing/billing.h
Normal file
37
include/platform/billing/billing.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __BILLING__
|
||||
#define __BILLING__
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short Billing system abstract interface.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
struct IBilling
|
||||
{
|
||||
// Process a billing event.
|
||||
virtual void onBillingEvent(const char *event, const char *item) = 0;
|
||||
|
||||
/// Returns true if the platform supports billing.
|
||||
virtual bool isBillingServiceSupported() = 0;
|
||||
/// Request a new purchase.
|
||||
virtual bool requestPurchase(const char *) = 0;
|
||||
/// Confirm a purchase.
|
||||
virtual bool confirmPurchase(const char *) = 0;
|
||||
/// Restore managed purchase states.
|
||||
virtual bool restorePurchases() = 0;
|
||||
|
||||
virtual ~IBilling() {}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __BILLING__
|
||||
57
include/platform/container/container_sort.h
Normal file
57
include/platform/container/container_sort.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __CONTAINER_SORT__
|
||||
#define __CONTAINER_SORT__
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
class ContainerSort
|
||||
{
|
||||
template <typename T, typename L> static inline void Swap(L &t, int i, int j)
|
||||
{
|
||||
if (i != j)
|
||||
{ T swap = t[j]; t[j] = t[i]; t[i] = swap; }
|
||||
}
|
||||
template <typename T, typename L, typename C> static int QuickSortPartition(L &t, C compare, int first, int last, int pivot)
|
||||
{
|
||||
Swap <T, L> (t, pivot, last);
|
||||
|
||||
int j = first;
|
||||
for (int i = first; i < last; ++i)
|
||||
if (compare(t[i], t[last]) > 0)
|
||||
{
|
||||
Swap <T, L> (t, i, j);
|
||||
++j;
|
||||
}
|
||||
|
||||
Swap <T, L> (t, j, last);
|
||||
return j;
|
||||
}
|
||||
template <typename T, typename L, typename C> static void QuickSortStep(L &t, C compare, int first, int last)
|
||||
{
|
||||
if (first < last)
|
||||
{
|
||||
int pivot = (first + last) / 2;
|
||||
pivot = QuickSortPartition <T, L, C> (t, compare, first, last, pivot);
|
||||
|
||||
QuickSortStep <T, L, C> (t, compare, first, pivot - 1);
|
||||
QuickSortStep <T, L, C> (t, compare, pivot + 1, last);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// Quick-sort a container in-place.
|
||||
template <typename T, typename L, typename C> static void QuickSort(L &t, C compare)
|
||||
{ QuickSortStep <T, L, C> (t, compare, 0, t.GetCount() - 1); }
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __CONTAINER_SORT__
|
||||
136
include/platform/container/mpmc_bounded_queue.h
Normal file
136
include/platform/container/mpmc_bounded_queue.h
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are
|
||||
those of the authors and should not be interpreted as representing official
|
||||
policies, either expressed or implied, of Dmitry Vyukov.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __MPMC_BOUNDED_QUEUE__
|
||||
#define __MPMC_BOUNDED_QUEUE__
|
||||
|
||||
|
||||
#include "thread/atomic_value.h"
|
||||
|
||||
|
||||
// Adapted from https://sites.google.com/site/1024cores/home/lock-free-algorithms/queues/bounded-mpmc-queue
|
||||
template<typename T> class mpmc_bounded_queue
|
||||
{
|
||||
struct cell_t
|
||||
{
|
||||
GS::Threading::Atomic32 sequence_;
|
||||
T data_;
|
||||
};
|
||||
|
||||
static size_t const cacheline_size = 64;
|
||||
typedef char cacheline_pad_t[cacheline_size];
|
||||
|
||||
cacheline_pad_t pad0_;
|
||||
cell_t * const buffer_;
|
||||
size_t const buffer_mask_;
|
||||
|
||||
cacheline_pad_t pad1_;
|
||||
GS::Threading::Atomic32 enqueue_pos_;
|
||||
cacheline_pad_t pad2_;
|
||||
GS::Threading::Atomic32 dequeue_pos_;
|
||||
cacheline_pad_t pad3_;
|
||||
|
||||
void operator = (mpmc_bounded_queue const&);
|
||||
|
||||
mpmc_bounded_queue(mpmc_bounded_queue const&);
|
||||
|
||||
public:
|
||||
|
||||
bool enqueue(T const &data)
|
||||
{
|
||||
cell_t *cell;
|
||||
int pos = enqueue_pos_.Get();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
cell = &buffer_[pos & buffer_mask_];
|
||||
size_t seq = cell->sequence_.Get();
|
||||
|
||||
intptr_t dif = (intptr_t)seq - (intptr_t)pos;
|
||||
|
||||
if (dif == 0)
|
||||
{
|
||||
if (enqueue_pos_.Cas(pos, pos + 1) == pos)
|
||||
break;
|
||||
}
|
||||
else if (dif < 0)
|
||||
return false;
|
||||
else
|
||||
pos = enqueue_pos_.Get();
|
||||
}
|
||||
|
||||
cell->data_ = data;
|
||||
cell->sequence_.Set(pos + 1);
|
||||
return true;
|
||||
}
|
||||
bool dequeue(T &data)
|
||||
{
|
||||
cell_t *cell;
|
||||
int pos = dequeue_pos_.Get();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
cell = &buffer_[pos & buffer_mask_];
|
||||
size_t seq = cell->sequence_.Get();
|
||||
|
||||
intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1);
|
||||
|
||||
if (dif == 0)
|
||||
{
|
||||
if (dequeue_pos_.Cas(pos, pos + 1) == pos)
|
||||
break;
|
||||
}
|
||||
else if (dif < 0)
|
||||
return false;
|
||||
else
|
||||
pos = dequeue_pos_.Get();
|
||||
}
|
||||
data = cell->data_;
|
||||
cell->sequence_.Set(pos + buffer_mask_ + 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
mpmc_bounded_queue(size_t buffer_size) : buffer_(new cell_t [buffer_size]), buffer_mask_(buffer_size - 1)
|
||||
{
|
||||
for (size_t i = 0; i != buffer_size; i += 1)
|
||||
buffer_[i].sequence_.Set(i);
|
||||
|
||||
enqueue_pos_.Set(0);
|
||||
dequeue_pos_.Set(0);
|
||||
}
|
||||
~mpmc_bounded_queue()
|
||||
{
|
||||
delete [] buffer_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // __MPMC_BOUNDED_QUEUE__
|
||||
215
include/platform/container/narray.h
Normal file
215
include/platform/container/narray.h
Normal file
@ -0,0 +1,215 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NARRAY__
|
||||
#define __NARRAY__
|
||||
|
||||
|
||||
#include "alloc/ialloc.h"
|
||||
#include "memory/memory.h"
|
||||
#include "assert/nassert.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short Managed array.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> class Array
|
||||
{
|
||||
uint count;
|
||||
T *data;
|
||||
|
||||
#if __ENABLE_ALLOCATION_STAT__
|
||||
Alloc::System system;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
inline operator T *() const
|
||||
{ return data; }
|
||||
inline T *c_ptr() const
|
||||
{ return data; }
|
||||
|
||||
inline T &operator [] (int n) const
|
||||
{ return data[n]; }
|
||||
inline T &operator [] (uint n) const
|
||||
{ return data[n]; }
|
||||
|
||||
void operator = (Array <T> &o) ///< Transfer assignation.
|
||||
{ Transfer(o); }
|
||||
|
||||
inline T *Start() const
|
||||
{ return data; }
|
||||
inline T *End() const
|
||||
{ return &data[count]; }
|
||||
|
||||
inline bool IsValid() const
|
||||
{ return data ? true : false; }
|
||||
inline bool IsNull() const
|
||||
{ return data ? false : true; }
|
||||
|
||||
/// Return the number of elements of type T in the buffer.
|
||||
inline uint GetCount() const
|
||||
{ return count; }
|
||||
/// Return the buffer size in bytes.
|
||||
inline size_t GetSize() const
|
||||
{ return count * sizeof(T); }
|
||||
|
||||
void Free()
|
||||
{
|
||||
if (data)
|
||||
__NSTAT_DELETE(count * sizeof(T), system);
|
||||
// _safe_delete_array(data);
|
||||
delete[] data;
|
||||
data = 0;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/// Reallocate buffer elements.
|
||||
bool Reallocate(uint new_count)
|
||||
{
|
||||
if (new_count == count)
|
||||
return true;
|
||||
|
||||
if (T *new_data = new T[new_count])
|
||||
{
|
||||
__NSTAT_ALLOC(new_count * sizeof(T), system);
|
||||
Memory::Copy(new_data, data, GetSize());
|
||||
|
||||
if (data)
|
||||
__NSTAT_DELETE(count * sizeof(T), system);
|
||||
// _safe_delete_array(data);
|
||||
delete[] data;
|
||||
data = 0;
|
||||
|
||||
data = new_data;
|
||||
count = new_count;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Allocate buffer elements.
|
||||
bool Allocate(uint _count)
|
||||
{
|
||||
/// @note We could add a small tolerance here to potentially reduce fragmentation?
|
||||
if (_count == count)
|
||||
return true;
|
||||
|
||||
Free();
|
||||
|
||||
if (_count && ((data = new T[_count]) == 0))
|
||||
return false;
|
||||
|
||||
__NSTAT_ALLOC(_count * sizeof(T), system);
|
||||
count = _count;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Relinquish ownership of the managed memory block.
|
||||
T *Detach()
|
||||
{
|
||||
T *r = data;
|
||||
data = 0;
|
||||
count = 0;
|
||||
return r;
|
||||
}
|
||||
/// Take ownership of a managed memory block.
|
||||
void Attach(uint _count, T *_data)
|
||||
{
|
||||
Free();
|
||||
count = _count;
|
||||
data = _data;
|
||||
}
|
||||
|
||||
/// Transfer data buffer.
|
||||
void Transfer(Array <T> &b)
|
||||
{
|
||||
Free();
|
||||
count = b.GetCount();
|
||||
data = b.Detach();
|
||||
#if __ENABLE_ALLOCATION_STAT__
|
||||
__NSTAT_DELETE(count * sizeof(T), b.system);
|
||||
__NSTAT_ALLOC(count * sizeof(T), system);
|
||||
#endif
|
||||
}
|
||||
/// Clone data buffer.
|
||||
bool Clone(const Array <T> &b)
|
||||
{
|
||||
Free();
|
||||
if (!Allocate(b.GetCount()))
|
||||
return false;
|
||||
for (uint n = 0; n < GetCount(); ++n)
|
||||
data[n] = b[n];
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Fill data buffer.
|
||||
void Fill(const T &v, uint from = 0, uint to = 0)
|
||||
{
|
||||
if (to <= 0)
|
||||
to = count + to;
|
||||
|
||||
__ASSERT__(from <= count);
|
||||
__ASSERT__(to <= count);
|
||||
for (uint n = from; n < to; ++n)
|
||||
data[n] = v;
|
||||
}
|
||||
|
||||
/// Swap two data buffer.
|
||||
static void Swap(Array <T> &a, Array <T> &b)
|
||||
{
|
||||
uint count_a = a.GetCount(), count_b = b.GetCount();
|
||||
T *data_a = a.Detach(), *data_b = b.Detach();
|
||||
a.Attach(count_b, data_b);
|
||||
b.Attach(count_a, data_a);
|
||||
}
|
||||
|
||||
Array(uint _count, Alloc::System sys = Alloc::General)
|
||||
{
|
||||
data = 0; count = 0;
|
||||
#if __ENABLE_ALLOCATION_STAT__
|
||||
system = sys;
|
||||
#endif
|
||||
Allocate(_count);
|
||||
}
|
||||
Array(uint _count, const T *_data, Alloc::System sys = Alloc::General)
|
||||
{
|
||||
data = 0; count = 0;
|
||||
#if __ENABLE_ALLOCATION_STAT__
|
||||
system = sys;
|
||||
#endif
|
||||
if (Allocate(_count))
|
||||
Memory::Copy(data, _data, sizeof(T) * _count);
|
||||
}
|
||||
Array(const Array <T> &array, Alloc::System sys = Alloc::General) ///< Copy constructor.
|
||||
{
|
||||
data = 0; count = 0;
|
||||
#if __ENABLE_ALLOCATION_STAT__
|
||||
system = sys;
|
||||
#endif
|
||||
Allocate(array.GetCount());
|
||||
Memory::Copy(data, array.c_ptr(), array.GetSize());
|
||||
}
|
||||
Array(Alloc::System sys = Alloc::General)
|
||||
{
|
||||
data = 0; count = 0;
|
||||
#if __ENABLE_ALLOCATION_STAT__
|
||||
system = sys;
|
||||
#endif
|
||||
}
|
||||
~Array()
|
||||
{ Free(); }
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NARRAY__
|
||||
268
include/platform/container/narray_list.h
Normal file
268
include/platform/container/narray_list.h
Normal file
@ -0,0 +1,268 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NARRAYLIST__
|
||||
#define __NARRAYLIST__
|
||||
|
||||
|
||||
#include "container/narray.h"
|
||||
#include "log/log.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short Array list.
|
||||
|
||||
A flexible structure with faster access time (both linear and random) and
|
||||
tighter memory usage than lists.
|
||||
|
||||
Especially suited for small types such as pointers.
|
||||
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> class ArrayList
|
||||
{
|
||||
Array <T> array;
|
||||
Array <uint> usage_map;
|
||||
|
||||
uint usage; ///< Array usage.
|
||||
uint grow_step;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool Grow()
|
||||
{
|
||||
if (int(usage) >= int(array.GetCount() - 1))
|
||||
return Resize(array.GetCount() + grow_step);
|
||||
return true;
|
||||
}
|
||||
inline bool Shrink()
|
||||
{
|
||||
if (((int)array.GetCount() - 1) > (int)grow_step)
|
||||
if ((int)usage < ((int)array.GetCount() - 1 - (int)grow_step))
|
||||
return Resize(array.GetCount() - grow_step);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class Iterator
|
||||
{
|
||||
const ArrayList <T> &list;
|
||||
uint i;
|
||||
|
||||
public:
|
||||
|
||||
inline void Reset(uint from = 0) { i = from; }
|
||||
inline bool IsOver() const { return i < list.GetCount() ? false : true; }
|
||||
|
||||
inline void operator++() { ++i; }
|
||||
|
||||
inline T &Object() { return list[i]; }
|
||||
inline T ObjectPtr() { return list[i]; }
|
||||
|
||||
Iterator(const ArrayList <T> &_list, uint from = 0) : list(_list), i(from) {}
|
||||
};
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline uint GetCount() const
|
||||
{ return usage; }
|
||||
|
||||
inline T &ObjectAt(int n) const
|
||||
{ return array[usage_map[n]]; }
|
||||
inline T &ObjectAt(uint n) const
|
||||
{ return array[usage_map[n]]; }
|
||||
|
||||
inline T &operator [] (int n) const
|
||||
{ return array[usage_map[n]]; }
|
||||
inline T &operator [] (uint n) const
|
||||
{ return array[usage_map[n]]; }
|
||||
|
||||
inline void SetGrowStep(uint step)
|
||||
{ grow_step = step; }
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// Insert a new value in the list.
|
||||
virtual bool Insert(const T &v, uint at)
|
||||
{
|
||||
Grow();
|
||||
|
||||
// Claim entry...
|
||||
uint claimed = usage_map[usage];
|
||||
|
||||
// ...and shift usage map.
|
||||
for (int n = (int)usage - 1; n >= (int)at; --n)
|
||||
usage_map[n + 1] = usage_map[n];
|
||||
|
||||
usage_map[at] = claimed;
|
||||
usage++;
|
||||
|
||||
array[claimed] = v;
|
||||
array[usage_map[usage]] = 0; // enforce terminator
|
||||
return true;
|
||||
}
|
||||
/// Add a new value to the end of the list.
|
||||
bool Add(const T &v)
|
||||
{
|
||||
return Insert(v, usage);
|
||||
}
|
||||
/// Return the index at which a value is first found in the list.
|
||||
int IndexOf(const T &v, uint from = 0)
|
||||
{
|
||||
for (uint i = from; i < usage; ++i)
|
||||
if (array[usage_map[i]] == v)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
/// Remove an entry from the list.
|
||||
virtual bool RemoveAt(uint i)
|
||||
{
|
||||
if (usage == 0)
|
||||
return false;
|
||||
|
||||
// Reclaim entry...
|
||||
uint reclaimed = usage_map[i];
|
||||
|
||||
// ...and shift usage map.
|
||||
for (uint n = i + 1; n < usage; ++n)
|
||||
usage_map[n - 1] = usage_map[n];
|
||||
|
||||
usage_map[usage - 1] = reclaimed;
|
||||
usage--;
|
||||
|
||||
array[reclaimed] = 0; // enforce terminator
|
||||
|
||||
Shrink();
|
||||
return true;
|
||||
}
|
||||
bool Remove(const T &v)
|
||||
{
|
||||
int i = IndexOf(v);
|
||||
return i != -1 ? RemoveAt(i) : false;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ArrayList <T> &operator = (const T &v)
|
||||
{
|
||||
if (this != &v)
|
||||
{
|
||||
Clear();
|
||||
for (uint n = 0; n < v.GetCount(); ++n)
|
||||
Add(v[n]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
ArrayList <T> &operator << (const T &v)
|
||||
{
|
||||
Add(v);
|
||||
return *this;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool Resize(uint new_size)
|
||||
{
|
||||
if ((int)new_size == (int)array.GetCount() - 1)
|
||||
return true;
|
||||
|
||||
Array <T> _array(new_size + 1);
|
||||
if (_array.IsNull())
|
||||
__ERR__(__LOG_E__ << "Failed to allocate new array.\n", false)
|
||||
|
||||
for (uint n = 0; n < usage; ++n)
|
||||
_array[n] = array[usage_map[n]];
|
||||
array.Transfer(_array);
|
||||
|
||||
if (!usage_map.Allocate(new_size + 1))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate array bookkeeping structures.\n", false)
|
||||
|
||||
for (uint n = 0; n < (new_size + 1); ++n)
|
||||
usage_map[n] = n;
|
||||
|
||||
array[usage_map[usage]] = 0; // enforce terminator
|
||||
return true;
|
||||
}
|
||||
/*!
|
||||
@short Clear the container.
|
||||
|
||||
Pass false to prevent the internal structures from being released,
|
||||
the array list will keep its current capacity and only its usage map
|
||||
will be reset.
|
||||
*/
|
||||
virtual void Clear(bool free_internals = true)
|
||||
{
|
||||
usage = 0;
|
||||
|
||||
if (free_internals)
|
||||
Resize(0);
|
||||
else
|
||||
{
|
||||
for (uint n = 0; n < array.GetCount(); ++n)
|
||||
usage_map[n] = n;
|
||||
array[0] = 0; // enforce terminator
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
ArrayList(uint initial_size = 0, uint step = 64) : usage(0), grow_step(step) { Resize(initial_size); }
|
||||
virtual ~ArrayList() {}
|
||||
};
|
||||
|
||||
/*
|
||||
@short Shared object array list.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> struct SharedArrayList : public ArrayList <T>
|
||||
{
|
||||
virtual bool Insert(const T &v, uint at)
|
||||
{
|
||||
v->AddRef();
|
||||
return ArrayList <T> ::Insert(v, at);
|
||||
}
|
||||
virtual bool RemoveAt(uint i)
|
||||
{
|
||||
(*this)[i]->RemoveRef();
|
||||
return ArrayList <T> :: RemoveAt(i);
|
||||
}
|
||||
virtual void Clear(bool free_internals = true)
|
||||
{
|
||||
for (uint n = 0; n < this->GetCount(); ++n)
|
||||
(*this)[n]->RemoveRef();
|
||||
return ArrayList <T> ::Clear(free_internals);
|
||||
}
|
||||
virtual ~SharedArrayList()
|
||||
{ Clear(); }
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Delete all list entries.
|
||||
#define ArrayListDeleteAllPtr(T, L) { for (uint __n = 0; __n < (L).GetCount(); ++__n) delete (L)[__n]; (L).Clear(); }
|
||||
// Iterate over a list of pointers.
|
||||
#define ArrayListForeachPtr(T, V, L) \
|
||||
for (ArrayList <T> ::Iterator iterator(L); T V = iterator.ObjectPtr(); ++iterator)
|
||||
// Iterate over a list of objects.
|
||||
#define ArrayListForeach(T, V, L) \
|
||||
for (ArrayList <T> ::Iterator V(L); V.IsOver() == false; ++V)
|
||||
|
||||
/// Find item by using a template identification class.
|
||||
template <typename T, typename F, typename P> T ArrayListFindEx(const ArrayList <T> &list, F filter, const P &what)
|
||||
{
|
||||
for (uint __n = 0; __n < list.GetCount(); ++__n)
|
||||
if (filter(list[__n], what))
|
||||
return list[__n];
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NARRAYLIST__
|
||||
604
include/platform/container/nlist.h
Normal file
604
include/platform/container/nlist.h
Normal file
@ -0,0 +1,604 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NLIST__
|
||||
#define __NLIST__
|
||||
|
||||
|
||||
#include "alloc/ialloc.h"
|
||||
#include "assert/nassert.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*
|
||||
@short List.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> class List
|
||||
{
|
||||
public:
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class Item
|
||||
{
|
||||
friend class List <T>;
|
||||
|
||||
T o;
|
||||
Item *p, *n;
|
||||
|
||||
public:
|
||||
|
||||
NPLACEMENT_NEW(ListItem)
|
||||
|
||||
/// Return the previous list link.
|
||||
inline Item *Previous() const { return p; }
|
||||
/// Return the next list link.
|
||||
inline Item *Next() const { return n; }
|
||||
|
||||
/// Retrieve a reference to the item object.
|
||||
inline T &Object() { return o; }
|
||||
|
||||
Item(const T &obj)
|
||||
{
|
||||
o = obj;
|
||||
p = n = 0;
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class Iterator
|
||||
{
|
||||
Item *c, *n;
|
||||
|
||||
public:
|
||||
|
||||
inline void operator++()
|
||||
{
|
||||
if ((c = c ? n : 0) != 0)
|
||||
n = c->n;
|
||||
}
|
||||
|
||||
inline bool IsOver() const { return c ? false : true; }
|
||||
inline Item *Next() const { return n; }
|
||||
|
||||
inline Item *GetItem() const { return c; }
|
||||
inline T &Object() { return c->Object(); }
|
||||
|
||||
/// Only use when using a pointer type.
|
||||
inline T ObjectPtr() { return c ? c->Object() : 0; }
|
||||
|
||||
void Reset(Item *start = 0)
|
||||
{
|
||||
c = start;
|
||||
n = c ? c->Next() : 0;
|
||||
}
|
||||
Iterator(Item *start = 0)
|
||||
{ Reset(start); }
|
||||
};
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
|
||||
uint count;
|
||||
Item *root, *last;
|
||||
|
||||
public:
|
||||
|
||||
/// Get item count in list.
|
||||
inline uint GetCount() const { return count; }
|
||||
/// Get root item.
|
||||
inline Item *GetRoot() const { return root; }
|
||||
/// Get last item.
|
||||
inline Item *GetLast() const { return last; }
|
||||
|
||||
/// Clone list.
|
||||
void Clone(List <T> &clone_list) const
|
||||
{
|
||||
clone_list.Clear();
|
||||
for (Item *_i = root; _i; _i = _i->Next())
|
||||
clone_list.Add(_i->Object());
|
||||
}
|
||||
|
||||
/// Get item from position.
|
||||
Item *ItemAt(uint n) const
|
||||
{
|
||||
if (n > count)
|
||||
return 0;
|
||||
|
||||
Item *p = root;
|
||||
while (n--)
|
||||
p = p->n;
|
||||
|
||||
return p;
|
||||
}
|
||||
inline T &ObjectAt(uint n) const
|
||||
{ return ItemAt(n)->Object(); }
|
||||
inline T &operator[] (uint n) const
|
||||
{ return ItemAt(n)->Object(); }
|
||||
|
||||
/// Get index of a given item.
|
||||
int Index(const T &o) const
|
||||
{
|
||||
int pos = 0;
|
||||
for (Item *p = root; p; p = p->n)
|
||||
{
|
||||
if (p->Object() == o)
|
||||
return pos;
|
||||
pos++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Check whether a given item belongs to this list or not.
|
||||
bool Belongs(Item *i) const
|
||||
{
|
||||
for (Item *s = root; s; s = s->n)
|
||||
if (s == i)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Insert item after a given reference item (defaults to last).
|
||||
virtual Item *Append(const T &o, Item *rfr = 0)
|
||||
{
|
||||
Item *i = new Item(o);
|
||||
if (!i)
|
||||
return 0;
|
||||
|
||||
if (!rfr)
|
||||
{
|
||||
i->p = last;
|
||||
if (last)
|
||||
last->n = i;
|
||||
else
|
||||
root = i;
|
||||
last = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rfr->n)
|
||||
rfr->n->p = i;
|
||||
i->n = rfr->n;
|
||||
rfr->n = i;
|
||||
i->p = rfr;
|
||||
|
||||
if (last == rfr) // Update last.
|
||||
last = i;
|
||||
}
|
||||
|
||||
count++;
|
||||
return i;
|
||||
}
|
||||
|
||||
/// Insert item before a given reference item (defaults to root).
|
||||
virtual Item *Prepend(const T &o, Item *rfr = 0)
|
||||
{
|
||||
Item *i = new Item(o);
|
||||
if (!i)
|
||||
return 0;
|
||||
|
||||
if (!rfr)
|
||||
{
|
||||
i->n = root;
|
||||
if (root)
|
||||
root->p = i;
|
||||
else
|
||||
last = i;
|
||||
root = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rfr->p)
|
||||
rfr->p->n = i;
|
||||
i->p = rfr->p;
|
||||
rfr->p = i;
|
||||
i->n = rfr;
|
||||
|
||||
if (root == rfr) // Update root.
|
||||
root = i;
|
||||
}
|
||||
|
||||
count++;
|
||||
return i;
|
||||
}
|
||||
|
||||
/// Insert a value at a given position.
|
||||
Item *Insert(const T &v, uint at)
|
||||
{
|
||||
Item *rfr = ItemAt(at);
|
||||
return rfr ? Prepend(v, rfr) : 0;
|
||||
}
|
||||
|
||||
/// Add item to list.
|
||||
Item *Add(const T &o, bool append, bool allow_duplicate)
|
||||
{
|
||||
if (!allow_duplicate)
|
||||
if (Item *i = Find(o))
|
||||
return i;
|
||||
return append ? Append(o) : Prepend(o);
|
||||
}
|
||||
/// Add item to list.
|
||||
Item *Add(const T &o)
|
||||
{ return Append(o); }
|
||||
|
||||
/// Add item to list.
|
||||
List <T> &operator << (const T &o)
|
||||
{
|
||||
Add(o);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Find item by reference to object.
|
||||
Item *Find(const T &o) const
|
||||
{
|
||||
for (Item *p = root; p; p = p->n)
|
||||
if (p->Object() == o)
|
||||
return p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Find item by object value.
|
||||
Item *FindByValue(const T &o) const
|
||||
{
|
||||
for (Item *p = root; p; p = p->n)
|
||||
if (*p->Object() == *o)
|
||||
return p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
@short Subtract two given lists by object value.
|
||||
@warning The resulting list holds pointers to the original objects.
|
||||
*/
|
||||
static List <T> *SubtractByValue(const List <T> &what, const List <T> &from)
|
||||
{
|
||||
List <T> *list = new List <T>;
|
||||
if (list)
|
||||
for (Item *f_p = from.root; f_p; f_p = f_p->n)
|
||||
if (!what.FindByValue(f_p->Object()))
|
||||
list->Add(f_p->Object());
|
||||
return list;
|
||||
}
|
||||
|
||||
/*!
|
||||
@short Subtract two given lists by object address.
|
||||
@warning The resulting list holds pointers to the original objects.
|
||||
*/
|
||||
static List <T> *SubtractByAddress(const List <T> &what, const List <T> &from)
|
||||
{
|
||||
List <T> *list = new List <T>;
|
||||
if (list)
|
||||
for (Item *f_p = from.root; f_p; f_p = f_p->n)
|
||||
if (!what.Find(f_p->Object()))
|
||||
list->Add(f_p->Object());
|
||||
return list;
|
||||
}
|
||||
|
||||
/// Filter out linked-list item function.
|
||||
template <typename F> void FilterOut(F filter)
|
||||
{
|
||||
for (Item *c = GetRoot(); c; )
|
||||
{
|
||||
Item *n = c->Next();
|
||||
if (filter(c->Object()))
|
||||
Remove(c);
|
||||
c = n;
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a new list from select items.
|
||||
template <typename F, typename P> uint Select(List <T> &out, F filter, const P &filter_param) const
|
||||
{
|
||||
out.Clear();
|
||||
for (Item *c = GetRoot(); c; )
|
||||
if (filter(c->Object(), filter_param))
|
||||
out.Add(c->Object());
|
||||
return out.GetCount();
|
||||
}
|
||||
|
||||
/// Sort linked-list function.
|
||||
template <typename C> void Sort(C compare)
|
||||
{
|
||||
for (bool swapped = true; swapped; )
|
||||
{
|
||||
swapped = false;
|
||||
|
||||
for (Item *c = GetRoot(); c; )
|
||||
{
|
||||
Item *n = c->Next();
|
||||
if (!n)
|
||||
break;
|
||||
|
||||
if (compare(c->Object(), n->Object()) < 0)
|
||||
{
|
||||
swapped = true;
|
||||
|
||||
c->n = n->n;
|
||||
n->n = c;
|
||||
n->p = c->p;
|
||||
c->p = n;
|
||||
|
||||
if (n->p)
|
||||
n->p->n = n;
|
||||
else root = n;
|
||||
|
||||
if (c->n)
|
||||
c->n->p = c;
|
||||
else last = c;
|
||||
}
|
||||
else
|
||||
c = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge sort linked-list function.
|
||||
template <typename C> void MergeSort(C compare)
|
||||
{
|
||||
Item *list = root, *tail = 0;
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
for (int insize = 1; ; insize *= 2)
|
||||
{
|
||||
Item *p = list;
|
||||
list = 0;
|
||||
tail = 0;
|
||||
|
||||
int merge_count = 0; // Count number of merges we do in this pass.
|
||||
|
||||
while (p)
|
||||
{
|
||||
merge_count++;
|
||||
|
||||
// Step along from p.
|
||||
Item *q = p;
|
||||
int psize = 0;
|
||||
for ( ; q && (psize < insize); ++psize)
|
||||
q = q->Next();
|
||||
|
||||
// If q hasn't fallen off end, we have two lists to merge.
|
||||
int qsize = insize;
|
||||
|
||||
// Now we have two lists, merge them.
|
||||
while (psize > 0 || (qsize > 0 && q))
|
||||
{
|
||||
Item *e;
|
||||
|
||||
if (!psize) // p is empty, e must come from q.
|
||||
{ e = q; q = q->Next(); qsize--; }
|
||||
else if (!qsize || !q) // q is empty, e must come from p.
|
||||
{ e = p; p = p->Next(); psize--; }
|
||||
else if (compare(p->Object(), q->Object()) <= 0) // First element of p is lower (or same), e must come from p.
|
||||
{ e = p; p = p->Next(); psize--; }
|
||||
else // First element of q is lower; e must come from q.
|
||||
{ e = q; q = q->Next(); qsize--; }
|
||||
|
||||
// Add the next element to the merged list.
|
||||
if (tail)
|
||||
tail->n = e;
|
||||
else list = e;
|
||||
|
||||
e->p = tail;
|
||||
tail = e;
|
||||
}
|
||||
|
||||
// Now p has stepped `insize' places along, and q has too.
|
||||
p = q;
|
||||
}
|
||||
|
||||
tail->n = 0;
|
||||
|
||||
// If we have done only one merge, we're done.
|
||||
if (merge_count <= 1)
|
||||
break;
|
||||
}
|
||||
|
||||
root = list;
|
||||
last = tail;
|
||||
}
|
||||
|
||||
/// Extract object from list.
|
||||
Item *ExtractItem(const T &o)
|
||||
{
|
||||
Item*i = Find(o);
|
||||
return i ? ExtractItem(i) : 0;
|
||||
}
|
||||
|
||||
/// Extract item from list.
|
||||
Item *ExtractItem(Item *i)
|
||||
{
|
||||
if (!i)
|
||||
return 0;
|
||||
|
||||
__ASSERT__(Belongs(i));
|
||||
|
||||
if (i->p)
|
||||
i->p->n = i->n;
|
||||
else
|
||||
{
|
||||
if (i->n)
|
||||
i->n->p = 0;
|
||||
root = i->n;
|
||||
}
|
||||
|
||||
if (i->n)
|
||||
i->n->p = i->p;
|
||||
else
|
||||
{
|
||||
if (i->p)
|
||||
i->p->n = 0;
|
||||
last = i->p;
|
||||
}
|
||||
|
||||
i->p = i->n = 0;
|
||||
|
||||
--count;
|
||||
return i;
|
||||
}
|
||||
/// Extract item at position.
|
||||
Item *ExtractAt(uint n)
|
||||
{
|
||||
Item *i = ItemAt(n);
|
||||
return i ? ExtractItem(i) : 0;
|
||||
}
|
||||
|
||||
/// Remove item from list.
|
||||
virtual bool Remove(Item *i)
|
||||
{
|
||||
if (ExtractItem(i) == 0)
|
||||
return false;
|
||||
|
||||
delete i;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Remove item from list.
|
||||
virtual bool Remove(const T &o)
|
||||
{
|
||||
return Remove(Find(o));
|
||||
}
|
||||
|
||||
/// Remove item at position.
|
||||
bool RemoveAt(uint n)
|
||||
{
|
||||
Item *i = ItemAt(n);
|
||||
return i ? Remove(i) : false;
|
||||
}
|
||||
|
||||
/// Remove all items from the list.
|
||||
virtual void Clear()
|
||||
{
|
||||
for (Item *p = root, *n; p; p = n)
|
||||
{
|
||||
n = p->n;
|
||||
delete p;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
root = last = 0;
|
||||
}
|
||||
|
||||
List()
|
||||
{
|
||||
count = 0;
|
||||
root = last = 0;
|
||||
}
|
||||
virtual ~List()
|
||||
{ Clear(); }
|
||||
};
|
||||
|
||||
/*
|
||||
@short Auto linked-list.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> struct AutoList : public List <T>
|
||||
{
|
||||
virtual bool Remove(class List <T> ::Item *i)
|
||||
{
|
||||
T o = i->Object();
|
||||
if (!List <T> ::Remove(i))
|
||||
return false;
|
||||
delete o;
|
||||
return true;
|
||||
}
|
||||
virtual bool Remove(const T &o)
|
||||
{
|
||||
class List <T> ::Item *i = this->Find(o);
|
||||
return i ? this->Remove(i) : false;
|
||||
}
|
||||
|
||||
virtual void Clear()
|
||||
{
|
||||
for (class List <T> ::Item *p = this->root; p; p = p->Next())
|
||||
delete p->Object();
|
||||
List <T> ::Clear();
|
||||
}
|
||||
virtual ~AutoList()
|
||||
{ this->Clear(); }
|
||||
};
|
||||
|
||||
/*
|
||||
@short Shared object linked-list.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> struct SharedList : public List <T>
|
||||
{
|
||||
virtual class List <T> ::Item *Append(const T &o, class List <T> ::Item *rfr = 0)
|
||||
{
|
||||
class List <T> ::Item *i = List <T> ::Append(o, rfr);
|
||||
if (i)
|
||||
o->AddRef();
|
||||
return i;
|
||||
}
|
||||
virtual class List <T> ::Item *Prepend(const T &o, class List <T> ::Item *rfr = 0)
|
||||
{
|
||||
class List <T> ::Item *i = List <T> ::Prepend(o, rfr);
|
||||
if (i)
|
||||
o->AddRef();
|
||||
return i;
|
||||
}
|
||||
|
||||
virtual bool Remove(class List <T> ::Item *i)
|
||||
{
|
||||
T o = i->Object();
|
||||
if (!List <T> ::Remove(i))
|
||||
return false;
|
||||
o->RemoveRef();
|
||||
return true;
|
||||
}
|
||||
virtual bool Remove(const T &o)
|
||||
{
|
||||
class List <T> ::Item *i = this->Find(o);
|
||||
return i ? this->Remove(i) : false;
|
||||
}
|
||||
|
||||
virtual void Clear()
|
||||
{
|
||||
for (class List <T> ::Item *p = this->root; p; p = p->Next())
|
||||
p->Object()->RemoveRef();
|
||||
List <T> ::Clear();
|
||||
}
|
||||
virtual ~SharedList()
|
||||
{ Clear(); }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Delete all list entries.
|
||||
#define ListDeleteAllPtr(T, L) { class GS::List <T> ::Item *t; while ((t = (L).GetRoot()) != 0) { T _o = t->Object(); (L).Remove(t); delete(_o); } }
|
||||
// Iterate over a list of pointers.
|
||||
#define ListForeachPtr(T, V, L) \
|
||||
for (class GS::List <T> ::Iterator iterator((L).GetRoot()); T V = iterator.ObjectPtr(); ++iterator)
|
||||
// Iterate over a list of objects.
|
||||
#define ListForeach(T, V, L) \
|
||||
for (class GS::List <T> ::Iterator V((L).GetRoot()); V.IsOver() == false; ++V)
|
||||
|
||||
/// Find item by using a template identification class.
|
||||
template <typename T, typename F, typename P> T ListFindEx(const List <T> &list, F filter, const P &what)
|
||||
{
|
||||
for (class List <T> ::Item *p = list.GetRoot(); p; p = p->Next())
|
||||
if (filter(p->Object(), what))
|
||||
return p->Object();
|
||||
return 0;
|
||||
}
|
||||
/// Remove all items with a reference count of 1 from a shared list.
|
||||
template <class T> uint PurgeSharedList(SharedList <T *> &list)
|
||||
{
|
||||
uint c = list.GetCount();
|
||||
ListForeachPtr(T *, t, list)
|
||||
if (t->GetRefCount() == 1)
|
||||
list.Remove(iterator.GetItem());
|
||||
return c - list.GetCount();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NLIST__
|
||||
68
include/platform/container/nmap.h
Normal file
68
include/platform/container/nmap.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*------------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NMAP__
|
||||
#define __NMAP__
|
||||
|
||||
|
||||
#include "container/nlist.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
//
|
||||
template <class KType, class VType> struct Pair
|
||||
{
|
||||
KType key;
|
||||
VType value;
|
||||
|
||||
Pair(const KType _key, const VType _value) : key(_key), value(_value) {}
|
||||
};
|
||||
|
||||
/*!
|
||||
@short Very naive map.
|
||||
@todo Red-black tree.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
template <class KType, class VType> class Map
|
||||
{
|
||||
AutoList <Pair <KType, VType> *> pairs;
|
||||
|
||||
public:
|
||||
|
||||
Pair <KType, VType> *Get(const KType &key) const
|
||||
{
|
||||
for (typename List <Pair <KType, VType> *> ::Item *p = pairs.GetRoot(); p; p = p->Next())
|
||||
if (p->Object()->key == key)
|
||||
return p->Object();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint GetCount() const
|
||||
{ return pairs.GetCount(); }
|
||||
|
||||
bool HasKey(const KType &key) const
|
||||
{ return asbool(Get(key)); }
|
||||
VType &operator [] (const KType &key) const
|
||||
{ return Get(key)->value; }
|
||||
|
||||
Pair <KType, VType> *Add(const KType &key, const VType &value)
|
||||
{
|
||||
AutoPtr <Pair <KType, VType> > pair(new Pair <KType, VType> (key, value));
|
||||
return pair.IsValid() && pairs.Add(pair) ? pair.Detach() : 0;
|
||||
}
|
||||
|
||||
bool Delete(Pair <KType, VType> *pair)
|
||||
{ return pairs.Remove(pair); }
|
||||
bool Delete(const KType &key)
|
||||
{ return Delete(Get(key)); }
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NMAP__
|
||||
150
include/platform/container/nstack.h
Normal file
150
include/platform/container/nstack.h
Normal file
@ -0,0 +1,150 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NSTACK__
|
||||
#define __NSTACK__
|
||||
|
||||
|
||||
#include "container/narray.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short Simple value stack.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
template <class T> class Stack
|
||||
{
|
||||
protected:
|
||||
|
||||
Array <T> data;
|
||||
|
||||
uint usage;
|
||||
uint grow_step;
|
||||
|
||||
public:
|
||||
|
||||
inline const T &operator [] (int n) const
|
||||
{ return data[n]; }
|
||||
inline const T &Top() const
|
||||
{ return data[usage - 1]; }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
T *Detach()
|
||||
{
|
||||
usage = 0;
|
||||
return data.Detach();
|
||||
}
|
||||
virtual void Transfer(Stack <T> &from)
|
||||
{
|
||||
usage = from.GetCount();
|
||||
data.Transfer(from.data);
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// Push a value on top of the stack.
|
||||
virtual bool Push(const T &v)
|
||||
{
|
||||
if (usage == data.GetCount())
|
||||
if (!data.Reallocate(usage + 64))
|
||||
return false;
|
||||
|
||||
data[usage++] = v;
|
||||
return true;
|
||||
}
|
||||
/// Pop a value from the stack.
|
||||
virtual void Pop()
|
||||
{
|
||||
if (usage > 0)
|
||||
--usage;
|
||||
}
|
||||
inline bool Add(const T &v)
|
||||
{ return Push(v); }
|
||||
inline Stack <T> &operator << (const T &v)
|
||||
{
|
||||
Add(v);
|
||||
return *this;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline uint GetCount() const
|
||||
{ return usage; }
|
||||
inline void SetGrowStep(uint step)
|
||||
{ grow_step = step; }
|
||||
virtual void Clear(bool free_internals = true)
|
||||
{
|
||||
if (free_internals)
|
||||
data.Free();
|
||||
usage = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline int Index(const T &v) const
|
||||
{
|
||||
for (uint n = 0; n < usage; ++n)
|
||||
if (data[n] == v)
|
||||
return n;
|
||||
return -1;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
Stack(uint size = 0, uint step = 64) : usage(0), grow_step(step) { data.Allocate(size); }
|
||||
virtual ~Stack() {}
|
||||
};
|
||||
|
||||
/// Auto-stack.
|
||||
template <class T> struct AutoStack : public Stack <T>
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
virtual void Transfer(Stack <T> &from)
|
||||
{
|
||||
for (uint n = 0; n < this->usage; ++n)
|
||||
delete this->data[n];
|
||||
Stack <T> ::Transfer(from);
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
virtual void Pop()
|
||||
{
|
||||
if (this->usage > 0)
|
||||
delete this->data[--this->usage];
|
||||
}
|
||||
virtual void Clear(bool free_internals = true)
|
||||
{
|
||||
for (uint n = 0; n < this->usage; ++n)
|
||||
delete this->data[n];
|
||||
Stack <T> ::Clear(free_internals);
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/*!
|
||||
@short Drop all pointers managed by this stack, does not free the storage.
|
||||
|
||||
The dropped pointers are expected to have been taken care of as this
|
||||
container will completely forget about them.
|
||||
*/
|
||||
void DropContentOwnership()
|
||||
{
|
||||
for (uint n = 0; n < this->usage; ++n)
|
||||
this->data[n] = 0;
|
||||
this->usage = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
AutoStack(uint size = 0, uint step = 64) : Stack <T> (size, step) {}
|
||||
virtual ~AutoStack() { Clear(); }
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NSTACK__
|
||||
161
include/platform/container/pair.h
Normal file
161
include/platform/container/pair.h
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TMPL_PAIRLIST__
|
||||
#define __TMPL_PAIRLIST__
|
||||
|
||||
|
||||
#include "data/array_list.h"
|
||||
#include "platform_config.h"
|
||||
|
||||
|
||||
//
|
||||
template <class PAIR, class TYPE> class ntPairList;
|
||||
|
||||
|
||||
/*
|
||||
@short Pair item.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class TYPE> class ntPairItem : public nArrayEntry
|
||||
{
|
||||
protected:
|
||||
|
||||
int hash;
|
||||
|
||||
public:
|
||||
|
||||
TYPE *a, *b; ///< Object pair.
|
||||
void *pair_data; ///< Pair associated data block.
|
||||
|
||||
/// Compute pair hash value.
|
||||
static int ComputeHash(TYPE *_a, TYPE *_b)
|
||||
{
|
||||
int hash = (((uintptr_t)_a) & 0xf0f0f0f0) | (((uintptr_t)_b) & 0x0f0f0f0f);
|
||||
hash = (hash + 0x7ed55d16) + (hash << 12);
|
||||
hash = (hash ^ 0xc761c23c) ^ (hash >> 19);
|
||||
hash = (hash + 0x165667b1) + (hash << 5);
|
||||
hash = (hash + 0xd3a2646c) ^ (hash << 9);
|
||||
hash = (hash + 0xfd7046c5) + (hash << 3);
|
||||
hash = (hash ^ 0xb55a4f09) ^ (hash >> 16);
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// Get pair hash.
|
||||
int Hash() const { return hash; }
|
||||
|
||||
ntPairItem(TYPE *_a, TYPE *_b)
|
||||
{
|
||||
a = _a; b = _b;
|
||||
hash = ComputeHash(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
struct ntPairListPool
|
||||
{
|
||||
uint bucket,
|
||||
entry;
|
||||
|
||||
void Reset()
|
||||
{ bucket = entry = 0; }
|
||||
|
||||
ntPairListPool()
|
||||
{ Reset(); }
|
||||
};
|
||||
|
||||
/*
|
||||
@short Pair list.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class PAIR, class TYPE> class ntPairList
|
||||
{
|
||||
|
||||
#define PairListBucketCount 64
|
||||
#define OrderPairItems(_A_, _B_) { if (_A_ > _B_) { TYPE *t = _A_; _A_ = _B_; _B_ = t; } }
|
||||
|
||||
protected:
|
||||
|
||||
uint count;
|
||||
nArrayList bucket[PairListBucketCount];
|
||||
|
||||
public:
|
||||
|
||||
/// Get item count in list.
|
||||
uint GetCount() const
|
||||
{ return count; }
|
||||
|
||||
/// Pool list.
|
||||
PAIR *Pool(ntPairListPool &pool) const
|
||||
{
|
||||
while (pool.bucket < PairListBucketCount)
|
||||
{
|
||||
if (pool.entry < bucket[pool.bucket].GetCount())
|
||||
break;
|
||||
|
||||
pool.entry = 0;
|
||||
pool.bucket++;
|
||||
}
|
||||
if (pool.bucket == PairListBucketCount)
|
||||
return 0;
|
||||
return (PAIR *)bucket[pool.bucket][pool.entry++];
|
||||
}
|
||||
|
||||
/// Add a pair.
|
||||
PAIR *Add(TYPE *a, TYPE *b)
|
||||
{
|
||||
OrderPairItems(a, b);
|
||||
|
||||
PAIR *pair = new PAIR(a, b);
|
||||
if (pair && !bucket[pair->Hash() & (PairListBucketCount - 1)].Add(pair))
|
||||
_safe_delete(pair);
|
||||
else
|
||||
count++;
|
||||
return pair;
|
||||
}
|
||||
|
||||
/// Find a pair.
|
||||
PAIR *Find(TYPE *a, TYPE *b)
|
||||
{
|
||||
OrderPairItems(a, b);
|
||||
|
||||
int hash = PAIR::ComputeHash(a, b);
|
||||
nArrayList &h_bucket = bucket[hash & (PairListBucketCount - 1)];
|
||||
|
||||
for (uint n = 0; n < h_bucket.GetCount(); ++n)
|
||||
{
|
||||
PAIR *pair = (PAIR *)h_bucket[n];
|
||||
if ((pair->a == a) && (pair->b == b))
|
||||
return pair;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Remove pair.
|
||||
bool Remove(PAIR *pair)
|
||||
{
|
||||
if (bucket[pair->Hash() & (PairListBucketCount - 1)].Delete(pair))
|
||||
{
|
||||
count--;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Delete all pair.
|
||||
void DeleteAll(bool freedata = true)
|
||||
{
|
||||
for (int n = 0; n < PairListBucketCount; ++n)
|
||||
bucket[n].DeleteAll(freedata);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
ntPairList()
|
||||
{ count = 0; }
|
||||
};
|
||||
|
||||
|
||||
#endif // __TMPL_PAIRLIST__
|
||||
62
include/platform/container/smart_median_average.h
Normal file
62
include/platform/container/smart_median_average.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __SMARTMEDIANAVG__
|
||||
#define __SMARTMEDIANAVG__
|
||||
|
||||
|
||||
#include "sort/sort.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
//
|
||||
template <class T, int Size = 16, int SafeGuard = 4> class SmartMedianAverage
|
||||
{
|
||||
T history[Size];
|
||||
int count;
|
||||
|
||||
public:
|
||||
|
||||
void LogValue(T v)
|
||||
{
|
||||
if (count < Size)
|
||||
count++; // fill up
|
||||
else
|
||||
for (int n = 1; n < Size; ++n) // scroll
|
||||
history[n - 1] = history[n];
|
||||
|
||||
history[count - 1] = v;
|
||||
}
|
||||
T GetMedian() const
|
||||
{
|
||||
if (count == 0)
|
||||
return 0;
|
||||
if (count < Size)
|
||||
return history[0]; // unfiltered
|
||||
|
||||
// Sort current histogram values.
|
||||
typename Sort <T, int> ::Entry entries[Size];
|
||||
for (int n = 0; n < Size; ++n)
|
||||
entries[n].v = history[n];
|
||||
Sort <T, int> ::QuickSort(Size, entries);
|
||||
|
||||
// Compute average of the safe values.
|
||||
T avg = 0;
|
||||
for (int n = (Size / SafeGuard); n < (Size - Size / SafeGuard); ++n)
|
||||
avg += entries[n].v;
|
||||
|
||||
return avg / (Size - (Size / SafeGuard) * 2);
|
||||
}
|
||||
void Reset() { count = 0; }
|
||||
|
||||
SmartMedianAverage() : count(0) {}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __SMARTMEDIANAVG__
|
||||
85
include/platform/filesystem/data_store.h
Normal file
85
include/platform/filesystem/data_store.h
Normal file
@ -0,0 +1,85 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIODATASTORE__
|
||||
#define __NIODATASTORE__
|
||||
|
||||
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "container/nlist.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "thread/mutex.h"
|
||||
#include "unit/nunit.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
/*!
|
||||
@short Data store.
|
||||
*/
|
||||
class DataStore
|
||||
{
|
||||
Threading::Mutex mutex;
|
||||
|
||||
SharedPtr <Base> io;
|
||||
size_t limit;
|
||||
|
||||
uint id_seed;
|
||||
String GetNewId();
|
||||
|
||||
public:
|
||||
|
||||
struct Entry
|
||||
{
|
||||
String id;
|
||||
size_t size;
|
||||
String user;
|
||||
|
||||
Entry() : size(0) {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
AutoList <Entry *> entries;
|
||||
|
||||
Entry *GetEntry(const String &id) const;
|
||||
|
||||
public:
|
||||
|
||||
Base *GetIO() const { return io.c_ptr(); }
|
||||
|
||||
const AutoList <Entry *> &GetEntries() const { return entries; }
|
||||
|
||||
/// Reserve space on the store, an empty id is returned if the store is full.
|
||||
virtual String Reserve(size_t size);
|
||||
/// Free a store alias.
|
||||
virtual bool Free(const String &id);
|
||||
|
||||
/// Store data on a reserved id.
|
||||
bool Store(const String &id, const void *data, size_t size, const char *user_data = 0);
|
||||
|
||||
/// Get entry size.
|
||||
size_t GetEntrySize(const String &id) const;
|
||||
|
||||
/// Get the current store size.
|
||||
size_t GetStoreSize() const;
|
||||
/// Get the store free space size.
|
||||
size_t GetFreeStore() const;
|
||||
|
||||
/// Restore store content from the storage fs.
|
||||
bool Load(const char *path = "store.db");
|
||||
/// Save store content to the storage fs.
|
||||
bool Save(const char *path = "store.db");
|
||||
|
||||
DataStore(Base *storage, size_t storage_limit = Units::MB(32)) : io(storage), limit(storage_limit), id_seed(0) {}
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIODATASTORE__
|
||||
73
include/platform/filesystem/filesystem.h
Normal file
73
include/platform/filesystem/filesystem.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NFILESYSTEM__
|
||||
#define __NFILESYSTEM__
|
||||
|
||||
|
||||
#include "container/nlist.h"
|
||||
#include "filesystem/io_base.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
class Handle;
|
||||
struct Base;
|
||||
|
||||
//
|
||||
struct MountPoint
|
||||
{
|
||||
String mount_point;
|
||||
SharedPtr <Base> io_sys;
|
||||
|
||||
MountPoint(const char *mount, Base *io) : mount_point(mount), io_sys(io) {}
|
||||
};
|
||||
|
||||
/*!
|
||||
@short I/O system.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class Filesystem
|
||||
{
|
||||
AutoList <MountPoint *> mount_list;
|
||||
SharedList <Base *> root_mount;
|
||||
public:
|
||||
|
||||
String MapToAbsolute(const char *) const;
|
||||
String StripRootPath(const char *) const;
|
||||
|
||||
bool Mount(Base *, const char *mount_point = 0);
|
||||
void Unmount(const char *);
|
||||
void Unmount(Base *);
|
||||
void UnmountAll();
|
||||
|
||||
Base *GetIOSystem(const char *mount_point) const;
|
||||
const char *GetMountPoint(const Base *) const;
|
||||
|
||||
Handle *Open(const char *, Mode = ModeRead) const;
|
||||
void Close(Handle *) const;
|
||||
|
||||
bool MkDir(const char *) const;
|
||||
|
||||
bool Exists(const char *) const;
|
||||
bool Delete(const char *) const;
|
||||
|
||||
size_t FileSize(const char *) const;
|
||||
bool FileLoad(const char *, Array <char> &, bool verbose = true) const;
|
||||
bool FileSave(const char *, const Array <char> &) const;
|
||||
bool FileCopy(const char *src, const char *dst) const;
|
||||
bool FileMove(const char *src, const char *dst) const;
|
||||
~Filesystem() { UnmountAll(); }
|
||||
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NFILESYSTEM__
|
||||
173
include/platform/filesystem/ftp_lib.h
Normal file
173
include/platform/filesystem/ftp_lib.h
Normal file
@ -0,0 +1,173 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __FTPLIB__
|
||||
#define __FTPLIB__
|
||||
|
||||
|
||||
#if __PLATFORM_WINDOWS__
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
#include "ntypes.h"
|
||||
|
||||
|
||||
/// FTP connection.
|
||||
struct FtpConnection
|
||||
{
|
||||
enum Direction
|
||||
{
|
||||
Upload = 0,
|
||||
Download
|
||||
};
|
||||
|
||||
int handle;
|
||||
bool ready;
|
||||
|
||||
char *buffer;
|
||||
int buffer_usage;
|
||||
|
||||
Direction direction;
|
||||
|
||||
void FreeBuffer();
|
||||
bool AllocateBuffer();
|
||||
|
||||
FtpConnection();
|
||||
~FtpConnection()
|
||||
{ FreeBuffer(); }
|
||||
};
|
||||
|
||||
/*
|
||||
@short FTP Library.
|
||||
*/
|
||||
class FtpLibrary
|
||||
{
|
||||
public:
|
||||
|
||||
enum ConnectionMode
|
||||
{
|
||||
ConnectionPORT = 0,
|
||||
ConnectionPASV
|
||||
};
|
||||
|
||||
enum TransferMode
|
||||
{
|
||||
TransferASCII = 'A',
|
||||
TransferBinary = 'I'
|
||||
};
|
||||
|
||||
enum AccessType
|
||||
{
|
||||
AccessDir = 0,
|
||||
AccessDirVerbose,
|
||||
AccessFileRead,
|
||||
AccessFileWrite,
|
||||
AccessFileReadAppend,
|
||||
AccessFileWriteAppend
|
||||
};
|
||||
|
||||
enum State
|
||||
{
|
||||
FtpError = 0,
|
||||
FtpOk,
|
||||
FtpSocketTimeout
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
char response[256];
|
||||
|
||||
FtpConnection master_connection;
|
||||
ConnectionMode connection_mode;
|
||||
|
||||
size_t offset;
|
||||
bool correctpasv;
|
||||
|
||||
/// Check server PASV support.
|
||||
bool CheckPASVResponse(unsigned char *v);
|
||||
/// Read and verify a response from the server.
|
||||
bool CheckResponse(char c);
|
||||
|
||||
/// Wait for the socket to receive or flush data.
|
||||
State WaitSocket(FtpConnection *socket);
|
||||
/// Read a line of text.
|
||||
State ReadASCII(char *buf, int max, FtpConnection *socket, int &line_length);
|
||||
/// Write a line of text.
|
||||
State WriteASCII(char *buf, int length, FtpConnection *socket, int &wrote_length);
|
||||
|
||||
/// Send a command and wait for expected response.
|
||||
bool FtpSendCmd(const char *cmd, char expresp);
|
||||
/// Accept connection from server.
|
||||
bool FtpAcceptConnection(FtpConnection *connection);
|
||||
|
||||
/// Create a PORT connection for data transfer.
|
||||
FtpConnection *CreatePORTConnection(TransferMode mode, FtpConnection::Direction direction, char *connection_command);
|
||||
/// Create a PASV connection for data transfer.
|
||||
FtpConnection *CreatePASVConnection(TransferMode mode, FtpConnection::Direction direction, char *connection_command);
|
||||
/// Create a connection for data transfer.
|
||||
FtpConnection *CreateConnection(const char *path, AccessType type, TransferMode mode);
|
||||
/// Close connection.
|
||||
bool CloseConnection(FtpConnection *connection);
|
||||
|
||||
/// Generic data transfer function.
|
||||
State DataTransfer(const char *local_path, const char *remote_path, AccessType type, TransferMode mode);
|
||||
/// Read data from a connection.
|
||||
State ReadBinary(void *buffer, int max, FtpConnection *connection, int &length);
|
||||
/// Write data to a connection.
|
||||
State WriteBinary(void *buffer, int length, FtpConnection *connection);
|
||||
|
||||
public:
|
||||
|
||||
/// Set data connection transfer mode.
|
||||
void SetDataConnectionMode(ConnectionMode mode)
|
||||
{ connection_mode = mode; }
|
||||
|
||||
/// Get last server response received.
|
||||
const char *GetLastResponse() const
|
||||
{ return response; }
|
||||
|
||||
/// Connect to a remote server.
|
||||
bool Connect(const char *host);
|
||||
/// Upload file to server.
|
||||
State Upload(const char *local_path, const char *remote_path, TransferMode mode = TransferBinary, int offset = 0);
|
||||
/// Download file from server.
|
||||
State Download(const char *local_path, const char *remote_path, TransferMode mode = TransferBinary, int offset = 0);
|
||||
/// Quit server, close connection.
|
||||
bool Quit();
|
||||
|
||||
/// Change directory.
|
||||
bool ChangeDirectory(const char *path);
|
||||
/// Up directory.
|
||||
bool UpDirectory();
|
||||
/// Delete remote file.
|
||||
bool DeleteFile(const char *path);
|
||||
/// Get remote file size.
|
||||
int GetFileSize(const char *path, TransferMode mode = TransferBinary);
|
||||
|
||||
/// Download directory listing to a local file.
|
||||
bool Nlst(const char *outputfile, const char *path);
|
||||
|
||||
/// Login remote server.
|
||||
bool Login(const char *user, const char *password);
|
||||
|
||||
|
||||
/*
|
||||
Callback functions.
|
||||
*/
|
||||
virtual bool IdleCallback()
|
||||
{ return true; }
|
||||
virtual void SendCommandCallback(const char * /*command*/)
|
||||
{}
|
||||
virtual bool DataReadCallback(const FtpConnection * /*connection*/)
|
||||
{ return true; }
|
||||
virtual bool DataWriteCallback(const FtpConnection * /*connection*/)
|
||||
{ return true; }
|
||||
|
||||
FtpLibrary();
|
||||
virtual ~FtpLibrary();
|
||||
};
|
||||
|
||||
|
||||
#endif // __FTPLIB__
|
||||
66
include/platform/filesystem/io_alias.h
Normal file
66
include/platform/filesystem/io_alias.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOALIAS__
|
||||
#define __NIOALIAS__
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nstring/nstring.h"
|
||||
#include "container/nmap.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
class Handle;
|
||||
|
||||
/*!
|
||||
@short Alias proxy I/O.
|
||||
A simple proxy I/O to provide filename aliasing to another I/O system.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class Alias : public Base
|
||||
{
|
||||
SharedPtr <Base> iofs;
|
||||
|
||||
public:
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
Map <String, String> alias_map;
|
||||
|
||||
String ResolveAlias(const char *path) const
|
||||
{
|
||||
Pair <String, String> *alias = alias_map.Get(path);
|
||||
return alias ? alias->value : path;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
virtual Handle *Open(const char *path, Mode mode = IORead)
|
||||
{ return iofs->Open(ResolveAlias(path), mode); }
|
||||
virtual void Close(Handle *h)
|
||||
{ iofs->Close(h); }
|
||||
|
||||
virtual bool Delete(const char *path)
|
||||
{ return iofs->Delete(ResolveAlias(path)); }
|
||||
|
||||
virtual size_t Tell(Handle *h)
|
||||
{ return iofs->Tell(h); }
|
||||
virtual size_t Seek(Handle *h, ptrdiff_t offset, SeekRef seek_ref = SeekCurrent)
|
||||
{ return iofs->Seek(h, offset, seek_ref); }
|
||||
|
||||
virtual size_t Read(Handle *h, void *p, size_t size)
|
||||
{ return iofs->Read(h, p, size); }
|
||||
virtual size_t Write(Handle *h, const void *p, size_t size)
|
||||
{ return iofs->Write(h, p, size); }
|
||||
|
||||
Alias(Base *io) : iofs(io) {}
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOALIAS__
|
||||
80
include/platform/filesystem/io_base.h
Normal file
80
include/platform/filesystem/io_base.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOBASE__
|
||||
#define __NIOBASE__
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include "filesystem/io_mode.h"
|
||||
#include "memory/nshared_ptr.h"
|
||||
#include "container/narray.h"
|
||||
#include "alloc/ialloc.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
class String;
|
||||
|
||||
namespace IO {
|
||||
class Handle;
|
||||
|
||||
/*!
|
||||
@short I/O base.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
struct Base : public SharedObject
|
||||
{
|
||||
NPLACEMENT_NEW(Filesystem)
|
||||
|
||||
enum SeekRef
|
||||
{
|
||||
SeekStart = 0,
|
||||
SeekCurrent,
|
||||
SeekEnd
|
||||
};
|
||||
|
||||
enum Caps
|
||||
{
|
||||
IsCaseSensitive = (1 << 0),
|
||||
CanRead = (1 << 1),
|
||||
CanWrite = (1 << 2),
|
||||
CanSeek = (1 << 3),
|
||||
CanDelete = (1 << 4),
|
||||
CanMkDir = (1 << 5)
|
||||
};
|
||||
|
||||
bool FileLoad(const char *uri, Array <char> &buffer);
|
||||
bool FileSave(const char *uri, const Array <char> &buffer);
|
||||
|
||||
String FileHash(const char *uri);
|
||||
|
||||
virtual bool Exists(const char *);
|
||||
virtual String Hash(const char *);
|
||||
|
||||
virtual String MapToAbsolute(const char *uri) const;
|
||||
virtual String MapToRelative(const char *path) const;
|
||||
|
||||
virtual uint GetCaps() const = 0;
|
||||
|
||||
virtual Handle *Open(const char *, Mode = ModeRead) = 0;
|
||||
virtual void Close(Handle *) = 0;
|
||||
|
||||
virtual bool Delete(const char *) = 0;
|
||||
|
||||
virtual size_t Tell(Handle *) = 0;
|
||||
virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent) = 0;
|
||||
|
||||
virtual size_t Read(Handle *, void *, size_t) = 0;
|
||||
virtual size_t Write(Handle *, const void *, size_t) = 0;
|
||||
|
||||
virtual bool MkDir(const char *) = 0;
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOBASE__
|
||||
87
include/platform/filesystem/io_buffer.h
Normal file
87
include/platform/filesystem/io_buffer.h
Normal file
@ -0,0 +1,87 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOBUFFER__
|
||||
#define __NIOBUFFER__
|
||||
|
||||
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
#include "container/narray.h"
|
||||
#include "unit/nunit.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
//
|
||||
struct IOBuffer
|
||||
{
|
||||
Array <char> buffer;
|
||||
|
||||
size_t start_pos;
|
||||
size_t usage;
|
||||
|
||||
IOBuffer() : start_pos(0), usage(0) {}
|
||||
};
|
||||
|
||||
//
|
||||
class BufferHandle : public Handle
|
||||
{
|
||||
friend class Buffer;
|
||||
|
||||
AutoPtr <Handle> handle;
|
||||
size_t size; // file size on wrapped fs
|
||||
size_t pos; // position in source handle
|
||||
|
||||
IOBuffer read_buffer;
|
||||
|
||||
public:
|
||||
|
||||
virtual size_t GetSize() { return size; }
|
||||
|
||||
BufferHandle(Base *io, Handle *h) : Handle(io), handle(h), size(0), pos(0) {}
|
||||
};
|
||||
|
||||
/*!
|
||||
@short Buffered I/O filesystem wrapper.
|
||||
Implements a transparent read/write buffer on top of another filesystem.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class Buffer : public Base
|
||||
{
|
||||
SharedPtr <Base> io;
|
||||
|
||||
size_t read_buffer_size,
|
||||
write_buffer_size;
|
||||
|
||||
public:
|
||||
|
||||
virtual uint GetCaps() const;
|
||||
|
||||
virtual Handle *Open(const char *, Mode = ModeRead);
|
||||
virtual void Close(Handle *);
|
||||
|
||||
virtual String Hash(const char *);
|
||||
virtual bool Delete(const char *);
|
||||
|
||||
virtual size_t Tell(Handle *);
|
||||
virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent);
|
||||
|
||||
virtual size_t Read(Handle *, void *, size_t);
|
||||
virtual size_t Write(Handle *, const void *, size_t);
|
||||
|
||||
virtual bool MkDir(const char *);
|
||||
|
||||
Buffer(Base *base, size_t read_buffer_size = Units::KB(4), size_t write_buffer_size = Units::KB(4));
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOBUFFER__
|
||||
109
include/platform/filesystem/io_cache.h
Normal file
109
include/platform/filesystem/io_cache.h
Normal file
@ -0,0 +1,109 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOCACHE__
|
||||
#define __NIOCACHE__
|
||||
|
||||
|
||||
#include "filesystem/data_store.h"
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
#include "container/nlist.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "time/ntime.h"
|
||||
#include "unit/nunit.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
//
|
||||
class CacheHandle : public Handle
|
||||
{
|
||||
friend class Cache;
|
||||
|
||||
protected:
|
||||
|
||||
String path;
|
||||
AutoPtr <Handle> handle;
|
||||
|
||||
public:
|
||||
|
||||
CacheHandle(Base *io, const char *p, Handle *h) : Handle(io), path(p), handle(h) {}
|
||||
~CacheHandle();
|
||||
};
|
||||
|
||||
/*!
|
||||
@short Cached I/O filesystem wrapper.
|
||||
Implements a transparent file cache on top of another filesystem.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class Cache : public Base
|
||||
{
|
||||
SharedPtr <Base> io;
|
||||
DataStore store;
|
||||
|
||||
public:
|
||||
|
||||
struct Entry
|
||||
{
|
||||
String path, id;
|
||||
String hash;
|
||||
|
||||
uint refc;
|
||||
size_t size;
|
||||
|
||||
Time last_use;
|
||||
|
||||
Entry() : refc(0), size(0) {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Threading::Mutex mutex;
|
||||
|
||||
size_t cache_size;
|
||||
AutoList <Entry *> entries;
|
||||
|
||||
int ComputeEntryRecyclingScore(const Entry *) const;
|
||||
String ReserveOnStore(size_t size);
|
||||
|
||||
Entry *GetCacheEntry(const char *path) const;
|
||||
Entry *CreateCacheEntry(const char *path);
|
||||
bool UpdateCacheEntry(Entry *entry, Array <char> *preloaded_data = 0);
|
||||
bool DeleteCacheEntry(Entry *entry);
|
||||
|
||||
public:
|
||||
|
||||
virtual uint GetCaps() const;
|
||||
|
||||
virtual Handle *Open(const char *, Mode = ModeRead);
|
||||
virtual void Close(Handle *);
|
||||
|
||||
virtual bool Delete(const char *);
|
||||
|
||||
virtual size_t Tell(Handle *);
|
||||
virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent);
|
||||
|
||||
virtual size_t Read(Handle *, void *, size_t);
|
||||
virtual size_t Write(Handle *, const void *, size_t);
|
||||
|
||||
virtual bool MkDir(const char *);
|
||||
|
||||
/// Test if a given path is in cache.
|
||||
bool IsInCache(const char *path) const { return asbool(GetCacheEntry(path)); }
|
||||
|
||||
/// Reload cache state from its store.
|
||||
bool SynchronizeWithStore(const char *store_path = "store.db");
|
||||
|
||||
Cache(Base *base, Base *store, size_t cache_size = Units::MB(32));
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOCACHE__
|
||||
70
include/platform/filesystem/io_cfile.h
Normal file
70
include/platform/filesystem/io_cfile.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOCFILE__
|
||||
#define __NIOCFILE__
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "nstring/nstring.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
//
|
||||
class CFileHandle : public Handle
|
||||
{
|
||||
friend class CFile;
|
||||
|
||||
FILE *file;
|
||||
|
||||
CFileHandle(Base *);
|
||||
|
||||
public:
|
||||
|
||||
~CFileHandle();
|
||||
};
|
||||
|
||||
/*!
|
||||
@short C-File I/O.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class CFile : public Base
|
||||
{
|
||||
String root;
|
||||
|
||||
public:
|
||||
|
||||
void SetRootPath(const char *);
|
||||
|
||||
virtual String MapToAbsolute(const char *) const;
|
||||
virtual String MapToRelative(const char *) const;
|
||||
|
||||
virtual uint GetCaps() const;
|
||||
|
||||
virtual Handle *Open(const char *, Mode = ModeRead);
|
||||
virtual void Close(Handle *);
|
||||
|
||||
virtual bool Delete(const char *);
|
||||
|
||||
virtual size_t Tell(Handle *);
|
||||
virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent);
|
||||
|
||||
virtual size_t Read(Handle *, void *, size_t);
|
||||
virtual size_t Write(Handle *, const void *, size_t);
|
||||
|
||||
virtual bool MkDir(const char *);
|
||||
|
||||
CFile(const char *root_path = 0);
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOCFILE__
|
||||
73
include/platform/filesystem/io_crypto.h
Normal file
73
include/platform/filesystem/io_crypto.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOCRYPTO__
|
||||
#define __NIOCRYPTO__
|
||||
|
||||
|
||||
#include "filesystem/io_memory.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
//
|
||||
class CryptoHandle : public Handle
|
||||
{
|
||||
friend class Crypto;
|
||||
|
||||
AutoPtr <Handle> cached_h;
|
||||
|
||||
String path;
|
||||
Mode io_mode;
|
||||
|
||||
CryptoHandle(Base *, Handle *, const char *, Mode);
|
||||
|
||||
public:
|
||||
|
||||
~CryptoHandle();
|
||||
};
|
||||
|
||||
/*!
|
||||
@short I/O Crypto proxy.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class Crypto : public Base
|
||||
{
|
||||
String key;
|
||||
|
||||
SharedPtr <Base> wrapped_io;
|
||||
SharedPtr <Memory> cache_io;
|
||||
|
||||
void Encrypt(Array <char> &);
|
||||
void Decrypt(Array <char> &);
|
||||
|
||||
public:
|
||||
|
||||
virtual uint GetCaps() const;
|
||||
|
||||
virtual Handle *Open(const char *, Mode = ModeRead);
|
||||
virtual void Close(Handle *);
|
||||
|
||||
virtual bool Delete(const char *);
|
||||
|
||||
virtual size_t Tell(Handle *);
|
||||
virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent);
|
||||
|
||||
virtual size_t Read(Handle *, void *, size_t);
|
||||
virtual size_t Write(Handle *, const void *, size_t);
|
||||
|
||||
virtual bool MkDir(const char *);
|
||||
|
||||
Crypto(Base *, const char *key);
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOCRYPTO__
|
||||
77
include/platform/filesystem/io_dispatcher.h
Normal file
77
include/platform/filesystem/io_dispatcher.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIODISPATCH__
|
||||
#define __NIODISPATCH__
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
#include "container/nlist.h"
|
||||
#include "nstring/nstring.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
//
|
||||
class DispatcherHandle : public Handle
|
||||
{
|
||||
friend class Dispatcher;
|
||||
|
||||
AutoPtr <Handle> handle;
|
||||
|
||||
DispatcherHandle(Base *, Handle *);
|
||||
|
||||
public:
|
||||
|
||||
~DispatcherHandle();
|
||||
};
|
||||
|
||||
/*!
|
||||
@short Dispatcher I/O.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class Dispatcher : public Base
|
||||
{
|
||||
struct DispatchFS
|
||||
{
|
||||
String prefix;
|
||||
SharedPtr <Base> fs;
|
||||
};
|
||||
|
||||
SharedList <Base *> roots;
|
||||
AutoList <DispatchFS *> mounts;
|
||||
|
||||
Base *Dispatch(String &, Mode);
|
||||
|
||||
public:
|
||||
|
||||
bool AddDispatch(Base *, const char *prefix = 0);
|
||||
|
||||
virtual uint GetCaps() const;
|
||||
|
||||
virtual Handle *Open(const char *, Mode = ModeRead);
|
||||
virtual void Close(Handle *);
|
||||
|
||||
virtual String Hash(const char *);
|
||||
virtual bool Delete(const char *);
|
||||
|
||||
virtual size_t Tell(Handle *);
|
||||
virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent);
|
||||
|
||||
virtual size_t Read(Handle *, void *, size_t);
|
||||
virtual size_t Write(Handle *, const void *, size_t);
|
||||
|
||||
virtual bool MkDir(const char *);
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIODISPATCH__
|
||||
71
include/platform/filesystem/io_handle.h
Normal file
71
include/platform/filesystem/io_handle.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOHANDLE__
|
||||
#define __NIOHANDLE__
|
||||
|
||||
|
||||
#include "filesystem/io_base.h"
|
||||
#include "memory/nweak_ptr.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
//
|
||||
class Handle
|
||||
{
|
||||
WeakPtr <Base> io_sys;
|
||||
|
||||
public:
|
||||
|
||||
NPLACEMENT_NEW(Filesystem)
|
||||
|
||||
virtual size_t GetSize();
|
||||
|
||||
virtual size_t Rewind();
|
||||
virtual bool IsEOF();
|
||||
|
||||
virtual size_t Tell();
|
||||
virtual size_t Seek(ptrdiff_t, Base::SeekRef = Base::SeekCurrent);
|
||||
|
||||
virtual size_t Read(void *, size_t);
|
||||
virtual size_t Write(const void *, size_t);
|
||||
|
||||
template <class T> Handle &operator << (const T &v)
|
||||
{
|
||||
io_sys->Write(this, &v, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
template <class T> Handle &operator >> (T &v)
|
||||
{
|
||||
io_sys->Read(this, &v, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
Handle &operator << (const char *);
|
||||
Handle &operator << (char *);
|
||||
|
||||
template <class T> bool Write(const T &v)
|
||||
{ return asbool(io_sys->Write(this, &v, sizeof(T))); }
|
||||
template <class T> T Read()
|
||||
{
|
||||
T v;
|
||||
io_sys->Read(this, &v, sizeof(T));
|
||||
return v;
|
||||
}
|
||||
|
||||
Base *GetIOSystem() const
|
||||
{ return io_sys.c_ptr(); }
|
||||
|
||||
Handle(Base *);
|
||||
virtual ~Handle();
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOHANDLE__
|
||||
50
include/platform/filesystem/io_handle_endian.h
Normal file
50
include/platform/filesystem/io_handle_endian.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOHANDLE_ENDIAN__
|
||||
#define __NIOHANDLE_ENDIAN__
|
||||
|
||||
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "memory/endian.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
/// IO Handle endian wrapper.
|
||||
class HandleEndian
|
||||
{
|
||||
AutoPtr <Handle> h;
|
||||
Endian::Config config;
|
||||
|
||||
public:
|
||||
|
||||
bool IsNull() const { return h.IsNull(); }
|
||||
bool IsValid() const { return h.IsValid(); }
|
||||
|
||||
Handle &GetIOHandle() const { return *h; }
|
||||
|
||||
template <class T> const HandleEndian &operator << (const T &v)
|
||||
{
|
||||
*h << Endian::ToHost(v, config);
|
||||
return *this;
|
||||
}
|
||||
template <class T> const HandleEndian &operator >> (T &v)
|
||||
{
|
||||
*h >> v;
|
||||
Endian::ToHost(&v, sizeof(T), config);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HandleEndian(Handle *in_h, Endian::Config in_config = Endian::Little) : h(in_h), config(in_config) {}
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOHANDLE_ENDIAN__
|
||||
42
include/platform/filesystem/io_handle_segment.h
Normal file
42
include/platform/filesystem/io_handle_segment.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOHANDLESEGMENT__
|
||||
#define __NIOHANDLESEGMENT__
|
||||
|
||||
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
//
|
||||
class HandleSegment : public Handle
|
||||
{
|
||||
Handle *handle;
|
||||
size_t offset, size;
|
||||
size_t cursor;
|
||||
|
||||
public:
|
||||
|
||||
virtual size_t GetSize();
|
||||
|
||||
virtual size_t Tell();
|
||||
virtual size_t Seek(ptrdiff_t, Base::SeekRef = Base::SeekCurrent);
|
||||
|
||||
virtual size_t Read(void *, size_t);
|
||||
virtual size_t Write(const void *, size_t);
|
||||
|
||||
HandleSegment(Handle *h, size_t o, size_t s) : Handle(0), handle(h), offset(o), size(s), cursor(0) {}
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOHANDLESEGMENT__
|
||||
86
include/platform/filesystem/io_memory.h
Normal file
86
include/platform/filesystem/io_memory.h
Normal file
@ -0,0 +1,86 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOMEMORY__
|
||||
#define __NIOMEMORY__
|
||||
|
||||
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "container/nlist.h"
|
||||
#include "nstring/nstring.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
//
|
||||
class MemoryFile
|
||||
{
|
||||
friend class Memory;
|
||||
|
||||
String uri;
|
||||
Array <char> data;
|
||||
size_t size; //< Might be != data.GetSize()
|
||||
|
||||
MemoryFile(const char *_uri = 0) : uri(_uri), size(0) {}
|
||||
|
||||
public:
|
||||
|
||||
const String &GetUri() const { return uri; }
|
||||
const Array <char> &GetData() const { return data; }
|
||||
size_t GetSize() const { return size; }
|
||||
};
|
||||
|
||||
//
|
||||
class MemoryHandle : public Handle
|
||||
{
|
||||
friend class Memory;
|
||||
|
||||
MemoryFile *file;
|
||||
size_t cursor;
|
||||
Mode mode;
|
||||
|
||||
MemoryHandle(Base *, MemoryFile *, Mode = ModeRead);
|
||||
|
||||
public:
|
||||
|
||||
~MemoryHandle();
|
||||
};
|
||||
|
||||
/*!
|
||||
@short Memory I/O.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class Memory : public Base
|
||||
{
|
||||
AutoList <MemoryFile *> fat;
|
||||
|
||||
public:
|
||||
|
||||
/// Return the system file allocation table.
|
||||
const List <MemoryFile *> &GetFat() const { return fat; }
|
||||
|
||||
virtual uint GetCaps() const;
|
||||
|
||||
virtual Handle *Open(const char *, Mode = ModeRead);
|
||||
virtual void Close(Handle *);
|
||||
|
||||
virtual bool Delete(const char *);
|
||||
|
||||
virtual size_t Tell(Handle *);
|
||||
virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent);
|
||||
|
||||
virtual size_t Read(Handle *, void *, size_t);
|
||||
virtual size_t Write(Handle *, const void *, size_t);
|
||||
|
||||
virtual bool MkDir(const char *) { return false; }
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOMEMORY__
|
||||
25
include/platform/filesystem/io_mode.h
Normal file
25
include/platform/filesystem/io_mode.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NIOMODE__
|
||||
#define __NIOMODE__
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace IO {
|
||||
|
||||
enum Mode
|
||||
{
|
||||
ModeNone = 0,
|
||||
ModeRead,
|
||||
ModeWrite
|
||||
};
|
||||
|
||||
} // IO
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NIOMODE__
|
||||
114
include/platform/hash/md5.h
Normal file
114
include/platform/hash/md5.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
|
||||
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
|
||||
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
|
||||
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.h is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Removed support for non-ANSI compilers; removed
|
||||
references to Ghostscript; clarified derivation from RFC 1321;
|
||||
now handles byte order either statically or dynamically.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
|
||||
added conditionalization for C++ compilation from Martin
|
||||
Purschke <purschke@bnl.gov>.
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef __NMD5__
|
||||
#define __NMD5__
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace MD5 {
|
||||
|
||||
/*
|
||||
This package supports both compile-time and run-time determination of CPU
|
||||
byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
|
||||
compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
|
||||
defined as non-zero, the code will be compiled to run only on big-endian
|
||||
CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
|
||||
run on either big- or little-endian CPUs, but will run slightly less
|
||||
efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
|
||||
*/
|
||||
|
||||
typedef unsigned char md5_byte_t; // 8-bit byte
|
||||
typedef unsigned int md5_word_t; // 32-bit word
|
||||
|
||||
/*
|
||||
@short MD5 digest.
|
||||
*/
|
||||
class Digest
|
||||
{
|
||||
md5_word_t count[2], ///< Message length in bits, lsw first.
|
||||
abcd[4]; ///< Digest buffer.
|
||||
md5_byte_t buf[64]; ///< Accumulate block.
|
||||
|
||||
/// Process.
|
||||
void Process(const md5_byte_t *data /*[64]*/);
|
||||
|
||||
public:
|
||||
|
||||
void Reset();
|
||||
|
||||
/// Append data to the message.
|
||||
void Append(const md5_byte_t *data, int nbytes);
|
||||
/// Finish the message and return the digest.
|
||||
void Finish(md5_byte_t digest[16]);
|
||||
|
||||
Digest() { Reset(); }
|
||||
};
|
||||
|
||||
/*!
|
||||
@short Convert a digest to string.
|
||||
@note The string is not NULL terminated by this function.
|
||||
*/
|
||||
void DigestToString(const md5_byte_t digest[16], char *s);
|
||||
|
||||
} // MD5
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NMD5__
|
||||
27
include/platform/hash/nsha1.h
Normal file
27
include/platform/hash/nsha1.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NSHA1__
|
||||
#define __NSHA1__
|
||||
|
||||
|
||||
namespace GS {
|
||||
class String;
|
||||
template <class T> class Array;
|
||||
|
||||
namespace SHA1 {
|
||||
|
||||
void ComputeHash(const String &source, Array <unsigned char> &hash);
|
||||
String ComputeHexa(const String &source);
|
||||
|
||||
void ComputeHash(const Array <char> &data, Array <unsigned char> &hash);
|
||||
String ComputeHexa(const Array <char> &data);
|
||||
|
||||
} // SHA1
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NSHA1__
|
||||
49
include/platform/hash/sha1.h
Normal file
49
include/platform/hash/sha1.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright (c) 2011, Micael Hildenborg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Micael Hildenborg nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SHA1_DEFINED
|
||||
#define SHA1_DEFINED
|
||||
|
||||
namespace sha1
|
||||
{
|
||||
|
||||
/**
|
||||
@param src points to any kind of data to be hashed.
|
||||
@param bytelength the number of bytes to hash from the src pointer.
|
||||
@param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in.
|
||||
*/
|
||||
void calc(const void* src, const int bytelength, unsigned char* hash);
|
||||
|
||||
/**
|
||||
@param hash is 20 bytes of sha1 hash. This is the same data that is the result from the calc function.
|
||||
@param hexstring should point to a buffer of at least 41 bytes of size for storing the hexadecimal representation of the hash. A zero will be written at position 40, so the buffer will be a valid zero ended string.
|
||||
*/
|
||||
void toHexString(const unsigned char* hash, char* hexstring);
|
||||
|
||||
} // namespace sha1
|
||||
|
||||
#endif // SHA1_DEFINED
|
||||
47
include/platform/http/http_interface.h
Normal file
47
include/platform/http/http_interface.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __HTTPINTERFACE__
|
||||
#define __HTTPINTERFACE__
|
||||
|
||||
|
||||
#include "container/narray.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace HTTP {
|
||||
|
||||
/*!
|
||||
@short HTTP interface.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
struct IHTTP
|
||||
{
|
||||
/// Process a request return value.
|
||||
virtual void OnRequestComplete(int ticket_id, const Array <char> &data) = 0;
|
||||
/// Process a request error.
|
||||
virtual void OnRequestError(int ticket_id) = 0;
|
||||
|
||||
/*!
|
||||
@short Post an asynchronous HTTP request.
|
||||
|
||||
This function posts an asynchronous HTTP request and returns a ticket
|
||||
id to the caller. When task result is available the OnRequestComplete
|
||||
or OnRequestError handler functions will be called.
|
||||
*/
|
||||
virtual int Post(const char *url, const char *post) = 0;
|
||||
|
||||
/// Process pending event dispatch in the caller thread.
|
||||
virtual void Update() = 0;
|
||||
|
||||
virtual ~IHTTP() {}
|
||||
};
|
||||
|
||||
} // HTTP
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __HTTPINTERFACE__
|
||||
136
include/platform/input/input_device.h
Normal file
136
include/platform/input/input_device.h
Normal file
@ -0,0 +1,136 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __INPUT_DEVICE__
|
||||
#define __INPUT_DEVICE__
|
||||
|
||||
|
||||
#include "ntypes.h"
|
||||
#include "memory/nshared_ptr.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Input {
|
||||
|
||||
/*
|
||||
@short Input device.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class Device : public SharedObject
|
||||
{
|
||||
public:
|
||||
|
||||
enum Type
|
||||
{
|
||||
Type_Any = 0, Type_Keyboard, Type_Mouse, Type_Pad, Type_Touch
|
||||
};
|
||||
|
||||
// Binary value.
|
||||
enum KeyCode
|
||||
{
|
||||
Key_None = 0,
|
||||
|
||||
// Keyboard.
|
||||
Key_LShift, Key_RShift, Key_LCtrl, Key_RCtrl, Key_LAlt, Key_RAlt, Key_LWin, Key_RWin,
|
||||
Key_Tab, Key_CapsLock, Key_Space, Key_Backspace, Key_Insert, Key_Suppr, Key_Home, Key_End, Key_PageUp, Key_PageDown,
|
||||
Key_Up, Key_Down, Key_Left, Key_Right,
|
||||
Key_Escape,
|
||||
Key_F1, Key_F2, Key_F3, Key_F4, Key_F5, Key_F6, Key_F7, Key_F8, Key_F9, Key_F10, Key_F11, Key_F12,
|
||||
Key_PrintScreen, Key_ScrollLock, Key_Pause, Key_NumLock, Key_Return,
|
||||
Key_Numpad0, Key_Numpad1, Key_Numpad2, Key_Numpad3, Key_Numpad4, Key_Numpad5, Key_Numpad6, Key_Numpad7, Key_Numpad8, Key_Numpad9,
|
||||
Key_Add, Key_Sub, Key_Mul, Key_Div, Key_Enter,
|
||||
Key_A, Key_B, Key_C, Key_D, Key_E, Key_F, Key_G, Key_H, Key_I, Key_J, Key_K, Key_L, Key_M, Key_N, Key_O, Key_P, Key_Q, Key_R, Key_S, Key_T, Key_U, Key_V, Key_W, Key_X, Key_Y, Key_Z,
|
||||
|
||||
// Mouse/pad.
|
||||
Key_Button0, Key_Button1, Key_Button2, Key_Button3, Key_Button4, Key_Button5, Key_Button6, Key_Button7, Key_Button8, Key_Button9,
|
||||
Key_Button10, Key_Button11, Key_Button12, Key_Button13, Key_Button14, Key_Button15, Key_Button16, Key_Button17, Key_Button18, Key_Button19,
|
||||
Key_Button20, Key_Button21, Key_Button22, Key_Button23, Key_Button24, Key_Button25, Key_Button26, Key_Button27, Key_Button28, Key_Button29,
|
||||
Key_Button30, Key_Button31, Key_Button32, Key_Button33, Key_Button34, Key_Button35, Key_Button36, Key_Button37, Key_Button38, Key_Button39,
|
||||
Key_Button40, Key_Button41, Key_Button42, Key_Button43, Key_Button44, Key_Button45, Key_Button46, Key_Button47, Key_Button48, Key_Button49,
|
||||
Key_Button50, Key_Button51, Key_Button52, Key_Button53, Key_Button54, Key_Button55, Key_Button56, Key_Button57, Key_Button58, Key_Button59,
|
||||
Key_Button60, Key_Button61, Key_Button62, Key_Button63, Key_Button64, Key_Button65, Key_Button66, Key_Button67, Key_Button68, Key_Button69,
|
||||
Key_Button70, Key_Button71, Key_Button72, Key_Button73, Key_Button74, Key_Button75, Key_Button76, Key_Button77, Key_Button78, Key_Button79,
|
||||
Key_Button80, Key_Button81, Key_Button82, Key_Button83, Key_Button84, Key_Button85, Key_Button86, Key_Button87, Key_Button88, Key_Button89,
|
||||
Key_Button90, Key_Button91, Key_Button92, Key_Button93, Key_Button94, Key_Button95, Key_Button96, Key_Button97, Key_Button98, Key_Button99,
|
||||
Key_Button100, Key_Button101, Key_Button102, Key_Button103, Key_Button104, Key_Button105, Key_Button106, Key_Button107, Key_Button108, Key_Button109,
|
||||
Key_Button110, Key_Button111, Key_Button112, Key_Button113, Key_Button114, Key_Button115, Key_Button116, Key_Button117, Key_Button118, Key_Button119,
|
||||
Key_Button120, Key_Button121, Key_Button122, Key_Button123, Key_Button124, Key_Button125, Key_Button126, Key_Button127,
|
||||
Key_Back, Key_Start, Key_Select, Key_L1, Key_L2, Key_L3, Key_R1, Key_R2, Key_R3,
|
||||
Key_Cross_Up, Key_Cross_Down, Key_Cross_Left, Key_Cross_Right,
|
||||
|
||||
Key_Last
|
||||
};
|
||||
|
||||
// Ranged-value.
|
||||
enum InputCode
|
||||
{
|
||||
Input_None = 0,
|
||||
Input_AxisX, Input_AxisY, Input_AxisZ, Input_AxisS, Input_AxisT, Input_AxisR,
|
||||
Input_RotX, Input_RotY, Input_RotZ, Input_RotS, Input_RotT, Input_RotR,
|
||||
Input_Button0, Input_Button1, Input_Button2, Input_Button3, Input_Button4, Input_Button5, Input_Button6, Input_Button7, Input_Button8, Input_Button9, Input_Button10, Input_Button11, Input_Button12, Input_Button13, Input_Button14, Input_Button15
|
||||
};
|
||||
|
||||
// Input semantics.
|
||||
enum InputSemantic
|
||||
{
|
||||
// Mouse semantics.
|
||||
Semantic_LeftMouseButton, Semantic_RightMouseButton, Semantic_MiddleMouseButton,
|
||||
Semantic_MouseAxisX, Semantic_MouseAxisY, Semantic_MouseWheel,
|
||||
|
||||
// Touch semantic.
|
||||
Semantic_TouchPressure, Semantic_TouchAxisX, Semantic_TouchAxisY,
|
||||
|
||||
// Pad semantics.
|
||||
Semantic_StartButton, Semantic_SelectButton
|
||||
};
|
||||
|
||||
enum Effect
|
||||
{
|
||||
Vibrate, VibrateLeft, VibrateRight,
|
||||
ConstantForce
|
||||
};
|
||||
|
||||
/// Get device type.
|
||||
virtual Type GetType() const = 0;
|
||||
/// Get device name.
|
||||
virtual const char *GetName() const = 0;
|
||||
|
||||
/// Pool state and refresh values.
|
||||
virtual void Update() = 0;
|
||||
/// Is device valid.
|
||||
virtual bool IsValid() const { return true; }
|
||||
|
||||
/// Get input from semantic.
|
||||
virtual InputCode GetInputFromSemantic(InputSemantic) { return Input_None; }
|
||||
|
||||
/// Test a key state.
|
||||
virtual bool IsDown(KeyCode) const { return false; }
|
||||
/// Test a key state during the previous update.
|
||||
virtual bool WasDown(KeyCode) const { return false; }
|
||||
|
||||
/// Get input range.
|
||||
virtual bool GetInputRange(InputCode, float &min, float &max) const { return false; }
|
||||
|
||||
/// Get input value.
|
||||
virtual float GetValue(InputCode) const { return 0; }
|
||||
/// Get input value during last update.
|
||||
virtual float GetLastValue(InputCode) const { return 0; }
|
||||
|
||||
/// Set input value, return true if the device supports setting this value.
|
||||
virtual bool SetValue(InputCode, float) { return false; }
|
||||
|
||||
/// Set device effect.
|
||||
virtual void SetEffect(Effect effect, float v) {}
|
||||
|
||||
bool WasPressed(KeyCode key) const
|
||||
{ return !WasDown(key) && IsDown(key); }
|
||||
};
|
||||
|
||||
} // Input
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __INPUT_DEVICE__
|
||||
45
include/platform/input/input_keyboard.h
Normal file
45
include/platform/input/input_keyboard.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __KEYBOARD_INPUT__
|
||||
#define __KEYBOARD_INPUT__
|
||||
|
||||
|
||||
#include "input/input_device.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Input {
|
||||
|
||||
/*
|
||||
@short Keyboard input device.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class Keyboard : public Device
|
||||
{
|
||||
protected:
|
||||
|
||||
bool is_down[Key_Last],
|
||||
was_down[Key_Last];
|
||||
|
||||
public:
|
||||
|
||||
virtual Type GetType() const { return Type_Keyboard; }
|
||||
virtual const char *GetName() const { return "Keyboard"; }
|
||||
|
||||
virtual void Update() = 0;
|
||||
|
||||
virtual bool IsDown(KeyCode k) const { return is_down[k]; }
|
||||
virtual bool WasDown(KeyCode k) const { return was_down[k]; }
|
||||
|
||||
Keyboard();
|
||||
};
|
||||
|
||||
} // Input
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __KEYBOARD_INPUT__
|
||||
56
include/platform/input/input_mouse.h
Normal file
56
include/platform/input/input_mouse.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __INPUT_MOUSE__
|
||||
#define __INPUT_MOUSE__
|
||||
|
||||
|
||||
#include "input/input_device.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Input {
|
||||
|
||||
/*
|
||||
@short Mouse input device.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class Mouse : public Device
|
||||
{
|
||||
protected:
|
||||
|
||||
struct State
|
||||
{
|
||||
float x, y, wheel, hwheel;
|
||||
bool left_button, right_button, middle_button;
|
||||
};
|
||||
|
||||
State state,
|
||||
last_state;
|
||||
|
||||
public:
|
||||
|
||||
virtual Type GetType() const { return Type_Mouse; }
|
||||
virtual const char *GetName() const { return "mouse"; }
|
||||
|
||||
virtual void Update() = 0;
|
||||
|
||||
virtual bool IsDown(KeyCode) const;
|
||||
virtual bool WasDown(KeyCode) const;
|
||||
|
||||
virtual bool GetInputRange(InputCode, float &min, float &max) const;
|
||||
|
||||
virtual float GetValue(InputCode) const;
|
||||
virtual float GetLastValue(InputCode) const;
|
||||
|
||||
Mouse();
|
||||
};
|
||||
|
||||
} // Input
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __INPUT_MOUSE__
|
||||
45
include/platform/input/input_null.h
Normal file
45
include/platform/input/input_null.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __INPUT_NULL_DEVICE__
|
||||
#define __INPUT_NULL_DEVICE__
|
||||
|
||||
|
||||
#include "input/input_device.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Input {
|
||||
|
||||
/*
|
||||
@short Null input device.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class NullDevice : public Device
|
||||
{
|
||||
public:
|
||||
|
||||
virtual Type GetType() const
|
||||
{ return Type_Any; }
|
||||
virtual const char *GetName() const
|
||||
{ return "Null"; }
|
||||
|
||||
virtual void Update() {}
|
||||
|
||||
virtual bool IsDown(KeyCode) const { return false; }
|
||||
virtual bool WasDown(KeyCode) const { return false; }
|
||||
|
||||
virtual bool GetInputRange(InputCode, float &min, float &max) const { return false; }
|
||||
|
||||
virtual float GetValue(InputCode) const { return 0; }
|
||||
virtual float GetLastValue(InputCode) const { return 0; }
|
||||
};
|
||||
|
||||
} // Input
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __INPUT_NULL_DEVICE__
|
||||
51
include/platform/input/input_system.h
Normal file
51
include/platform/input/input_system.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __INPUT_SYSTEM__
|
||||
#define __INPUT_SYSTEM__
|
||||
|
||||
|
||||
#include "input/input_device.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "container/nlist.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Input {
|
||||
|
||||
/*
|
||||
@short Input system.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
struct System
|
||||
{
|
||||
/// Return true if the input system is active.
|
||||
virtual bool IsActive() { return true; }
|
||||
|
||||
virtual void Update() = 0;
|
||||
|
||||
/// Return the current display handle.
|
||||
virtual void *GetHandle() const { return 0; }
|
||||
/// Set display handle.
|
||||
virtual void SetHandle(void *) {}
|
||||
|
||||
/// Return a list of devices available on this system.
|
||||
virtual bool GetDeviceList(StringList &, Device::Type = Device::Type_Any) const { return true; }
|
||||
/// Return a list of guid devices available on this system.
|
||||
virtual bool GetDeviceGuidList(StringList &, Device::Type = Device::Type_Any) const { return true; }
|
||||
|
||||
/// Get a device from its name.
|
||||
virtual Device *GetDevice(const char *name) = 0;
|
||||
virtual Device *GetDeviceFromGuid(const char *name) {return NULL;};
|
||||
|
||||
virtual ~System() {}
|
||||
};
|
||||
|
||||
} // Input
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __INPUT_SYSTEM__
|
||||
59
include/platform/input/input_touch.h
Normal file
59
include/platform/input/input_touch.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __INPUT_TOUCH__
|
||||
#define __INPUT_TOUCH__
|
||||
|
||||
|
||||
#include "input/input_device.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Input {
|
||||
|
||||
/*
|
||||
@short Touch input device.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
class TouchDevice : public Device
|
||||
{
|
||||
protected:
|
||||
|
||||
struct State
|
||||
{
|
||||
float x, y;
|
||||
bool button;
|
||||
};
|
||||
|
||||
int index;
|
||||
State state, last_state, pending_state;
|
||||
|
||||
public:
|
||||
|
||||
virtual Type GetType() const;
|
||||
virtual const char *GetName() const;
|
||||
|
||||
virtual void Update();
|
||||
|
||||
virtual bool IsDown(KeyCode) const;
|
||||
virtual bool WasDown(KeyCode) const;
|
||||
|
||||
virtual bool GetInputRange(InputCode, float &min, float &max) const;
|
||||
|
||||
virtual float GetValue(InputCode) const;
|
||||
virtual float GetLastValue(InputCode) const;
|
||||
|
||||
void SetIndex(int);
|
||||
void RegisterTouchEvent(float x, float y, float weight);
|
||||
|
||||
TouchDevice(int index = -1);
|
||||
};
|
||||
|
||||
} // Input
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __INPUT_TOUCH__
|
||||
30
include/platform/licensing/licensing.h
Normal file
30
include/platform/licensing/licensing.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __LICENSING__
|
||||
#define __LICENSING__
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short License system interface.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
struct ILicensing
|
||||
{
|
||||
// Event handler for the license system.
|
||||
virtual void onLicensingEvent(const char *) = 0;
|
||||
/// Request an update of the application license.
|
||||
virtual bool updateLicence(const char *) = 0;
|
||||
|
||||
virtual ~ILicensing() {}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __LICENSING__
|
||||
37
include/platform/locale/country.h
Normal file
37
include/platform/locale/country.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NCOUNTRY__
|
||||
#define __NCOUNTRY__
|
||||
|
||||
|
||||
#include "nstring/nstring.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Locale {
|
||||
|
||||
struct Info
|
||||
{
|
||||
String continent, region, country, fips, iso2, iso3;
|
||||
int iso;
|
||||
String internet;
|
||||
};
|
||||
|
||||
// FIPS 10-4: American National Standard Codes for the Representation of Names of Countries, Dependencies, and Areas of Special Sovereignty for Information Interchange.
|
||||
const Info *GetFIPSCountry(const char *);
|
||||
// ISO 3166: Two-character.
|
||||
const Info *GetISO2Country(const char *);
|
||||
// ISO 3166: Three-character.
|
||||
const Info *GetISO3Country(const char *);
|
||||
// ISO 3166: Three-digit.
|
||||
const Info *GetISOCountry(int);
|
||||
|
||||
} // Locale
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NCOUNTRY__
|
||||
38
include/platform/log/file_log.h
Normal file
38
include/platform/log/file_log.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NFILELOG__
|
||||
#define __NFILELOG__
|
||||
|
||||
|
||||
#include "nstring/nstring.h"
|
||||
#include "log/log.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short File log.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
class FileLog : public Log
|
||||
{
|
||||
String path;
|
||||
|
||||
bool do_timestamp;
|
||||
bool initial_write;
|
||||
|
||||
public:
|
||||
|
||||
virtual void NewLog(const char *log, char entry_level = EngineLogStandard);
|
||||
|
||||
FileLog(const char *path, bool do_timestamp = false);
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NFILELOG__
|
||||
137
include/platform/log/log.h
Normal file
137
include/platform/log/log.h
Normal file
@ -0,0 +1,137 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NLOG__
|
||||
#define __NLOG__
|
||||
|
||||
|
||||
#include "ntypes.h"
|
||||
#include "memory/singleton.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
class String;
|
||||
|
||||
namespace Threading { class Mutex; }
|
||||
|
||||
/*!
|
||||
Define the maximum log line length.
|
||||
*/
|
||||
#define LOG_LINE_MAX_LEN 8192
|
||||
|
||||
/*!
|
||||
@short Log.
|
||||
|
||||
The log subsystem provides several log levels to enable activation and
|
||||
deactivation of a whole log level.
|
||||
|
||||
The following log streams are available to log to the different levels:
|
||||
|
||||
* __LOG_H__: Header (eg: __LOG_H__ << "Physics entry point.\n")
|
||||
* __LOG_W__: Warning
|
||||
* __LOG_E__: Error
|
||||
* __LOG_E__: Non-maskable
|
||||
|
||||
Standard logs may be output to the __LOG__ stream.
|
||||
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
class Log
|
||||
{
|
||||
protected:
|
||||
|
||||
Threading::Mutex *mutex;
|
||||
|
||||
#if __PLATFORM_LOG_SUPPORT__
|
||||
char full_a[LOG_LINE_MAX_LEN], full_b[LOG_LINE_MAX_LEN];
|
||||
char *a, *b;
|
||||
#endif
|
||||
|
||||
#define EngineLogNone 0 ///< Log no log ouput
|
||||
#define EngineLogStandard 1
|
||||
#define EngineLogHeader 2
|
||||
#define EngineLogWarning 4
|
||||
#define EngineLogError 8
|
||||
#define EngineLogVerbose 16
|
||||
#define EngineLogScript 32
|
||||
#define EngineLogAll ~0
|
||||
|
||||
uint log_level;
|
||||
|
||||
public:
|
||||
|
||||
/// Set the log level.
|
||||
void SetLogLevel(uint level = EngineLogAll)
|
||||
{ log_level = level; }
|
||||
/// Get the current log level.
|
||||
uint GetLogLevel() const
|
||||
{ return log_level; }
|
||||
|
||||
/// Get the log mutex.
|
||||
Threading::Mutex &GetMutex()
|
||||
{ return *mutex; }
|
||||
|
||||
Log &operator << (const char);
|
||||
Log &operator << (const short);
|
||||
Log &operator << (const int);
|
||||
Log &operator << (const uchar);
|
||||
Log &operator << (const ushort);
|
||||
Log &operator << (const uint);
|
||||
#if __PLATFORM_IOS__
|
||||
Log &operator << (const size_t);
|
||||
#endif
|
||||
Log &operator << (const float);
|
||||
Log &operator << (const bool);
|
||||
Log &operator << (const void *);
|
||||
Log &operator << (const char *);
|
||||
Log &operator << (const String &);
|
||||
|
||||
void LogProcessed();
|
||||
|
||||
/// Implement to receive new log lines.
|
||||
virtual void NewLog(const char *log, char entry_level = EngineLogStandard);
|
||||
|
||||
Log();
|
||||
virtual ~Log();
|
||||
};
|
||||
|
||||
/// Log system.
|
||||
class LogSystem : public Singleton <LogSystem>
|
||||
{
|
||||
Log *log;
|
||||
|
||||
public:
|
||||
|
||||
/// Set the log object.
|
||||
void SetLog(Log *log = 0);
|
||||
/// Get the current log object.
|
||||
Log &GetLog();
|
||||
|
||||
LogSystem();
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#define __LOG__ GS::LogSystem::Get().GetLog() // Standard
|
||||
#define __LOG_H__ __LOG__ << "[H] " // Header
|
||||
#define __LOG_CAM__ __LOG__ << "[WEBCAM] " // Header
|
||||
#if 0
|
||||
#define __LOG_W__ __LOG__ << "[*] " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << ") " // Warning
|
||||
#define __LOG_E__ __LOG__ << "[!] " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << ") " // Error
|
||||
#else
|
||||
#define __LOG_W__ __LOG__ << "[*] "
|
||||
#define __LOG_E__ __LOG__ << "[!] "
|
||||
#endif
|
||||
#define __LOG_V__ __LOG__ << "[V] " // Verbose
|
||||
#define __LOG_F__ __LOG__ << __FUNCTION__ << ": "
|
||||
|
||||
#define __LOG_FUNC__ __LOG_V__ << __FUNCTION__ << "\n";
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NLOG__
|
||||
26
include/platform/log/log_scope.h
Normal file
26
include/platform/log/log_scope.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NLOGSCOPE__
|
||||
#define __NLOGSCOPE__
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
class LogScope
|
||||
{
|
||||
const char *exit;
|
||||
|
||||
public:
|
||||
|
||||
LogScope(const char *enter, const char *exit);
|
||||
~LogScope();
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NFILELOG__
|
||||
78
include/platform/math/nmath.h
Normal file
78
include/platform/math/nmath.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NMATH__
|
||||
#define __NMATH__
|
||||
|
||||
|
||||
#include "unit/nunit.h"
|
||||
|
||||
|
||||
/*
|
||||
@short Math namespace.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
namespace GS {
|
||||
namespace Math {
|
||||
|
||||
static const float Pi = 3.1415926535f;
|
||||
|
||||
/// Euler angles rotation order.
|
||||
enum rOrder
|
||||
{
|
||||
rOrder_ZYX = 0,
|
||||
rOrder_YZX,
|
||||
rOrder_ZXY,
|
||||
rOrder_XZY,
|
||||
rOrder_YXZ,
|
||||
rOrder_XYZ,
|
||||
rOrder_XY,
|
||||
|
||||
rOrder_Default = rOrder_YXZ // Y then X then Z.
|
||||
};
|
||||
|
||||
enum Axis
|
||||
{
|
||||
AxisX, // Do not modify X, Y and Z order.
|
||||
AxisY,
|
||||
AxisZ,
|
||||
AxisNone
|
||||
};
|
||||
|
||||
void Init();
|
||||
|
||||
/// Return the reverse rotation order from a given input order.
|
||||
rOrder ReverserRotationOrder(rOrder r);
|
||||
|
||||
float Sqrt(float v);
|
||||
|
||||
float TestEqual(float a, float b, float e = 0.000001f);
|
||||
bool EqualZero(float v, float e = 0.000001f);
|
||||
|
||||
float Pow(float v, float exp);
|
||||
|
||||
float Ceil(float);
|
||||
float Floor(float);
|
||||
float Mod(float);
|
||||
|
||||
float RangeAdjust(float v, float old_min, float old_max, float new_min, float new_max);
|
||||
|
||||
float Quantize(float v, float q);
|
||||
|
||||
float Sin(float);
|
||||
float ASin(float);
|
||||
float Cos(float);
|
||||
float ACos(float);
|
||||
float Tan(float);
|
||||
float ATan(float);
|
||||
|
||||
bool IsFinite(float);
|
||||
|
||||
} // Math
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NMATH__
|
||||
49
include/platform/math/nrange.h
Normal file
49
include/platform/math/nrange.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NRANGE__
|
||||
#define __NRANGE__
|
||||
|
||||
|
||||
#include "math/nrange.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short Range.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> struct Range
|
||||
{
|
||||
T start, end;
|
||||
|
||||
T valueRange() const { return end - start; }
|
||||
bool inRange(const T &v) const { return (start < end) ? ((v >= start) && (v < end)) : ((v >= end) && (v < start)); }
|
||||
void sort() { if (start > end) { T t = start; start = end; end = t; } }
|
||||
|
||||
static Range Intersection(const Range <T> &a, const Range <T> &b)
|
||||
{
|
||||
if ((a.end < b.start) || (a.start > b.end))
|
||||
return Range <T> ();
|
||||
return Range(a.start > b.start ? a.start : b.start, a.end < b.end ? a.end : b.end);
|
||||
}
|
||||
static Range Union(const Range &a, const Range &b)
|
||||
{ return Range(a.start < b.start ? a.start : b.start, a.end > b.end ? a.end : b.end); }
|
||||
|
||||
void Set(const T &s, const T &e) { start = s; end = e; }
|
||||
|
||||
template <class N> Range <N> convert() const
|
||||
{ return Range <N> (N(start), N(end)); }
|
||||
|
||||
Range(const T &s, const T &e) : start(s), end(e) {}
|
||||
Range() : start(0), end(0) {}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NRANGE__
|
||||
60
include/platform/memory/bit_field.h
Normal file
60
include/platform/memory/bit_field.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NBITFIELD__
|
||||
#define __NBITFIELD__
|
||||
|
||||
|
||||
#include "ntypes.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
class BitField
|
||||
{
|
||||
uint v;
|
||||
|
||||
public:
|
||||
|
||||
BitField &operator &= (uint b) { v &= b; return *this; }
|
||||
BitField &operator |= (uint b) { v |= b; return *this; }
|
||||
BitField &operator = (uint b) { v = b; return *this; }
|
||||
|
||||
BitField &operator &= (const BitField &b) { v &= b.v; return *this; }
|
||||
BitField &operator |= (const BitField &b) { v |= b.v; return *this; }
|
||||
BitField &operator = (const BitField &b) { v = b.v; return *this; }
|
||||
|
||||
bool operator == (const BitField &b) const { return v == b.v; }
|
||||
bool operator != (const BitField &b) const { return v != b.v; }
|
||||
|
||||
inline uint Get() const
|
||||
{
|
||||
return v;
|
||||
}
|
||||
inline uint Set(uint b)
|
||||
{
|
||||
v |= b;
|
||||
return v;
|
||||
}
|
||||
inline uint Remove(uint b)
|
||||
{
|
||||
v &= ~b;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline uint Raise(uint b, bool raise = true)
|
||||
{
|
||||
return raise ? Set(b) : Remove(b);
|
||||
}
|
||||
inline bool IsSet(uint b) const { return asbool(v & b); }
|
||||
|
||||
BitField() : v(0) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // __NBITFIELD__
|
||||
52
include/platform/memory/endian.h
Normal file
52
include/platform/memory/endian.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NENDIAN__
|
||||
#define __NENDIAN__
|
||||
|
||||
|
||||
#include "ntypes.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Endian {
|
||||
|
||||
enum Config
|
||||
{
|
||||
Undefined = 0,
|
||||
|
||||
Big,
|
||||
Little,
|
||||
|
||||
Motorola = Big,
|
||||
Intel = Little
|
||||
};
|
||||
|
||||
/// Swap bytes in memory.
|
||||
void SwapBytes(void *, size_t);
|
||||
|
||||
/// Return the current host memory configuration.
|
||||
Config GetHostConfiguration();
|
||||
|
||||
/// Convert a memory block to the host configuration.
|
||||
void *ToHost(void *, size_t, Config = Big);
|
||||
|
||||
/// Convert a value to the host configuration.
|
||||
template <class T> T ToHost(const T &v, Config cfg = Big)
|
||||
{
|
||||
if (GetHostConfiguration() == cfg)
|
||||
return v;
|
||||
|
||||
T host_value = v;
|
||||
SwapBytes(&host_value, sizeof(T));
|
||||
return host_value;
|
||||
}
|
||||
|
||||
} // Endian
|
||||
} // GS
|
||||
|
||||
|
||||
#endif //__NENDIAN__
|
||||
36
include/platform/memory/memory.h
Normal file
36
include/platform/memory/memory.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NMEMORY__
|
||||
#define __NMEMORY__
|
||||
|
||||
|
||||
#include "ntypes.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Memory {
|
||||
|
||||
/// Return smallest number of bits that can be used to represent a value.
|
||||
uchar GetBitCount(int);
|
||||
/// Return the position in bit of the first non-zero bit.
|
||||
uchar GetShiftCount(int);
|
||||
/// Return the number of bit set in a given value.
|
||||
uchar CountSetBit(int);
|
||||
|
||||
void WriteBit(uchar *, uint offset_in_bit, uint bit_count, uint value);
|
||||
uint ReadBit(uchar *, uint offset_in_bit, uint bit_count);
|
||||
|
||||
bool Compare(const void *, const void *, size_t);
|
||||
void Copy(void *, const void *, size_t);
|
||||
void Set(void *, char, size_t);
|
||||
|
||||
void Fill(void *, const char *pattern, size_t);
|
||||
} // Memory
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NMEMORY__
|
||||
78
include/platform/memory/nauto_ptr.h
Normal file
78
include/platform/memory/nauto_ptr.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NAUTO_PTR__
|
||||
#define __NAUTO_PTR__
|
||||
|
||||
|
||||
#include "alloc/ialloc.h"
|
||||
#include "billing/billing.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short Auto pointer.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> class AutoPtr
|
||||
{
|
||||
private:
|
||||
|
||||
T *o;
|
||||
|
||||
public:
|
||||
|
||||
inline operator T*() const
|
||||
{ return o; }
|
||||
inline T *c_ptr() const
|
||||
{ return o; }
|
||||
|
||||
inline bool IsNull() const { return o ? false : true; }
|
||||
inline bool IsValid() const { return o ? true : false; }
|
||||
|
||||
T *operator = (T *p)
|
||||
{
|
||||
if (o != p)
|
||||
{
|
||||
delete(o);
|
||||
o = p;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
inline T &operator[] (size_t n) { return o[n]; }
|
||||
|
||||
inline bool operator == (const T *p) const
|
||||
{ return o == p; }
|
||||
inline bool operator != (const T *p) const
|
||||
{ return o != p; }
|
||||
|
||||
inline T *operator -> () const
|
||||
{ return o; }
|
||||
inline T &operator * () const
|
||||
{ return *o; }
|
||||
|
||||
inline T *Detach()
|
||||
{
|
||||
T *p = o;
|
||||
o = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
explicit AutoPtr(T *p = 0) : o(p)
|
||||
{}
|
||||
~AutoPtr()
|
||||
{
|
||||
delete(o);
|
||||
o = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NAUTO_PTR__
|
||||
150
include/platform/memory/nshared_ptr.h
Normal file
150
include/platform/memory/nshared_ptr.h
Normal file
@ -0,0 +1,150 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NSHARED_PTR__
|
||||
#define __NSHARED_PTR__
|
||||
|
||||
|
||||
#include "thread/atomic_value.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/// Weak reference to a shared object.
|
||||
class WeakRef
|
||||
{
|
||||
friend class SharedObject;
|
||||
|
||||
bool is_valid;
|
||||
Threading::Atomic32 refc;
|
||||
|
||||
WeakRef() : is_valid(true) {}
|
||||
|
||||
public:
|
||||
|
||||
bool IsValid() const { return is_valid; }
|
||||
|
||||
int GetRefCount() const { return refc.Get(); }
|
||||
|
||||
void AddRef() { refc.Inc(); }
|
||||
void RemoveRef()
|
||||
{
|
||||
if ((refc.Dec() == 0) && !is_valid)
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
@short Reference counted object.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
class SharedObject
|
||||
{
|
||||
Threading::Atomic32 refc;
|
||||
WeakRef *weak_ref;
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~SharedObject()
|
||||
{
|
||||
if (weak_ref)
|
||||
{
|
||||
if (weak_ref->refc.Get() == 0)
|
||||
delete weak_ref;
|
||||
else
|
||||
weak_ref->is_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
WeakRef *GetWeakRef()
|
||||
{
|
||||
if (!weak_ref)
|
||||
weak_ref = new WeakRef; // TODO have a specialized, fixed pool allocator for these.
|
||||
return weak_ref;
|
||||
}
|
||||
|
||||
int GetRefCount() const { return refc.Get(); }
|
||||
|
||||
void AddRef() { refc.Inc(); }
|
||||
void RemoveRef()
|
||||
{
|
||||
if (refc.Dec() == 0)
|
||||
{
|
||||
if (weak_ref)
|
||||
weak_ref->is_valid = false;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
SharedObject() : weak_ref(0) {}
|
||||
};
|
||||
|
||||
/*!
|
||||
@short Strong smart pointer to a reference counted object.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> class SharedPtr
|
||||
{
|
||||
T *rc_o;
|
||||
|
||||
public:
|
||||
|
||||
inline operator T *() const { return rc_o; }
|
||||
inline T *c_ptr() const { return rc_o; }
|
||||
|
||||
inline bool IsNull() const { return rc_o ? false : true; }
|
||||
inline bool IsValid() const { return rc_o ? true : false; }
|
||||
|
||||
void Init()
|
||||
{
|
||||
if (rc_o)
|
||||
rc_o->AddRef();
|
||||
}
|
||||
|
||||
inline bool operator == (const T *p) const { return rc_o == p; }
|
||||
inline bool operator != (const T *p) const { return rc_o != p; }
|
||||
inline bool operator == (T *p) const { return rc_o == p; }
|
||||
inline bool operator != (T *p) const { return rc_o != p; }
|
||||
|
||||
inline bool operator == (const SharedPtr &p) const { return rc_o == p.rc_o; }
|
||||
inline bool operator != (const SharedPtr &p) const { return rc_o != p.rc_o; }
|
||||
|
||||
T *operator = (T *p)
|
||||
{
|
||||
if (rc_o != p)
|
||||
{
|
||||
if (rc_o)
|
||||
rc_o->RemoveRef();
|
||||
rc_o = p;
|
||||
Init();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
SharedPtr <T> &operator = (const SharedPtr &p)
|
||||
{
|
||||
*this = p.c_ptr();
|
||||
return *this;
|
||||
}
|
||||
inline T *operator -> () const { return rc_o; }
|
||||
inline T &operator * () const { return *rc_o; }
|
||||
|
||||
explicit SharedPtr(T *p) : rc_o(p) { Init(); }
|
||||
SharedPtr(const SharedPtr &p) : rc_o(p.rc_o) { Init(); }
|
||||
SharedPtr() : rc_o(0) {}
|
||||
|
||||
~SharedPtr()
|
||||
{
|
||||
if (rc_o)
|
||||
rc_o->RemoveRef();
|
||||
}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NSHARED_PTR__
|
||||
101
include/platform/memory/nweak_ptr.h
Normal file
101
include/platform/memory/nweak_ptr.h
Normal file
@ -0,0 +1,101 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NWEAK_PTR__
|
||||
#define __NWEAK_PTR__
|
||||
|
||||
|
||||
#include "memory/nshared_ptr.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short Weak pointer to a reference counted object.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> class WeakPtr
|
||||
{
|
||||
private:
|
||||
|
||||
T *rc_o;
|
||||
WeakRef *wref;
|
||||
|
||||
public:
|
||||
|
||||
T *c_ptr() const { return wref && wref->IsValid() ? rc_o : 0; }
|
||||
|
||||
bool IsValid() const { return wref && wref->IsValid() ? true : false; }
|
||||
bool IsNull() const { return !IsValid(); }
|
||||
|
||||
/// Lock pointed object to a strong pointer.
|
||||
bool Lock(SharedPtr <T> &p)
|
||||
{
|
||||
if (IsNull())
|
||||
return false;
|
||||
p = rc_o;
|
||||
return true;
|
||||
}
|
||||
SharedPtr <T> Lock() const { return SharedPtr <T> (IsValid() ? rc_o : 0); }
|
||||
|
||||
void Init()
|
||||
{
|
||||
if (!rc_o)
|
||||
wref = 0;
|
||||
else
|
||||
{
|
||||
wref = rc_o->GetWeakRef();
|
||||
wref->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator == (const T *p) const
|
||||
{ return rc_o == p; }
|
||||
inline bool operator != (const T *p) const
|
||||
{ return rc_o != p; }
|
||||
inline bool operator == (T *p) const
|
||||
{ return rc_o == p; }
|
||||
inline bool operator != (T *p) const
|
||||
{ return rc_o != p; }
|
||||
|
||||
inline bool operator == (const WeakPtr &p) const
|
||||
{ return rc_o == p.rc_o; }
|
||||
inline bool operator != (const WeakPtr &p) const
|
||||
{ return rc_o != p.rc_o; }
|
||||
|
||||
WeakPtr <T> &operator = (const WeakPtr &p)
|
||||
{
|
||||
if (rc_o != p.rc_o)
|
||||
{
|
||||
WeakRef *old_wref = wref;
|
||||
|
||||
rc_o = p.rc_o;
|
||||
Init();
|
||||
|
||||
if (old_wref)
|
||||
old_wref->RemoveRef();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline T *operator -> () const
|
||||
{ return rc_o; }
|
||||
inline T &operator * () const
|
||||
{ return *rc_o; }
|
||||
|
||||
WeakPtr(T *p = 0) : rc_o(p) { Init(); }
|
||||
WeakPtr(const WeakPtr &p) : rc_o(p.rc_o) { Init(); }
|
||||
WeakPtr(const SharedPtr <T> &p) : rc_o(p.c_ptr()) { Init(); }
|
||||
~WeakPtr()
|
||||
{
|
||||
if (wref)
|
||||
wref->RemoveRef();
|
||||
}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NWEAK_PTR__
|
||||
80
include/platform/memory/ring_buffer.h
Normal file
80
include/platform/memory/ring_buffer.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NRINGBUFFER__
|
||||
#define __NRINGBUFFER__
|
||||
|
||||
|
||||
#include "container/narray.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*
|
||||
@short Ring buffer.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
template <class T> class RingBuffer
|
||||
{
|
||||
Array <T> buffer;
|
||||
uint put, get, usage;
|
||||
|
||||
public:
|
||||
|
||||
/// Get the maximum number of element in buffer.
|
||||
uint GetCount() const
|
||||
{ return buffer.GetCount(); }
|
||||
|
||||
/// Number of T left to put in the buffer.
|
||||
uint GetFree() const
|
||||
{ return buffer.GetCount() - usage; }
|
||||
/// Number of T available to get from the buffer.
|
||||
uint GetUsage() const
|
||||
{ return usage; }
|
||||
|
||||
/// Increment the put pointer, returns true when successful.
|
||||
bool Produce()
|
||||
{
|
||||
if (usage == buffer.GetCount())
|
||||
return false;
|
||||
|
||||
put = (put + 1) % buffer.GetCount();
|
||||
usage++;
|
||||
|
||||
return true;
|
||||
}
|
||||
/// Increment the get pointer, returns true when successful.
|
||||
bool Consume()
|
||||
{
|
||||
if (usage == 0)
|
||||
return false;
|
||||
|
||||
get = (get + 1) % buffer.GetCount();
|
||||
usage--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Retrieve the object at the current get pointer.
|
||||
T &CurrentGet()
|
||||
{ return buffer[get]; }
|
||||
/// Retrieve the object at the current put pointer.
|
||||
T &CurrentPut()
|
||||
{ return buffer[put]; }
|
||||
|
||||
bool Allocate(uint count)
|
||||
{
|
||||
put = get = usage = 0;
|
||||
return buffer.Allocate(count);
|
||||
}
|
||||
|
||||
RingBuffer() : put(0), get(0), usage(0) {}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NRINGBUFFER__
|
||||
28
include/platform/memory/singleton.h
Normal file
28
include/platform/memory/singleton.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __SINGLETON__
|
||||
#define __SINGLETON__
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
template <class T> class Singleton
|
||||
{
|
||||
static T *i;
|
||||
|
||||
public:
|
||||
|
||||
static T &Get() { return *i; }
|
||||
static void Set(T *s) { i = s; }
|
||||
static void Free() { delete i; i = nullptr; }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // __SINGLETON__
|
||||
48
include/platform/messaging/messaging.h
Normal file
48
include/platform/messaging/messaging.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __MESSAGING__
|
||||
#define __MESSAGING__
|
||||
|
||||
|
||||
#include "container/nlist.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Messaging {
|
||||
|
||||
/*!
|
||||
@short Low-level message broadcasting system.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
template <class Message, class Listener, class From, class Parm = void *> class Broadcaster
|
||||
{
|
||||
protected:
|
||||
|
||||
/// Message listener list.
|
||||
List <Listener *> listener_list;
|
||||
|
||||
public:
|
||||
|
||||
bool RegisterMessageListener(Listener *listener)
|
||||
{ return listener_list.Add(listener) ? true : false; }
|
||||
bool UnregisterMessageListener(Listener *listener)
|
||||
{ return listener_list.Remove(listener); }
|
||||
|
||||
virtual void BroadcastMessage(const Message &msg, const From &from, const Parm &parm)
|
||||
{
|
||||
ListForeachPtr(Listener *, listener, listener_list)
|
||||
listener->ProcessMessage(msg, from, parm);
|
||||
}
|
||||
|
||||
virtual ~Broadcaster() {}
|
||||
};
|
||||
|
||||
} // Messaging
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __MESSAGING__
|
||||
73
include/platform/nconfig.h
Normal file
73
include/platform/nconfig.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __GSCONFIG__
|
||||
#define __GSCONFIG__
|
||||
|
||||
|
||||
/// Define to disable all debug/tracking code.
|
||||
#ifndef __ENGINE_RETAIL__
|
||||
#define __ENGINE_RETAIL__ 0
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Engine configuration.
|
||||
//------------------------------------------------------------------------------
|
||||
/// Enable logging system support.
|
||||
#define __PLATFORM_LOG_SUPPORT__ 1
|
||||
|
||||
/*!
|
||||
@short Maximum UV channel count.
|
||||
This value has no limitation, however try to keep it in a reasonable
|
||||
range to avoid wasting memory and preserve compatibility.
|
||||
@note The lowest acceptable value is 1. (Default: 3)
|
||||
*/
|
||||
#define __UV_PER_GEOMETRY__ 3
|
||||
/*!
|
||||
@short Bone/vertex limit.
|
||||
*/
|
||||
#define __PV_BONE_LIMIT__ 4
|
||||
/*!
|
||||
@short Bone/list limit.
|
||||
*/
|
||||
#define __PL_BONE_LIMIT__ 48
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Debug configuration.
|
||||
//------------------------------------------------------------------------------
|
||||
#if __ENGINE_RETAIL__
|
||||
|
||||
/*
|
||||
Deactivate unneeded subsystems for a retail build.
|
||||
*/
|
||||
#undef __PLATFORM_LOG_SUPPORT__
|
||||
#define __PLATFORM_LOG_SUPPORT__ 0
|
||||
|
||||
#else // __ENGINE_RETAIL__
|
||||
|
||||
/*!
|
||||
@short Define to enable per allocation statistics.
|
||||
@note All allocations are inflated by a monitoring header.
|
||||
The allocators are adapted to fit the increased allocations
|
||||
so that their behavior will not change.
|
||||
@note A 2 bytes long magic word is added to the end of each allocation
|
||||
and checked for overrun on release.
|
||||
*/
|
||||
#define __ENABLE_ALLOCATION_STAT__ 0
|
||||
/// Define to enable end of allocation overwrite detection.
|
||||
#define __ENABLE_ALLOCATION_GUARD__ 0
|
||||
|
||||
/// Enable the small block allocator system (ialloc.cpp).
|
||||
#define __ENABLE_GLOBAL_SBA__ 0
|
||||
|
||||
#endif // __ENGINE_RETAIL__
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // __GSCONFIG__
|
||||
74
include/platform/network/network_interface.h
Normal file
74
include/platform/network/network_interface.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NETWORK_INTERFACE__
|
||||
#define __NETWORK_INTERFACE__
|
||||
|
||||
|
||||
#include "container/narray.h"
|
||||
#include "ntypes.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
class String;
|
||||
namespace Network {
|
||||
|
||||
//
|
||||
struct INetwork
|
||||
{
|
||||
enum Timeout
|
||||
{
|
||||
TimeoutDefault = 0,
|
||||
TimeoutLong,
|
||||
TimeoutVeryLong
|
||||
};
|
||||
|
||||
virtual bool SendString(void *peer, const String &);
|
||||
virtual bool BroadcastString(const String &);
|
||||
|
||||
struct Statistics
|
||||
{
|
||||
size_t sent_data;
|
||||
size_t received_data;
|
||||
};
|
||||
|
||||
virtual void GetStatistics(Statistics &) = 0;
|
||||
virtual int GetPeerPacketLossRatio(void *peer) = 0;
|
||||
|
||||
virtual void OnPeerConnection(void *peer) = 0;
|
||||
virtual void OnPacketReceived(void *peer, const void *data, size_t size) = 0;
|
||||
virtual void OnConnectionClosed(void *peer) = 0;
|
||||
|
||||
/*!
|
||||
@name Communication interface.
|
||||
@{
|
||||
*/
|
||||
virtual void UpdateHost() = 0;
|
||||
|
||||
virtual bool Send(void *peer, const void *data, size_t size) = 0;
|
||||
virtual bool Broadcast(const void *data, size_t size) = 0;
|
||||
/// @}
|
||||
|
||||
virtual bool IsOpen() const = 0;
|
||||
|
||||
virtual bool GetHostAddress(String &address) = 0;
|
||||
virtual bool GetPeerAddress(void *peer, String &address) = 0;
|
||||
virtual void SetPeerTimeout(void *peer, Timeout = TimeoutDefault) = 0;
|
||||
|
||||
virtual bool OpenServer(const char *address, int port) = 0;
|
||||
virtual bool OpenClient(const char *address, int port) = 0;
|
||||
virtual void Disconnect(void *peer) = 0;
|
||||
|
||||
virtual void Close() = 0;
|
||||
|
||||
virtual ~INetwork() {}
|
||||
};
|
||||
|
||||
} // Network
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NETWORK_INTERFACE__
|
||||
310
include/platform/nstring/nstring.h
Normal file
310
include/platform/nstring/nstring.h
Normal file
@ -0,0 +1,310 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NSTRING__
|
||||
#define __NSTRING__
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include "container/narray.h"
|
||||
|
||||
namespace GS {
|
||||
template <class T> class List;
|
||||
template <class T> class Array;
|
||||
|
||||
/*!
|
||||
@short String class.
|
||||
Strings are internally stored as UTF-8.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
class String
|
||||
{
|
||||
Array <char> _p;
|
||||
|
||||
mutable uint hash;
|
||||
int len;
|
||||
|
||||
void Touch();
|
||||
|
||||
public:
|
||||
|
||||
enum CaseSensitivity
|
||||
{
|
||||
CaseSensitive = 0,
|
||||
CaseInsensitive
|
||||
};
|
||||
|
||||
enum EOLConvention
|
||||
{
|
||||
EOLUnix = 0,
|
||||
EOLWindows
|
||||
};
|
||||
|
||||
/*!
|
||||
@short Compare string object with a C string
|
||||
Optionally accept a hash value for the input string.
|
||||
@return True if strings match.
|
||||
*/
|
||||
bool equals(const char *s, const uint hash = 0) const;
|
||||
|
||||
bool operator == (const String &) const;
|
||||
bool operator != (const String &) const;
|
||||
bool operator == (const char *) const;
|
||||
bool operator != (const char *) const;
|
||||
|
||||
/// Format a string.
|
||||
static String Format(const char *format, ...);
|
||||
|
||||
String operator + (const char *) const;
|
||||
String operator + (const String &) const;
|
||||
|
||||
void operator += (const char *);
|
||||
void operator += (const String &);
|
||||
void operator += (float);
|
||||
void operator += (double);
|
||||
void operator += (int);
|
||||
void operator += (uint);
|
||||
void operator += (bool);
|
||||
|
||||
String &operator = (const String &);
|
||||
String &operator = (const char *);
|
||||
|
||||
void Set(const char *s, const char *e = 0);
|
||||
|
||||
String &operator << (const String &);
|
||||
String &operator << (const char *);
|
||||
String &operator << (float);
|
||||
String &operator << (double);
|
||||
String &operator << (int);
|
||||
String &operator << (uint);
|
||||
String &operator << (bool);
|
||||
|
||||
/// String hash value.
|
||||
uint Hash() const;
|
||||
/// String length.
|
||||
uint Len() const;
|
||||
/// String size in bytes.
|
||||
size_t Size() const;
|
||||
|
||||
/// Is empty.
|
||||
inline bool IsEmpty() const { return (!_p || !len) ? true : false; }
|
||||
|
||||
/// Normalize the string end of line.
|
||||
void NormalizeEOL(EOLConvention = EOLUnix);
|
||||
/// Return a normalized version of this string.
|
||||
String NormalizedEOL(EOLConvention = EOLUnix) const;
|
||||
|
||||
/*!
|
||||
@name File system tool set.
|
||||
@{
|
||||
*/
|
||||
/// Is absolute path.
|
||||
bool IsAbsolutePath() const;
|
||||
|
||||
String BeautifyFileName(bool allow_spaces = true) const;
|
||||
|
||||
String CleanFilePath() const;
|
||||
|
||||
String CutFilePath() const;
|
||||
String CutFileName() const;
|
||||
String CutFileExtension() const;
|
||||
|
||||
String GetFilePath() const;
|
||||
String GetFileName() const;
|
||||
String GetFileNameAndExtension() const;
|
||||
String GetFileExtension() const;
|
||||
|
||||
/// Return this filename with another file extension.
|
||||
String GetSwappedExtension(const char *) const;
|
||||
|
||||
void FileCutPath();
|
||||
void FileSwapExtension(const char *);
|
||||
void FileCutPathAndExtension();
|
||||
void FileCutExtension();
|
||||
void FileCutName();
|
||||
|
||||
/// Get extension.
|
||||
static String FileGetExtension(const char *path);
|
||||
/// Convert backslash to slash, merge redundant slash.
|
||||
bool FileCleanName();
|
||||
/// @}
|
||||
|
||||
/// Return as utf-8 ASCII C string.
|
||||
inline operator const char *() const { return _p; }
|
||||
/// Return as utf-8 ASCII C string.
|
||||
inline const char *c_str() const { return _p; }
|
||||
inline char *str() const { return _p; }
|
||||
/// Return a pointer to the end of the string.
|
||||
inline const char *eos() const { return _p + Len(); }
|
||||
/*!
|
||||
@name Unicode tool set.
|
||||
@{
|
||||
*/
|
||||
/// Convert an utf-8 character to utf-32, returns the number of consumed bytes.
|
||||
static size_t Utf8toUtf32(const uchar *utf8, uint *utf32);
|
||||
/// Get utf-8 character size in byte.
|
||||
static size_t GetUtf8CharSize(const uchar *utf8);
|
||||
|
||||
/// Create a string from a UCS-2 buffer.
|
||||
static String FromUcs2(const ushort *);
|
||||
|
||||
/// Return as utf-8
|
||||
inline const char *toUtf8() const { return _p; }
|
||||
/// Return string as UCS-2 (utf-16 compatible up to code point 0xffff).
|
||||
Array <ushort> toUcs2() const;
|
||||
/// Return string as utf-32.
|
||||
Array <uint> toUtf32() const;
|
||||
/// @}
|
||||
|
||||
/// Remove all occurrences of a given character from the string.
|
||||
String TrimChar(char);
|
||||
|
||||
/// ASCII to float.
|
||||
inline float Float(bool support_comma = true) const { return atof(_p, _p + Len(), support_comma); }
|
||||
/// ASCII to integer.
|
||||
inline int Integer() const { return atoi(_p); }
|
||||
/// ASCII header less, 0x or h prefixed hexadecimal to integer.
|
||||
inline int Hex() const { return atoh(_p); }
|
||||
|
||||
/// Split string against a separator string.
|
||||
template <class C> uint Split(const char *separator, C &container, const char skip = 0) const
|
||||
{
|
||||
const char *s = c_str();
|
||||
if (!s)
|
||||
return 0;
|
||||
size_t ls = strlen(separator);
|
||||
|
||||
for (const char *n = s; s[0]; s = n)
|
||||
{
|
||||
// Check the skip char.
|
||||
if (skip && (n[0] == skip))
|
||||
for (++n; n[0] && (n[0] != skip); ++n)
|
||||
;
|
||||
|
||||
// Seek the next separator occurrence.
|
||||
while (n[0] && (strncmp(n, separator, ls) != 0))
|
||||
++n;
|
||||
|
||||
// Append sub-string.
|
||||
if (skip)
|
||||
container.Add(String(s, n).TrimChar(skip));
|
||||
else
|
||||
container.Add(String(s, n));
|
||||
|
||||
if (!n[0])
|
||||
break;
|
||||
|
||||
n += ls;
|
||||
}
|
||||
return container.GetCount();
|
||||
}
|
||||
/// Get a slice of the string starting at s ending at e.
|
||||
String Slice(uint s, uint e) const;
|
||||
|
||||
bool Compare(const char *, CaseSensitivity = CaseSensitive) const;
|
||||
|
||||
/// Test if the string starts with another string.
|
||||
bool StartsWith(const char *, CaseSensitivity = CaseSensitive) const;
|
||||
/// Test if the string ends with another string.
|
||||
bool EndsWith(const char *, CaseSensitivity = CaseSensitive) const;
|
||||
/// Test if the string contains another string.
|
||||
bool Contains(const char *, CaseSensitivity = CaseSensitive) const;
|
||||
|
||||
String Upper() const;
|
||||
String Lower() const;
|
||||
|
||||
/// Get the n leftmost characters from the string.
|
||||
String Left(uint n) const;
|
||||
/// Get the n rightmost characters from the string.
|
||||
String Right(uint n) const;
|
||||
/// Get 'n' characters starting at p from the string.
|
||||
String Mid(uint p, int n = -1) const;
|
||||
|
||||
/// Return the index of a specific character in string, starting at p.
|
||||
size_t IndexOf(char c, uint p = 0) const;
|
||||
|
||||
/// Return the address of a substring in string, starting at p.
|
||||
char *FindString(const char *c, uint p = 0, CaseSensitivity = CaseSensitive) const;
|
||||
|
||||
bool Replace(const char *what, const char *by, CaseSensitivity cs = CaseSensitive);
|
||||
bool ReplaceAll(const char *what, const char *by, bool match_whole_word = false);
|
||||
bool ReplaceAll(const char **what, const char **by, bool match_whole_word = false);
|
||||
|
||||
static const char *LocatePattern(const char *s, const char *format, const char **e = 0);
|
||||
bool Extract(const char *format, List <String> &arg);
|
||||
|
||||
typedef String RewriteFunc(const char *pattern, List <String> &arg);
|
||||
static String RewritePatternAll(const char *p, const char *pattern, RewriteFunc &rewrite_func);
|
||||
|
||||
/*!
|
||||
@short C string library.
|
||||
@{
|
||||
*/
|
||||
/// Compare two strings, returns -1 if b < a, 0 if a == b, 1 if b > a.
|
||||
static int Compare(const String &a, const String &b);
|
||||
|
||||
/*!
|
||||
@short Returns the address where a given character can be found.
|
||||
|
||||
Returns the address where a given character can be found inside the
|
||||
memory block starting at 'from' and ending at 'to'.
|
||||
*/
|
||||
static char *strfindchar(const char *from, const char c, const char *to = 0);
|
||||
|
||||
/*!
|
||||
@short Compare the shortest C string with the other C string.
|
||||
Returns false if matching. (eg: 'fore' and 'foremost' do match).
|
||||
*/
|
||||
static bool strccmp(const char *, const char *);
|
||||
/// Compute string hash value.
|
||||
static uint strhash(const char *);
|
||||
/// Compute string length.
|
||||
static size_t strlen(const char *);
|
||||
|
||||
/// Remove path.
|
||||
static void rmpath(char *);
|
||||
/// Remove extension.
|
||||
static void rmext(char *);
|
||||
/// Remove path and extension.
|
||||
static void rmpathext(char *);
|
||||
/// Remove filename.
|
||||
static void rmname(char *);
|
||||
|
||||
/// Integer to ASCII.
|
||||
static char *itoa(int);
|
||||
|
||||
/// ASCII to float.
|
||||
static float atof(const char *s, const char *e = 0, bool support_comma = true);
|
||||
/// ASCII to integer.
|
||||
static int atoi(const char *s);
|
||||
/// ASCII header-less, 0x or h prefixed hexadecimal to integer.
|
||||
static int atoh(const char *s);
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/*!
|
||||
@short Reserve space on the string for a number of characters.
|
||||
@note An extra byte will be allocated to store the string terminator.
|
||||
*/
|
||||
bool Allocate(uint size);
|
||||
void Clear();
|
||||
|
||||
String(const char *s) : _p(Alloc::StringBuffer) { Clear(); *this = s; }
|
||||
String(const String &b) : _p(Alloc::StringBuffer) { Clear(); *this = b.c_str(); }
|
||||
String(const char *s, const char *e) : _p(Alloc::StringBuffer) { Clear(); Set(s, e); }
|
||||
String(const char *s, size_t l) : _p(Alloc::StringBuffer) { Clear(); Set(s, s + l); }
|
||||
String() : _p(Alloc::StringBuffer) { Clear(); }
|
||||
~String() { Clear(); }
|
||||
};
|
||||
|
||||
typedef List <String> StringList;
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NSTRING__
|
||||
113
include/platform/ntypes.h
Normal file
113
include/platform/ntypes.h
Normal file
@ -0,0 +1,113 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
#ifndef __NTYPES__
|
||||
#define __NTYPES__
|
||||
|
||||
|
||||
#include "nconfig.h"
|
||||
#if __PLATFORM_ANDROID_NDK__ || __PLATFORM_IOS__ || __PLATFORM_POSIX__
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@short __float32 is expected to be 4 byte float.
|
||||
Platform with no such type will need to port code dependent on this type.
|
||||
*/
|
||||
typedef float __float32;
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef signed char schar;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
namespace GS {
|
||||
namespace Types {
|
||||
|
||||
template <class T> T inline Abs(T v) { return v < 0 ? -v : v; }
|
||||
|
||||
template <class T> T inline Min(T a, T b) { return a < b ? a : b; }
|
||||
template <class T> T inline Max(T a, T b) { return a > b ? a : b; }
|
||||
|
||||
template <class T> T inline Clamp(T v, T min = 0, T max = 1) { return v < min ? min : (v > max ? max : v); }
|
||||
|
||||
template <class T> T inline Wrap(T v, T range_start, T range_end)
|
||||
{
|
||||
const T dt = range_end - range_start + 1;
|
||||
|
||||
while (v < range_start)
|
||||
v += dt;
|
||||
while (v > range_end)
|
||||
v -= dt;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
template <class T> void inline swap(T &a, T&b) { T t = b; b = a; a = t; }
|
||||
|
||||
uint getPOT(uint v);
|
||||
bool isPOT(uint v);
|
||||
|
||||
} // Types
|
||||
} // GS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(__PLATFORM_WINDOWS__)
|
||||
#define GSEXPORT __declspec(dllexport)
|
||||
#define GSRESTRICT __restrict
|
||||
#else
|
||||
#define GSRESTRICT
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helper macros.
|
||||
//------------------------------------------------------------------------------
|
||||
#if __PLATFORM_LOG_SUPPORT__
|
||||
#define __ERR__(err_exp, ret_exp) { (err_exp); return (ret_exp); }
|
||||
#define __ERRRAW__(err_exp) { (err_exp); return; }
|
||||
#else
|
||||
#define __ERR__(err_exp, ret_exp) { return (ret_exp); }
|
||||
#define __ERRRAW__(err_exp) { return; }
|
||||
#endif
|
||||
|
||||
#define nUnused(__P__)
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef forever
|
||||
#define forever for(;;)
|
||||
#endif
|
||||
#define asbool(v) ((v) ? true : false)
|
||||
|
||||
template <class T> inline bool _cached_value_test_and_synch(T &cached, const T &value)
|
||||
{ bool r = cached != value; cached = value; return r; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Disable unwanted warnings.
|
||||
//------------------------------------------------------------------------------
|
||||
#if _MSC_VER
|
||||
// int to float.
|
||||
#pragma warning(disable : 4100)
|
||||
// CRT.
|
||||
#pragma warning(disable : 4996)
|
||||
// empty controlled statement found.
|
||||
#pragma warning(disable : 4390)
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // __NTYPES__
|
||||
128
include/platform/platform.h
Normal file
128
include/platform/platform.h
Normal file
@ -0,0 +1,128 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __PLATFORM__
|
||||
#define __PLATFORM__
|
||||
|
||||
|
||||
#include "memory/nauto_ptr.h"
|
||||
#include "memory/singleton.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "input/input_system.h"
|
||||
#include "async/job.h"
|
||||
#include "signal/signal.h"
|
||||
#include "licensing/licensing.h"
|
||||
#include "analytics/analytics.h"
|
||||
#include "billing/billing.h"
|
||||
#include "time/ntime.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
struct ISharedLib;
|
||||
|
||||
/*!
|
||||
@short Platform interface.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
class Platform : public Singleton <Platform>
|
||||
{
|
||||
bool initialized;
|
||||
|
||||
public:
|
||||
|
||||
/// Initialize platform.
|
||||
virtual void Initialize();
|
||||
|
||||
AutoPtr <ASync::JobManager> job_manager;
|
||||
AutoPtr <IO::Filesystem> io;
|
||||
AutoPtr <IBilling> billing;
|
||||
AutoPtr <IAnalytics> analytics;
|
||||
AutoPtr <ILicensing> licensing;
|
||||
AutoPtr <Input::System> input_system;
|
||||
|
||||
// Platform signals.
|
||||
struct Signals
|
||||
{
|
||||
Signal <void> renderer_output_closed;
|
||||
};
|
||||
|
||||
Signals signal;
|
||||
|
||||
/// Return the platform name.
|
||||
virtual String GetName() const = 0;
|
||||
/// Return the device name the platform is running on.
|
||||
virtual String GetDeviceName() const = 0;
|
||||
|
||||
/// Get the platform locale as an ISO3166 code.
|
||||
virtual String GetLocale() = 0;
|
||||
|
||||
/// Return the number of logical thread available.
|
||||
virtual int GetSystemThreadCount() { return 1; }
|
||||
/// Return the number of physical processor core available.
|
||||
virtual int GetSystemCoreCount() { return 1; }
|
||||
|
||||
/// Open a given URL using the platform integrated browser.
|
||||
virtual bool OpenURL(const char *) { return false; }
|
||||
/// Open the application page.
|
||||
virtual bool OpenAppPage() { return false; }
|
||||
|
||||
/// Send to background.
|
||||
virtual bool SendToBackground(bool kill = false) { return false; }
|
||||
|
||||
/// Return the current user directory.
|
||||
virtual bool GetUserDir(String &, const char *user = 0) { return false; }
|
||||
|
||||
/// Output a program trace to the platform log.
|
||||
virtual void Trace(const char *trace, const char *source, int line);
|
||||
|
||||
/*!
|
||||
@name Application
|
||||
@{
|
||||
*/
|
||||
static String app_dir;
|
||||
|
||||
virtual String GetAppPluginPath(const char *) const;
|
||||
/// @}
|
||||
|
||||
/*!
|
||||
@name Timer subsystem.
|
||||
@{
|
||||
*/
|
||||
/// Get the platform clock.
|
||||
virtual Time GetTime() = 0;
|
||||
|
||||
/// Return the system clock frequency.
|
||||
virtual int GetClockFrequency() = 0;
|
||||
/// Return the current clock.
|
||||
virtual int GetClock() = 0;
|
||||
/// Sleep platform for 'n' milliseconds.
|
||||
virtual void Sleep(uint ms) = 0;
|
||||
|
||||
int GetStartClock() const;
|
||||
Time GetStartTime() const;
|
||||
|
||||
/// System clock unit macros.
|
||||
int GetSecond(int t) { return t * GetClockFrequency(); }
|
||||
int GetMinute(int t) { return t * 60 * GetClockFrequency(); }
|
||||
/// @}
|
||||
|
||||
/// Load a shared library.
|
||||
virtual ISharedLib *LoadSharedLibrary(const char *) { return 0; }
|
||||
|
||||
Platform();
|
||||
virtual ~Platform() {}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define __NTRACE(T) { GS::Platform::Get().Trace(T, __FILE__, __LINE__); }
|
||||
#else
|
||||
#define __NTRACE(T) ;
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __PLATFORM__
|
||||
40
include/platform/platform_config.h
Normal file
40
include/platform/platform_config.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __KERNEL_CONFIG__
|
||||
#define __KERNEL_CONFIG__
|
||||
|
||||
|
||||
#include "assert/nassert.h"
|
||||
|
||||
|
||||
#if __PLATFORM_WINDOWS__
|
||||
|
||||
#define strupr _strupr
|
||||
#define strlwr _strlwr
|
||||
|
||||
#elif __PLATFORM_POSIX__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <alloca.h>
|
||||
|
||||
#define _snprintf snprintf
|
||||
|
||||
#elif __PLATFORM_NINTENDO_WII__
|
||||
|
||||
#include <revolution.h>
|
||||
|
||||
using namespace std;
|
||||
#define _snprintf snprintf
|
||||
|
||||
#elif SN_TARGET_PS3
|
||||
|
||||
#define _snprintf snprintf
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __KERNEL_CONFIG__
|
||||
55
include/platform/rand/rand.h
Normal file
55
include/platform/rand/rand.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NRAND__
|
||||
#define __NRAND__
|
||||
|
||||
|
||||
#include "ntypes.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Random {
|
||||
|
||||
#ifndef RAND_MAX
|
||||
#define RAND_MAX 0x7fff
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@short A random number generator class.
|
||||
|
||||
@note The maximum precision of this generator is fixed to 16bit integer.
|
||||
This means that you cannot get, even with floats, more than 65536
|
||||
different values. But this generator has, of course, no query
|
||||
limit.
|
||||
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
/// Set the starting seed of the random number generator.
|
||||
void Seed(uint s);
|
||||
/// Return an integer random number in the range [0;r] (default [0;RAND_MAX].
|
||||
uint Rand(uint r = RAND_MAX);
|
||||
/// Return a float random value in the range [0;r] (default [0;1]).
|
||||
float FRand(float r = 1.0f);
|
||||
/// Return a float random value un the range [lo, hi] (default [-1, 1]).
|
||||
float FRRand(float lo = -1, float hi = 1);
|
||||
/*!
|
||||
@short Pseudo-unique random number generator.
|
||||
|
||||
A random number generator that tries to feed a different number
|
||||
than what was returned at the previous call.
|
||||
This class is a wrapper for Rand().
|
||||
|
||||
@note The number 'might' still be the same.
|
||||
*/
|
||||
uint CRand(uint r = RAND_MAX);
|
||||
|
||||
} // Random
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NRAND__
|
||||
|
||||
44
include/platform/reflection/c_refl.h
Normal file
44
include/platform/reflection/c_refl.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2011 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NREFL_OBJECT__
|
||||
#define __NREFL_OBJECT__
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include "reflection/nenum_string.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Reflection {
|
||||
|
||||
struct Property
|
||||
{
|
||||
enum PropType
|
||||
{
|
||||
InvalidProp,
|
||||
BoolProp,
|
||||
CharProp,
|
||||
ShortProp,
|
||||
IntProp,
|
||||
FloatProp,
|
||||
StringProp,
|
||||
EnumProp
|
||||
};
|
||||
|
||||
PropType type;
|
||||
|
||||
const char *name;
|
||||
size_t offset_of;
|
||||
|
||||
Enum::Dict *enum_dict;
|
||||
};
|
||||
|
||||
} // Reflection
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NREFL_OBJECT__
|
||||
30
include/platform/reflection/nenum_string.h
Normal file
30
include/platform/reflection/nenum_string.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NENUM_STRING__
|
||||
#define __NENUM_STRING__
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Reflection {
|
||||
|
||||
struct Enum
|
||||
{
|
||||
struct Dict
|
||||
{
|
||||
int enum_v;
|
||||
const char *string_v;
|
||||
};
|
||||
|
||||
static const char *toString(int, Dict *);
|
||||
static int fromString(const char *, Dict *);
|
||||
};
|
||||
|
||||
} // Reflection
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NENUM_STRING__
|
||||
32
include/platform/shared/shared_library.h
Normal file
32
include/platform/shared/shared_library.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NSHAREDLIB__
|
||||
#define __NSHAREDLIB__
|
||||
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short Shared library interface.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
struct ISharedLib
|
||||
{
|
||||
/// Lookup for a function exported by the shared library.
|
||||
virtual void *GetFunctionPointer(const char *s) = 0;
|
||||
|
||||
virtual ~ISharedLib() {}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NSHAREDLIB__
|
||||
175
include/platform/signal/signal.h
Normal file
175
include/platform/signal/signal.h
Normal file
@ -0,0 +1,175 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __SIGNAL__
|
||||
#define __SIGNAL__
|
||||
|
||||
|
||||
#include "container/nlist.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
//
|
||||
template <typename T> class Signal
|
||||
{
|
||||
/// Base signal listener.
|
||||
struct IListener
|
||||
{
|
||||
virtual void Call(T) = 0;
|
||||
|
||||
virtual bool BelongsToInstance(void *) const = 0;
|
||||
virtual bool IsFunction(void (*)(T)) const = 0;
|
||||
|
||||
virtual ~IListener() {}
|
||||
};
|
||||
|
||||
AutoList <IListener *> listeners;
|
||||
|
||||
/// Pointer to member listener.
|
||||
template <class O, typename T1> struct InstanceListener : public IListener
|
||||
{
|
||||
O *i;
|
||||
void (O::*f)(T1);
|
||||
|
||||
void Call(T1 t) { (i->*f)(t); }
|
||||
|
||||
bool BelongsToInstance(void *p) const { return asbool(p == (void *)i); }
|
||||
bool IsFunction(void (*)(T1)) const { return false; }
|
||||
|
||||
InstanceListener(O *_i, void (O::*_f)(T1)) : i(_i), f(_f) {}
|
||||
};
|
||||
|
||||
/// Global/static function listener.
|
||||
template <typename T1> struct FunctionListener : public IListener
|
||||
{
|
||||
void (*f)(T1);
|
||||
|
||||
void Call(T1 t) { (*f)(t); }
|
||||
|
||||
bool BelongsToInstance(void *) const { return false; }
|
||||
bool IsFunction(void (*_f)(T1)) const { return f == _f; }
|
||||
|
||||
FunctionListener(void (*_f)(T1)) : f(_f) {}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/// Return the number of listener on this signal.
|
||||
uint GetListenerCount() const { return listeners.GetCount(); }
|
||||
|
||||
/// Subscribe an instance member function to call when the event is triggered.
|
||||
template <class O> void Connect(O *i, void (O::*f)(T))
|
||||
{ listeners.Add(new InstanceListener <O, T> (i, f)); }
|
||||
/// Remove the subscription of all handlers associated with a specific class instance.
|
||||
template <class O> void Disconnect(O *i)
|
||||
{
|
||||
ListForeachPtr(IListener *, l, this->listeners)
|
||||
if (l->BelongsToInstance((void *)i))
|
||||
listeners.Remove(l);
|
||||
}
|
||||
|
||||
/// Subscribe a function to call when the event is triggered.
|
||||
void Connect(void (*f)(T))
|
||||
{ listeners.Add(new FunctionListener <T> (f)); }
|
||||
/// Remove a function subscription.
|
||||
void Disconnect(void (*f)(T))
|
||||
{
|
||||
ListForeachPtr(IListener *, l, this->listeners)
|
||||
if (l->IsFunction(f))
|
||||
listeners.Remove(l);
|
||||
}
|
||||
|
||||
/// Emit the signal, notifies all listeners.
|
||||
void Emit(T t) const
|
||||
{
|
||||
ListForeachPtr(IListener *, l, listeners)
|
||||
l->Call(t);
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization for void type. Note: I gave up on factoring code => compiler vendor/extension hell.
|
||||
template <> class Signal <void>
|
||||
{
|
||||
/// Base signal listener.
|
||||
struct IListener
|
||||
{
|
||||
virtual void Call() = 0;
|
||||
|
||||
virtual bool BelongsToInstance(void *) const = 0;
|
||||
virtual bool IsFunction(void (*)()) const = 0;
|
||||
|
||||
virtual ~IListener() {}
|
||||
};
|
||||
|
||||
AutoList <IListener *> listeners;
|
||||
|
||||
/// Pointer to member listener.
|
||||
template <class O> struct InstanceListener : public IListener
|
||||
{
|
||||
O *i;
|
||||
void (O::*f)();
|
||||
|
||||
void Call() { (i->*f)(); }
|
||||
|
||||
bool BelongsToInstance(void *p) const { return asbool(p == (void *)i); }
|
||||
bool IsFunction(void (*)()) const { return false; }
|
||||
|
||||
InstanceListener(O *_i, void (O::*_f)()) : i(_i), f(_f) {}
|
||||
};
|
||||
|
||||
/// Global/static function listener.
|
||||
struct FunctionListener : public IListener
|
||||
{
|
||||
void (*f)();
|
||||
|
||||
void Call() { (*f)(); }
|
||||
|
||||
bool BelongsToInstance(void *) const { return false; }
|
||||
bool IsFunction(void (*_f)()) const { return f == _f; }
|
||||
|
||||
FunctionListener(void (*_f)()) : f(_f) {}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/// Return the number of listener on this signal.
|
||||
uint GetListenerCount() const { return listeners.GetCount(); }
|
||||
|
||||
/// Subscribe an instance member function to call when the event is triggered.
|
||||
template <class O> void Connect(O *i, void (O::*f)())
|
||||
{ listeners.Add(new InstanceListener <O> (i, f)); }
|
||||
/// Remove the subscription of all handlers associated with a specific class instance.
|
||||
template <class O> void Disconnect(O *i)
|
||||
{
|
||||
ListForeachPtr(IListener *, l, listeners)
|
||||
if (l->BelongsToInstance((void *)i))
|
||||
listeners.Remove(l);
|
||||
}
|
||||
|
||||
/// Subscribe a function to call when the event is triggered.
|
||||
void Connect(void (*f)())
|
||||
{ listeners.Add(new FunctionListener(f)); }
|
||||
/// Remove a function subscription.
|
||||
void Disconnect(void (*f)())
|
||||
{
|
||||
ListForeachPtr(IListener *, l, listeners)
|
||||
if (l->IsFunction(f))
|
||||
listeners.Remove(l);
|
||||
}
|
||||
|
||||
/// Emit the signal, notifies all listeners.
|
||||
void Emit() const
|
||||
{
|
||||
ListForeachPtr(IListener *, l, listeners)
|
||||
l->Call();
|
||||
}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __SIGNAL__
|
||||
38
include/platform/social/social.h
Normal file
38
include/platform/social/social.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NSOCIAL__
|
||||
#define __NSOCIAL__
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Social {
|
||||
|
||||
struct Account
|
||||
{
|
||||
String login;
|
||||
|
||||
String first, middle, last;
|
||||
String email;
|
||||
|
||||
String address, phone;
|
||||
};
|
||||
|
||||
/*!
|
||||
@short Social system abstract interface.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
struct ISocial
|
||||
{
|
||||
virtual bool Login(const char *login, const char *key) = 0;
|
||||
virtual bool Logout() = 0;
|
||||
};
|
||||
|
||||
} // Social
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NSOCIAL__
|
||||
49
include/platform/thread/atomic_value.h
Normal file
49
include/platform/thread/atomic_value.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __ATOMIC_VALUE__
|
||||
#define __ATOMIC_VALUE__
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
/*!
|
||||
@short 32bit atomic value.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
class Atomic32
|
||||
{
|
||||
void *v;
|
||||
|
||||
public:
|
||||
|
||||
/// Perform atomic increment, return the new value.
|
||||
int Inc();
|
||||
/// Perform atomic decrement, return the new value.
|
||||
int Dec();
|
||||
|
||||
/// Return the current value.
|
||||
int Get() const;
|
||||
/// Set new value, return the initial value.
|
||||
int Set(int);
|
||||
|
||||
/*!
|
||||
@short Perform an atomic compare and swap operation.
|
||||
Compare the current value with the comparand, if they match set the
|
||||
new value. Return the initial value.
|
||||
*/
|
||||
int Cas(int comparand, int value);
|
||||
|
||||
explicit Atomic32(int value = 0);
|
||||
~Atomic32();
|
||||
};
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __ATOMIC_VALUE__
|
||||
90
include/platform/thread/mutex.h
Normal file
90
include/platform/thread/mutex.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NMUTEX__
|
||||
#define __NMUTEX__
|
||||
|
||||
|
||||
#if __PLATFORM_POSIX__
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#elif __PLATFORM_NINTENDO_WII__
|
||||
#include <revolution.h>
|
||||
#endif
|
||||
#include "ntypes.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
/// Portable mutex class.
|
||||
class Mutex
|
||||
{
|
||||
protected:
|
||||
|
||||
#if __PLATFORM_POSIX__
|
||||
pthread_mutex_t mutex;
|
||||
#elif __PLATFORM_WINDOWS__
|
||||
void *mutex;
|
||||
#elif __PLATFORM_NINTENDO_WII__
|
||||
OSMutex mutex;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
|
||||
Mutex();
|
||||
~Mutex();
|
||||
};
|
||||
|
||||
/// Mutex helper class.
|
||||
class MutexLock
|
||||
{
|
||||
protected:
|
||||
|
||||
Mutex *mutex;
|
||||
|
||||
public:
|
||||
|
||||
bool HasLock() const
|
||||
{ return asbool(mutex); }
|
||||
|
||||
void Lock(Mutex *m, bool try_only)
|
||||
{
|
||||
Unlock();
|
||||
|
||||
if (try_only)
|
||||
{
|
||||
if (m && m->TryLock())
|
||||
mutex = m;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m)
|
||||
(mutex = m)->Lock();
|
||||
}
|
||||
}
|
||||
void Unlock()
|
||||
{
|
||||
if (mutex)
|
||||
mutex->Unlock();
|
||||
mutex = 0;
|
||||
}
|
||||
|
||||
MutexLock(Mutex *m, bool try_only = false) : mutex(0)
|
||||
{ Lock(m, try_only); }
|
||||
~MutexLock()
|
||||
{ Unlock(); }
|
||||
};
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NMUTEX__
|
||||
55
include/platform/thread/thread.h
Normal file
55
include/platform/thread/thread.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NTHREAD__
|
||||
#define __NTHREAD__
|
||||
|
||||
|
||||
#include "thread/atomic_value.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
/*
|
||||
@short Thread abstraction class.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
struct Thread
|
||||
{
|
||||
void *handle;
|
||||
|
||||
virtual bool Start();
|
||||
|
||||
void Kill();
|
||||
void Join();
|
||||
|
||||
static void SetName(const char *);
|
||||
// Yield execution to the next running system thread.
|
||||
static void Switch();
|
||||
|
||||
/*
|
||||
@short Set thread priority.
|
||||
|
||||
Set the thread priority from 0 to 31.
|
||||
0 is the highest priority, 31 is the lowest.
|
||||
|
||||
@return False is the required priority was invalid.
|
||||
*/
|
||||
bool SetPriority(int priority = 16);
|
||||
|
||||
/// Main thread execution function.
|
||||
virtual void Execute() = 0;
|
||||
|
||||
Thread();
|
||||
virtual ~Thread();
|
||||
};
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NTHREAD__
|
||||
135
include/platform/thread/thread_controller.h
Normal file
135
include/platform/thread/thread_controller.h
Normal file
@ -0,0 +1,135 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __THREAD_CONTROLLER__
|
||||
#define __THREAD_CONTROLLER__
|
||||
|
||||
|
||||
#include "thread/atomic_value.h"
|
||||
#include "thread/thread_event.h"
|
||||
#include "thread/future.h"
|
||||
#include "thread/thread.h"
|
||||
#include "thread/mutex.h"
|
||||
#include "container/nlist.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <typename Target> struct DefaultControllerPolicy
|
||||
{
|
||||
static const bool use_event = true; // use thread event to sleep the worker thread
|
||||
static const bool own_target = false; // the controller owns the target object and is responsible for deleting it
|
||||
|
||||
static void Update(Target *) {}
|
||||
};
|
||||
|
||||
template <typename Target, class Policy = DefaultControllerPolicy <Target> > class Controller
|
||||
{
|
||||
public:
|
||||
|
||||
struct Command
|
||||
{
|
||||
Atomic32 dispose;
|
||||
virtual void Execute(Target *target) = 0;
|
||||
|
||||
Command() : dispose(1) {}
|
||||
virtual ~Command() {}
|
||||
};
|
||||
|
||||
template <class Result> struct CommandWithResult : public Command
|
||||
{
|
||||
Future <Result> future_result;
|
||||
CommandWithResult() { this->dispose.Set(0); }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
struct WorkerThread : public Thread
|
||||
{
|
||||
Target *target;
|
||||
|
||||
Atomic32 running;
|
||||
|
||||
Mutex command_mutex;
|
||||
Event command_event;
|
||||
|
||||
AutoList <Command *> command_queue;
|
||||
|
||||
void Execute()
|
||||
{
|
||||
forever
|
||||
{
|
||||
Policy::Update(target);
|
||||
{
|
||||
MutexLock lock(&command_mutex);
|
||||
while (command_queue.GetCount() > 0)
|
||||
{
|
||||
command_queue[0]->Execute(target);
|
||||
while (command_queue[0]->dispose.Get() != 1)
|
||||
; // spin lock on command dispose flag
|
||||
command_queue.RemoveAt(0);
|
||||
}
|
||||
if (running.Get() != 1)
|
||||
break;
|
||||
}
|
||||
if (Policy::use_event)
|
||||
command_event.Wait();
|
||||
}
|
||||
running.Set(0);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
running.Set(2);
|
||||
if (Policy::use_event)
|
||||
command_event.Trigger();
|
||||
while (running.Get() != 0); // spinlock
|
||||
}
|
||||
|
||||
WorkerThread(Target *t) : target(t), running(1) {}
|
||||
~WorkerThread()
|
||||
{
|
||||
if (Policy::own_target)
|
||||
delete target;
|
||||
}
|
||||
};
|
||||
|
||||
WorkerThread worker;
|
||||
|
||||
public:
|
||||
|
||||
void QueueCommand(Command *c)
|
||||
{
|
||||
{
|
||||
MutexLock lock(&worker.command_mutex);
|
||||
worker.command_queue.Append(c);
|
||||
}
|
||||
worker.command_event.Trigger();
|
||||
}
|
||||
template <class Result> Result QueueCommand(CommandWithResult <Result> *c)
|
||||
{
|
||||
QueueCommand((Command *)c);
|
||||
|
||||
Result result = c->future_result.Get(); // wait for command result
|
||||
c->dispose.Set(1); // flag command disposal
|
||||
return result; // return result
|
||||
}
|
||||
|
||||
bool Start()
|
||||
{ return worker.Start(); }
|
||||
void Stop()
|
||||
{ worker.Stop(); }
|
||||
|
||||
Controller(Target *t) : worker(t) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __THREAD_CONTROLLER__
|
||||
38
include/platform/thread/thread_event.h
Normal file
38
include/platform/thread/thread_event.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NTHREAD_EVENT__
|
||||
#define __NTHREAD_EVENT__
|
||||
|
||||
|
||||
#include "time/ntime.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
/*!
|
||||
@short Multi-threaded event.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
struct Event
|
||||
{
|
||||
void *event;
|
||||
|
||||
/// Thread entering this function will suspend until this event is triggered.
|
||||
void Wait(Time * = 0);
|
||||
/// Trigger event.
|
||||
void Trigger();
|
||||
|
||||
Event();
|
||||
~Event();
|
||||
};
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NTHREAD_EVENT__
|
||||
81
include/platform/time/ntime.h
Normal file
81
include/platform/time/ntime.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NTIME__
|
||||
#define __NTIME__
|
||||
|
||||
|
||||
#include "nstring/nstring.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
/*!
|
||||
@short Time class.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
class Time
|
||||
{
|
||||
int sec, nsec; // second, nanosecond (10^9 -> 1 billionth second) (63+ years loop)
|
||||
|
||||
public:
|
||||
|
||||
static Time Inf;
|
||||
|
||||
void operator += (const Time &);
|
||||
void operator -= (const Time &);
|
||||
Time operator + (const Time &) const;
|
||||
Time operator - (const Time &) const;
|
||||
|
||||
template <class T> void operator *= (T k) { sec = int(T(sec) * k); nsec = int(T(nsec) * k); Normalize(); }
|
||||
template <class T> void operator /= (T k) { sec = int(T(sec) / k); nsec = int(T(nsec) / k); Normalize(); }
|
||||
template <class T> Time operator * (T k) const { return Time(int(T(sec) * k), int(T(nsec) * k)); }
|
||||
template <class T> Time operator / (T k) const { return Time(int(T(sec) / k), int(T(nsec) / k)); }
|
||||
|
||||
bool operator > (const Time &) const;
|
||||
bool operator < (const Time &) const;
|
||||
bool operator >= (const Time &) const;
|
||||
bool operator <= (const Time &) const;
|
||||
bool operator == (const Time &) const;
|
||||
bool operator != (const Time &) const;
|
||||
|
||||
Time Abs() const;
|
||||
|
||||
int getSec() const { return sec; }
|
||||
int getNanoSec() const { return nsec; }
|
||||
|
||||
float toDay() const;
|
||||
float toHour() const;
|
||||
float toMin() const;
|
||||
float toSec() const;
|
||||
float toMs() const;
|
||||
float toNs() const;
|
||||
|
||||
String toString() const;
|
||||
|
||||
void setSec(float);
|
||||
void setSec(int);
|
||||
void setMs(int);
|
||||
void setNs(int);
|
||||
|
||||
static Time fromSec(float);
|
||||
static Time fromSec(int);
|
||||
static Time fromMs(int);
|
||||
static Time fromNs(int);
|
||||
|
||||
void Normalize();
|
||||
Time Normalized() const;
|
||||
|
||||
Time(const int sec, const int nsec);
|
||||
|
||||
explicit Time(const int sec = 0);
|
||||
explicit Time(const float sec);
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NTIME__
|
||||
22
include/platform/time/ntime_range.h
Normal file
22
include/platform/time/ntime_range.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __TIMERANGE__
|
||||
#define __TIMERANGE__
|
||||
|
||||
|
||||
#include "math/nrange.h"
|
||||
#include "time/ntime.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
typedef Range <Time> TimeRange;
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __TIMERANGE__
|
||||
49
include/platform/unit/nunit.h
Normal file
49
include/platform/unit/nunit.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NUNIT__
|
||||
#define __NUNIT__
|
||||
|
||||
|
||||
#include "ntypes.h"
|
||||
|
||||
|
||||
/*
|
||||
@short Units namespace.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
namespace GS {
|
||||
namespace Units {
|
||||
|
||||
template <typename T> T Deg(T v) { return v / T(180) * T(3.1415926535); }
|
||||
template <typename T> T Rad(T v) { return v; }
|
||||
|
||||
template <typename T> T DegreeToRadian(T v) { return v / T(180) * T(3.1415926535); }
|
||||
template <typename T> T RadianToDegree(T v) { return v / T(3.1415926535) * T(180); }
|
||||
|
||||
template <typename T> T Sec(T v) { return v; }
|
||||
template <typename T> T Csec(T v) { return v * T(0.01); }
|
||||
template <typename T> T Ms(T v) { return v * T(0.001); }
|
||||
|
||||
template <typename T> T Tick(T v) { return v * T(0.001); }
|
||||
|
||||
template <typename T> T Kg(T v) { return v; }
|
||||
template <typename T> T G(T v) { return v * T(0.001); }
|
||||
|
||||
template <typename T> T Km(T v) { return v * T(1000); }
|
||||
template <typename T> T Mtr(T v) { return v; }
|
||||
template <typename T> T Cm(T v) { return v * T(0.01); }
|
||||
template <typename T> T Mm(T v) { return v * T(0.001); }
|
||||
template <typename T> T Inch(T v) { return v * T(0.0254); }
|
||||
|
||||
size_t KB(const size_t v);
|
||||
size_t MB(const size_t v);
|
||||
|
||||
} // Units
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NUNIT__
|
||||
79
include/platform/video/video_mode.h
Normal file
79
include/platform/video/video_mode.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __NVIDEOMODE__
|
||||
#define __NVIDEOMODE__
|
||||
|
||||
|
||||
#include "ntypes.h"
|
||||
|
||||
|
||||
/*!
|
||||
@short Video mode database.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
namespace nVideoMode
|
||||
{
|
||||
struct Mode
|
||||
{
|
||||
const char *name;
|
||||
|
||||
uint width, height;
|
||||
uchar bpp;
|
||||
|
||||
bool pc_mode;
|
||||
};
|
||||
|
||||
enum AspectRatio
|
||||
{
|
||||
AR_4_3,
|
||||
AR_16_9,
|
||||
AR_16_10,
|
||||
|
||||
AR_Unknown
|
||||
};
|
||||
|
||||
enum Name
|
||||
{
|
||||
CGA, // 320x200
|
||||
QVGA, // 320x240
|
||||
WQVGA, // 480x272
|
||||
VGA, // 640x480
|
||||
SVGA, // 800x600
|
||||
|
||||
XGA, // 1024x768
|
||||
XGAPlus, // 1152x864
|
||||
|
||||
HD, // 1366x768
|
||||
WXGA_922K, // 1280x720
|
||||
WXGA_1024K, // 1280x800
|
||||
HDPlus, // 1600x900
|
||||
SXGA, // 1280x1024
|
||||
WXGAPlus, // 1440x900
|
||||
|
||||
UXGA, // 1600x1200
|
||||
WSXGAPlus, // 1680x1050
|
||||
FullHD, // 1920x1080
|
||||
WUXGA, // 1920x1200
|
||||
|
||||
QXGA, // 2048x1536
|
||||
QWXGA, // 2048x1152
|
||||
WQHD, // 2560x1440
|
||||
WQXGA, // 2560x1600
|
||||
|
||||
NameLast
|
||||
};
|
||||
|
||||
extern Mode mode_desc[NameLast];
|
||||
|
||||
/// Get video mode aspect ratio.
|
||||
AspectRatio GetModeAspectRatio(const Mode &);
|
||||
/// Get video mode from resolution.
|
||||
Mode *GetMode(uint w, uint h);
|
||||
};
|
||||
|
||||
|
||||
#endif // __NVIDEOMODE__
|
||||
Reference in New Issue
Block a user