commit x64 compilation from lulu cause the other branch dont seems to compile properly at home

This commit is contained in:
2026-07-17 16:08:20 +02:00
parent c0f3eeb00d
commit 0efa4ee6f7
625 changed files with 117283 additions and 4426 deletions

View File

@ -0,0 +1,281 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <stdlib.h>
#include "alloc/ialloc.h"
#include "thread/mutex.h"
#include "log/log.h"
using namespace GS::Alloc;
//------------------------------------------------------------------------------
void *DefaultAllocator::Alloc(size_t size, System sys)
{ __NSTAT_WRAPALLOC(malloc(size), sys) }
void DefaultAllocator::Delete(void *addr, System sys)
{ __NSTAT_WRAPDELETE(free(addr), sys) }
//------------------------------------------------------------------------------
#if __ENABLE_ALLOCATION_STAT__
namespace GS {
namespace Alloc {
Stat system_stat[SystemCount];
SystemDesc system_desc[SystemCount] =
{
{ "General", "System" },
{ "Container", "List Item" },
{ "String", "String Buffer" },
{ "I/O", "Filesystem" },
{ "I/O", "Metatag" },
{ "Animation", "Curve" },
{ "Animation", "Motion" },
{ "Animation", "Animation Source" },
{ "Maths", "Vector" },
{ "Maths", "Matrix" },
{ "Physics", "Physics" },
{ "Scene 3D", "Item" },
{ "Resource", "Geometry" },
{ "Resource", "Material" },
{ "Resource", "Texture" },
{ "Resource", "Picture" },
{ "Mixer", "System" },
{ "Resource", "Sound" },
{ "Renderer", "System" },
{ "Renderer", "Render Job" },
{ "Renderer", "Terrain" },
{ "Renderer", "VBO" },
{ "Global", "Other" }
};
//------------------------------------------------------------------------------
size_t GetAdjustedAllocationSize(size_t size)
{ return size + sizeof(Header); }
void *SetupAllocationStat(void *addr, size_t size)
{
Header *h = (Header *)addr;
h->size = size;
return (void *)(h + 1);
}
void *GetAllocationStat(void *addr, Header *&h)
{
h = ((Header *)addr) - 1;
return (void *)h;
}
//------------------------------------------------------------------------------
static Mutex stat_mutex;
//------------------------------------------------------------------------------
void UpdateStatAlloc(size_t size, System system)
{
MutexLock lock(&stat_mutex);
++system_stat[system].alloc_count;
++system_stat[system].alive_count;
if (system_stat[system].alive_count > system_stat[system].alive_count_peak)
system_stat[system].alive_count_peak = system_stat[system].alive_count;
system_stat[system].size += size;
if (system_stat[system].size > system_stat[system].size_peak)
system_stat[system].size_peak = system_stat[system].size;
}
void UpdateStatDelete(size_t size, System system)
{
MutexLock lock(&stat_mutex);
system_stat[system].alive_count--;
system_stat[system].size -= size;
}
//------------------------------------------------------------------------------
} // Alloc
} // GS
#endif // __ENABLE_ALLOCATION_STAT__
#include "container/narray.h"
//------------------------------------------------------------------------------
class SmallBlockAllocatorPool
{
void *root;
char *pool, *pool_end;
public:
bool Owns(void *p) const
{ return (p >= (void *)pool) && (p < (void *)pool_end); }
void *Alloc()
{
if (!root)
return NULL;
void *p = root;
root = *((void **)root);
return p;
}
void Free(void *p)
{
*((void **)p) = root;
root = p;
}
bool Init(size_t block_size, uint block_count)
{
Uninit();
pool = (char *)malloc(block_size * block_count);
if (pool == NULL)
return false;
pool_end = pool + block_size * block_count;
for (uint n = 0; n < (block_count - 1); ++n)
*((void **)(pool + n * block_size)) = (void *)(pool + (n + 1) * block_size);
*((void **)(pool + (block_count - 1) * block_size)) = NULL;
root = (void *)pool;
return true;
}
void Uninit()
{
free(pool);
root = NULL;
}
SmallBlockAllocatorPool()
{
pool = pool_end = NULL;
root = NULL;
}
~SmallBlockAllocatorPool()
{
Uninit();
}
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
class MixedBlockAllocator
{
SmallBlockAllocatorPool allocator[4];
public:
void *operator new (size_t size)
{ return malloc(size); }
void operator delete(void *addr)
{ free(addr); }
void *Alloc(size_t size)
{
void *p = NULL;
if (size <= 8)
p = allocator[0].Alloc();
else if (size <= 16)
p = allocator[1].Alloc();
else if (size <= 32)
p = allocator[2].Alloc();
else if (size <= 64)
p = allocator[3].Alloc();
return p ? p : malloc(size);
}
void Free(void *p)
{
if (allocator[0].Owns(p))
allocator[0].Free(p);
else if (allocator[1].Owns(p))
allocator[1].Free(p);
else if (allocator[2].Owns(p))
allocator[2].Free(p);
else if (allocator[3].Owns(p))
allocator[3].Free(p);
else
free(p);
}
bool Init()
{
allocator[0].Init(8, 16000); // 128k
allocator[1].Init(16, 16000); // 256k
allocator[2].Init(32, 8000); // 256k
allocator[3].Init(64, 8000); // 512k
return true;
}
};
//------------------------------------------------------------------------------
#if __ENABLE_GLOBAL_SBA__
MixedBlockAllocator *mixed_allocator = NULL;
MixedBlockAllocator *GetMixedAllocator()
{
if (!mixed_allocator)
{
mixed_allocator = new MixedBlockAllocator;
mixed_allocator->Init();
}
return mixed_allocator;
}
//------------------------------------------------------------------------------
void *operator new(size_t size)
{
__NSTAT_WRAPALLOC(GetMixedAllocator()->Alloc(size), Alloc::Global)
}
void operator delete(void *addr)
{
__NSTAT_WRAPDELETE(GetMixedAllocator()->Free(addr), Alloc::Global)
}
void *operator new [] (size_t size)
{
__NSTAT_WRAPALLOC(GetMixedAllocator()->Alloc(size), Alloc::Global)
}
void operator delete [] (void *addr)
{
__NSTAT_WRAPDELETE(GetMixedAllocator()->Free(addr), Alloc::Global)
}
//------------------------------------------------------------------------------
#endif
//------------------------------------------------------------------------------
void *_align_alloc(size_t size, size_t align)
{
#ifdef _WIN32
return _aligned_malloc(size, align);
#else
return malloc(size);
#endif
}
void _align_free(void *p)
{
#ifdef _WIN32
_aligned_free(p);
#else
free(p);
#endif
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,28 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#if __PLATFORM_WINDOWS__
#define WINDOWS_LEAN_AND_MEAN
#include <Windows.h>
#endif
#include "assert/nassert.h"
#include "nstring/nstring.h"
//------------------------------------------------------------------------------
void GS::Assert::Trigger(const char *source, int line, const char *condition, const char *message)
{
String description = String::Format("%s\n\nFile: %s\nLine %d\n", condition, source, line);
if (message)
description += String("\nDetail: ") + message;
#if __PLATFORM_WINDOWS__
MessageBoxA(NULL, description.c_str(), "Assertion failed!", MB_ICONSTOP);
DebugBreak();
#endif
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,215 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "async/job.h"
#include "memory/memory.h"
#include "log/log.h"
using namespace GS::ASync;
using namespace GS::Threading;
#ifndef _DEBUG
#define __ENABLE_ITT_API__ 0
#endif
#if __ENABLE_ITT_API__
#include "ittnotify.h"
static __itt_domain *domain = NULL;
#endif
//------------------------------------------------------------------------------
void JobWorkerThread::Execute()
{
running.Set(1);
Thread::SetName(GS::String::Format("Job Worker Thread %d", worker_id));
while (running.Get() == 1)
{
// Execute as much jobs as possible until starvation.
while (manager.ExecutePendingJob(worker_id));
// Wait for notification on the queue event.
manager.job_queued_event.Wait();
}
running.Set(0);
}
void JobWorkerThread::Stop()
{ running.Set(2); }
bool JobWorkerThread::IsRunning() const
{ return running.Get() > 0; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool JobManager::CreateJobThreadPool(uint count)
{
FreeJobThreadPool();
if (!pool.Allocate(count))
return false;
for (uint n = 0; n < count; ++n)
if ((pool[n] = new JobWorkerThread(*this, n + 1)) == NULL)
__ERR__(__LOG_E__ << "Failed to allocate a job worker thread.\n", false)
// Create workers.
for (uint n = 0; n < count; ++n)
if (!pool[n]->Start())
__LOG_W__ << "Failed to create worker thread " << pool[n]->GetWorkerId() << ".\n";
return true;
}
void JobManager::FreeJobThreadPool()
{
// Set thread exit flag.
for (uint n = 0; n < pool.GetCount(); ++n)
pool[n]->Stop();
// Trigger event so that the thread processes the exit flag.
for (uint n = 0; n < pool.GetCount(); ++n)
job_queued_event.Trigger();
// Join threads.
for (uint n = 0; n < pool.GetCount(); ++n)
if (!pool[n]->IsRunning())
delete pool[n];
pool.Free();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool JobManager::EnqueueJob(Job *job, JobGroup *group)
{
if (pool.GetCount() == 0)
{
job->Execute(0);
job->done.Set(1);
}
else
{
job->done.Set(0);
if (group)
{
MutexLock lock(group->job_list_mutex);
group->job_list.Add(job);
}
{
#if __USE_LOCK_FREE_JOB_QUEUE__
while (!pending_queue.enqueue(job)) {}
#else
nMutexLock lock(pending_queue_mutex);
pending_queue.Push(job);
#endif
}
}
job_queued_event.Trigger(); // wake workers
return true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool JobManager::JoinJob(Job *job, bool blocking)
{
if (job)
while (job->done.Get() == 0) // spinlock
if (!blocking)
return false;
return true;
}
bool JobManager::JoinGroup(JobGroup *group, bool blocking)
{
if (group)
for (bool done = false; !done; ) // spinlock
{
done = true;
{
MutexLock glock(group->job_list_mutex);
ListForeachPtr(Job *, job, group->job_list)
if (job->done.Get() == 0)
{
done = false;
break;
}
}
if (!blocking)
return done;
Thread::Switch();
}
return true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool JobManager::ExecutePendingJob(uint worker_id)
{
// Look for a job to execute.
Job *job = NULL;
{
#if __USE_LOCK_FREE_JOB_QUEUE__
pending_queue.dequeue(job);
#else
nMutexLock pending_lock(pending_queue_mutex);
if (pending_queue.GetCount() > 0)
{
job = pending_queue.Top();
pending_queue.Pop();
}
#endif
}
// Execute job.
if (job)
{
#if __ENABLE_ITT_API__
__itt_task_begin(domain, __itt_null, __itt_null, __itt_string_handle_create(job->name));
#endif
// job->time_start = Platform::Get().GetTime();
job->Execute(worker_id);
job->done.Set(1);
// job->time_end = Platform::Get().GetTime();
Thread::Switch(); // let other workers do their job
#if __ENABLE_ITT_API__
__itt_task_end(domain);
#endif
}
return asbool(job);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint JobManager::GetWorkerPoolSize() const
{ return pool.GetCount(); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
JobManager::JobManager() : pending_queue(256)
{
#if __ENABLE_ITT_API__
domain = __itt_domain_create("GS.JobManager");
#endif
#if (__USE_LOCK_FREE_JOB_QUEUE__ == 0)
pending_queue_mutex = new nMutex;
#endif
}
JobManager::~JobManager()
{ FreeJobThreadPool(); }
JobGroup::JobGroup()
{ job_list_mutex = new Mutex; }
//------------------------------------------------------------------------------

View File

@ -0,0 +1,160 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "filesystem/data_store.h"
#include "rand/rand.h"
#include "memory/nauto_ptr.h"
using namespace GS;
using namespace GS::IO;
//------------------------------------------------------------------------------
DataStore::Entry *DataStore::GetEntry(const String &id) const
{
ListForeachPtr(Entry *, e, entries)
if (e->id == id)
return e;
return NULL;
}
String DataStore::GetNewId()
{
for ( ; ; ++id_seed)
{
String id = String::Format("store_%012d", id_seed);
if (GetEntry(id) == NULL)
return id;
}
return String();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
size_t DataStore::GetEntrySize(const String &id) const
{
if (Entry *e = GetEntry(id))
return e->size;
return 0;
}
size_t DataStore::GetStoreSize() const
{
size_t size = 0;
ListForeachPtr(Entry *, e, entries)
size += e->size;
return size;
}
size_t DataStore::GetFreeStore() const
{ return limit - GetStoreSize(); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
String DataStore::Reserve(size_t size)
{
Threading::MutexLock lock(&mutex);
if (limit > 0) // enforce size limit
{
size_t store_size = GetStoreSize();
if (size > (limit - store_size))
return String(); // store is full
}
// Reserve a new entry.
Entry *entry = new Entry;
entry->id = GetNewId();
entry->size = size;
entries.Add(entry);
return entry->id;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool DataStore::Store(const String &id, const void *data, size_t size, const char *user)
{
Threading::MutexLock lock(&mutex);
Entry *entry = GetEntry(id);
if ((entry == NULL) || (entry->size != size))
return false; // invalid id/store size
lock.Unlock();
entry->user = user;
AutoPtr <Handle> h(io->Open(id, ModeWrite));
return h.IsValid() && (h->Write(data, size) == size);
}
bool DataStore::Free(const String &id)
{
Threading::MutexLock lock(&mutex);
Entry *entry = GetEntry(id);
if (entry == NULL)
return false; // invalid id
if (!io->Delete(id))
return false;
return entries.Remove(entry);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Store format
//
// 18 bytes - id
// 4 bytes - size in bytes
// -----------------------------
bool DataStore::Load(const char *path)
{
AutoPtr <Handle> h(io->Open(path));
if (h.IsNull())
return true; // nothing to restore
entries.Clear();
char id[18];
while (!h->IsEOF())
{
if (h->Read((void *)id, 18) != 18)
return false;
Entry *e = new Entry;
e->id.Set(id, id + 18);
e->size = h->Read <size_t> ();
uint user_data_size = h->Read <uint> ();
if (!e->user.Allocate(user_data_size))
return false;
h->Read((void *)e->user.c_str(), user_data_size);
entries.Add(e);
}
return true;
}
bool DataStore::Save(const char *path)
{
AutoPtr <Handle> h(io->Open(path, ModeWrite));
if (h.IsNull())
return false;
ListForeachPtr(Entry *, e, entries)
{
h->Write(e->id.c_str(), 18);
h->Write(&e->size, 4);
uint user_data_size = e->user.Len();
h->Write(user_data_size);
if (user_data_size > 0)
h->Write(e->user.c_str(), user_data_size);
}
return true;
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,218 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "filesystem/filesystem.h"
#include "filesystem/io_handle.h"
#include "log/log.h"
#if __PLATFORM_POSIX__
#include <unistd.h>
#include <sys/stat.h>
#elif __PLATFORM_WINDOWS__
#include <direct.h>
#endif
#include "filesystem/io_cfile.h"
#include "memory/nauto_ptr.h"
using GS::String;
using namespace GS::IO;
//------------------------------------------------------------------------------
bool Filesystem::Exists(const char *uri) const
{
AutoPtr <Handle> h(Open(uri));
return h.IsValid();
}
size_t Filesystem::FileSize(const char *uri) const
{
AutoPtr <Handle> h(Open(uri));
return h.IsNull() ? 0 : h->GetSize();
}
bool Filesystem::FileLoad(const char *uri, GS::Array <char> &buffer, bool verbose) const
{
AutoPtr <Handle> h(Open(uri));
if (h.IsNull())
{
if (verbose)
__LOG_W__ << "Failed to open '" << uri << "'.\n";
return false;
}
// Warning: Do not load through IO::Base::FileLoad. That would create another handle!
size_t size = h->GetSize();
if (!buffer.Allocate(size))
__ERR__(__LOG_W__ << "Failed to allocate memory to load '" << uri << "'.\n", false)
return asbool(h->Read(buffer.c_ptr(), size) == size);
}
bool Filesystem::FileSave(const char *uri, const GS::Array <char> &buffer) const
{
AutoPtr <Handle> h(Open(uri, ModeWrite));
if (h.IsNull())
__ERR__(__LOG_W__ << "Failed to open '" << uri << "'.\n", false)
return asbool(h->Write(buffer.c_ptr(), buffer.GetSize()) == buffer.GetSize());
}
bool Filesystem::FileCopy(const char *src, const char *dst) const
{
Array <char> buffer;
return FileLoad(src, buffer) && FileSave(dst, buffer);
}
bool Filesystem::FileMove(const char *src, const char *dst) const
{
Array <char> buffer;
return FileLoad(src, buffer) && FileSave(dst, buffer) && Delete(src);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
String Filesystem::MapToAbsolute(const char *uri) const
{
String _uri(uri);
ListForeachPtr(MountPoint *, m, mount_list)
if (_uri.StartsWith(m->mount_point))
return m->io_sys->MapToAbsolute(_uri.Mid(m->mount_point.Len())).CleanFilePath();
ListForeachPtr(Base *, i, root_mount)
{
AutoPtr <Handle> h(i->Open(_uri));
if (h.IsValid())
return i->MapToAbsolute(_uri).CleanFilePath();
}
return _uri;
}
String Filesystem::StripRootPath(const char *path) const
{
String _path(path);
_path.FileCleanName();
ListForeachPtr(Base *, i, root_mount)
{
String rpath = i->MapToRelative(_path);
if (!rpath.IsEmpty())
if (rpath != _path)
return rpath[0] == '/' ? rpath.Mid(1) : rpath; // Ensure no leading '/' remains.
}
return _path;
}
bool Filesystem::Mount(Base *io_sys, const char *mount_point)
{
if (mount_point)
{
ListForeachPtr(MountPoint *, m, mount_list)
if (m->mount_point == mount_point)
{
delete io_sys;
return false;
}
return asbool(mount_list.Prepend(new MountPoint(mount_point, io_sys)));
}
else
{
ListForeachPtr(Base *, i, root_mount)
if (i == io_sys)
__ERR__(__LOG_E__ << "Cannot mount IO system twice as root.\n", false)
return asbool(root_mount.Prepend(io_sys));
}
}
void Filesystem::Unmount(const char *mount_point)
{ Unmount(GetIOSystem(mount_point)); }
void Filesystem::Unmount(Base *io_sys)
{
ListForeachPtr(MountPoint *, m, mount_list)
if (m->io_sys.c_ptr() == io_sys)
mount_list.Remove(m);
ListForeachPtr(Base *, i, root_mount)
if (i == io_sys)
root_mount.Remove(i);
}
void Filesystem::UnmountAll()
{
ListForeachPtr(MountPoint *, m, mount_list)
mount_list.Remove(m);
while (List <Base *> ::Item *m = root_mount.GetRoot())
root_mount.Remove(m);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Base *Filesystem::GetIOSystem(const char *mount_point) const
{
ListForeachPtr(MountPoint *, m, mount_list)
if (m->mount_point == mount_point)
return m->io_sys;
return NULL;
}
const char *Filesystem::GetMountPoint(const Base *io_sys) const
{
ListForeachPtr(MountPoint *, m, mount_list)
if (m->io_sys == io_sys)
return m->mount_point;
return NULL;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Handle *Filesystem::Open(const char *uri, Mode mode) const
{
String _uri(uri);
if (_uri.IsEmpty())
return NULL;
ListForeachPtr(MountPoint *, m, mount_list)
if (_uri.StartsWith(m->mount_point))
return m->io_sys->Open(_uri.Mid(m->mount_point.Len()), mode);
ListForeachPtr(Base *, i, root_mount)
if (Handle *h = i->Open(uri, mode))
return h;
return NULL;
}
void Filesystem::Close(Handle *h) const
{
ListForeachPtr(MountPoint *, m, mount_list)
if (m->io_sys.c_ptr() == h->GetIOSystem())
m->io_sys->Close(h);
ListForeachPtr(Base *, i, root_mount)
if (i == h->GetIOSystem())
i->Close(h);
}
bool Filesystem::Delete(const char *uri) const
{
AutoPtr <Handle> h(Open(uri));
if (h.IsValid())
{
Base *io_sys = h->GetIOSystem();
h = NULL;
return io_sys->Delete(uri);
}
else
return asbool(unlink(uri) == 0);
return false;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Filesystem::MkDir(const char *path) const
{
String _path(path);
if (_path.IsEmpty())
return false;
ListForeachPtr(MountPoint *, m, mount_list)
if (_path.StartsWith(m->mount_point))
return m->io_sys->MkDir(_path.Mid(m->mount_point.Len()));
// [EJ] No creation on a root filesystem here!
return false;
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,984 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "filesystem/ftp_lib.h"
#include "nstring/nstring.h"
#include "platform_config.h"
#include "alloc/ialloc.h"
#include "log/log.h"
using namespace GS;
#define ConnectionBufferSize 1024
#if __PLATFORM_WINDOWS__
#define SETSOCKOPT_OPTVAL_TYPE (const char *)
#define net_read(x,y,z) recv(x,(char*)y,z,0)
#define net_write(x,y,z) send(x,(char*)y,z,0)
#define net_close closesocket
typedef int socklen_t;
#elif (__PLATFORM_LINUX__ || __PLATFORM_OSX__)
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define SETSOCKOPT_OPTVAL_TYPE (void *)
#define net_read read
#define net_write write
#define net_close close
#define SOCKET int
#endif
//------------------------------------------------------------------------------
#if (__PLATFORM_WINDOWS__ || __PLATFORM_LINUX__ || __PLATFORM_OSX__)
#define FTP_PROPAGATE_ERROR__(__C__) { State s = __C__; if (s != FtpOk) return s; }
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
//----------------------------
FtpConnection::FtpConnection()
//----------------------------
{
handle = -1;
ready = false;
buffer = 0;
buffer_usage = 0;
}
//---------------------------------------------
void FtpConnection::FreeBuffer()
//---------------------------------------------
{ _safe_delete_array(buffer); }
//-------------------------------------------------
bool FtpConnection::AllocateBuffer()
//-------------------------------------------------
{
FreeBuffer();
return (buffer = new char[ConnectionBufferSize]) != NULL ? true : false;
}
//-------------------------------------------------------------------
FtpLibrary::State FtpLibrary::WaitSocket(FtpConnection *connection)
//-------------------------------------------------------------------
{
fd_set fd, *rfd = NULL, *wfd = NULL;
FD_ZERO(&fd);
if (connection->direction == FtpConnection::Upload)
wfd = &fd;
else
rfd = &fd;
forever
{
FD_SET(connection->handle, &fd);
// 5 seconds timeout.
timeval tv;
tv.tv_sec = 4;
tv.tv_usec = 100000;
SOCKET rv = select((int)(connection->handle + 1), rfd, wfd, NULL, &tv);
if (rv == -1)
return FtpError;
else if (!rv)
return FtpSocketTimeout;
else
break;
/*
if (!IdleCallback())
FtpSocketTimeout;
*/
}
return FtpOk;
}
//---------------------------------------------------
bool FtpLibrary::CheckResponse(char c)
//---------------------------------------------------
{
char match[5];
int length;
if (ReadASCII(response, 256, &master_connection, length) != FtpOk)
return false;
if (response[3] == '-')
{
strncpy(match, response, 3);
match[3] = ' ';
match[4] = '\0';
do
{
if (ReadASCII(response, 256, &master_connection, length) != FtpOk)
return false;
} while (strncmp(response, match, 4));
}
return (response[0] == c) ? true : false;
}
//-------------------------------------------------------
bool FtpLibrary::Connect(const char *host)
//-------------------------------------------------------
{
sockaddr_in sin;
memset(&sin,0,sizeof(sin));
sin.sin_family = AF_INET;
char *lhost = strdup(host), *pnum = strchr(lhost,':');
servent *pse;
if (!pnum)
{
if ((pse = getservbyname("ftp", "tcp")) == NULL)
__ERR__(__LOG__ << "[!] (FTP) Failed to get service port.\n", false)
sin.sin_port = pse->s_port;
}
else
{
*pnum++ = 0;
if (isdigit(*pnum))
sin.sin_port = htons((u_short)atoi(pnum));
else
{
pse = getservbyname(pnum, "tcp");
sin.sin_port = pse->s_port;
}
}
#if __PLATFORM_WINDOWS__
if ((sin.sin_addr.s_addr = inet_addr(lhost)) == -1)
#else
if (!inet_aton(lhost, &sin.sin_addr))
#endif
{
hostent *phe;
if ((phe = gethostbyname(lhost)) == NULL)
__ERR__(__LOG__ << "[!] (FTP) Failed to resolve host.\n", false)
memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
}
free(lhost);
//-------------------------------------------------------------------------------------------------------
#define __ConnectError__(_S_)\
{ __LOG__ << _S_; net_close(master_connection.handle); master_connection.handle = 0; return false; }
//-------------------------------------------------------------------------------------------------------
master_connection.handle = (int)socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (master_connection.handle == -1)
__ConnectError__("[!] (FTP) Failed to create socket.\n")
int on = 1;
if (setsockopt(master_connection.handle, SOL_SOCKET, SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1)
__ConnectError__("[!] (FTP) Set socket option failed.\n")
if (connect(master_connection.handle, (struct sockaddr *)&sin, sizeof(sin)) == -1)
__ConnectError__("[!] (FTP) Socket failed to connect.\n")
if (!CheckResponse('2'))
__ConnectError__("")
return true;
}
//-----------------------------------------------------------------
bool FtpLibrary::CheckPASVResponse(unsigned char *v)
//-----------------------------------------------------------------
{
sockaddr sa;
socklen_t l = sizeof(sa);
if (getpeername(master_connection.handle, &sa, &l) == -1)
{
net_close(master_connection.handle);
return false;
}
for (int i = 2; i < 6; ++i)
v[i] = sa.sa_data[i];
return true;
}
//---------------------------------------------------------------------------
bool FtpLibrary::FtpSendCmd(const char *command, char expresp)
//---------------------------------------------------------------------------
{
if (!master_connection.handle)
return 0;
char ftp_command[256];
_snprintf(ftp_command, 255, "%s\r\n", command);
if (net_write(master_connection.handle, ftp_command, (int)strlen(ftp_command)) <= 0)
return false;
SendCommandCallback(ftp_command);
return CheckResponse(expresp);
}
//---------------------------------------------------------------------------
bool FtpLibrary::Login(const char *user, const char *password)
//---------------------------------------------------------------------------
{
char ftp_command[64];
// Send user.
_snprintf(ftp_command, 63, "USER %s", user);
if (!FtpSendCmd(ftp_command, '3'))
{
if (*GetLastResponse() == '2')
return true;
return false;
}
// Send password.
_snprintf(ftp_command, 63, "PASS %s", password);
return FtpSendCmd(ftp_command, '2');
}
//------------------------------------------------------------------------------------------------------------------------------
FtpConnection *FtpLibrary::CreatePORTConnection(TransferMode mode, FtpConnection::Direction dir, char *connection_command)
//------------------------------------------------------------------------------------------------------------------------------
{
union
{
sockaddr sa;
sockaddr_in in;
} sin;
// Create the new connection.
FtpConnection *connection = new FtpConnection;
if (!connection)
__ERR__(__LOG__ << "[!] (FTP) Failed to allocate new connection object.\n", NULL)
// Get socket from the master connection.
socklen_t l = sizeof(sin);
if (getsockname(master_connection.handle, &sin.sa, &l) < 0)
return connection;
// Create socket.
connection->handle = (int)socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (connection->handle == -1)
return connection;
// Set socket options.
int on = 1;
if (setsockopt(connection->handle, SOL_SOCKET, SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1)
return connection;
linger lng = { 0, 0 };
if (setsockopt(connection->handle, SOL_SOCKET, SO_LINGER, SETSOCKOPT_OPTVAL_TYPE &lng, sizeof(lng)) == -1)
return connection;
// Bind socket.
sin.in.sin_port = 0;
if (
(bind(connection->handle, &sin.sa, sizeof(sin)) == -1) ||
(listen(connection->handle, 1) < 0) ||
(getsockname(connection->handle, &sin.sa, &l) < 0)
)
return connection;
// Open PORT connection.
char ftp_command[256];
_snprintf(ftp_command, 255, "PORT %hhu,%hhu,%hhu,%hhu,%hhu,%hhu",
(unsigned char)sin.sa.sa_data[2],
(unsigned char)sin.sa.sa_data[3],
(unsigned char)sin.sa.sa_data[4],
(unsigned char)sin.sa.sa_data[5],
(unsigned char)sin.sa.sa_data[0],
(unsigned char)sin.sa.sa_data[1] );
if (!FtpSendCmd(ftp_command, '2'))
return connection;
// Handle resuming.
if (offset)
{
_snprintf(ftp_command, 255, "REST %lld", offset);
if (!FtpSendCmd(ftp_command, '3'))
return connection; // TODO allow for a full restart here?
}
// Allocate buffer for binary transaction.
if ((mode == TransferASCII) && !connection->AllocateBuffer())
return connection;
// Finally send the connection command.
if (!FtpSendCmd(connection_command, '1'))
return connection;
// Connection is ready.
connection->direction = dir;
connection->ready = true;
return connection;
}
//------------------------------------------------------------------------------------------------------------------------------
FtpConnection *FtpLibrary::CreatePASVConnection(TransferMode mode, FtpConnection::Direction dir, char *connection_command)
//------------------------------------------------------------------------------------------------------------------------------
{
// Set PASV mode.
if (!FtpSendCmd("PASV", '2'))
return NULL;
// Check server answer.
char *cp = strchr(response,'(');
if (!cp)
return NULL;
unsigned char v[6];
sscanf(++cp, "%hhu,%hhu,%hhu,%hhu,%hhu,%hhu", &v[2], &v[3], &v[4], &v[5], &v[0], &v[1]);
if (correctpasv && !CheckPASVResponse(v))
__ERR__(__LOG__ << "[!] (FTP) Incorrect PASV response.\n", NULL)
struct sockaddr sa;
sa.sa_family = AF_INET;
sa.sa_data[2] = v[2];
sa.sa_data[3] = v[3];
sa.sa_data[4] = v[4];
sa.sa_data[5] = v[5];
sa.sa_data[0] = v[0];
sa.sa_data[1] = v[1];
// Handle resume.
char ftp_command[256];
if (offset)
{
_snprintf(ftp_command, 255, "REST %lld", offset);
if (!FtpSendCmd(ftp_command, '3'))
return NULL;
}
// Create the new connection.
FtpConnection *connection = new FtpConnection;
if (!connection)
__ERR__(__LOG__ << "[!] (FTP) Failed to allocate new connection object.\n", NULL)
// Create socket.
int on = 1;
linger lng = { 0, 0 };
connection->handle = (int)socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if (
(connection->handle == -1) ||
(setsockopt(connection->handle, SOL_SOCKET, SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1) ||
(setsockopt(connection->handle, SOL_SOCKET, SO_LINGER, SETSOCKOPT_OPTVAL_TYPE &lng, sizeof(lng)) == -1)
)
return connection;
// Setup connection.
_snprintf(ftp_command, 255, "%s\r\n", connection_command);
if (net_write(master_connection.handle, ftp_command, (int)strlen(ftp_command)) <= 0)
return connection;
// Connect socket.
if ((connect(connection->handle, &sa, sizeof(sa)) == -1) || !CheckResponse('1'))
return connection;
// Allocate buffer for binary transaction.
if ((mode == TransferASCII) && !connection->AllocateBuffer())
return connection;
// Connection is ready.
connection->direction = dir;
connection->ready = true;
return connection;
}
//----------------------------------------------------------------------------
bool FtpLibrary::FtpAcceptConnection(FtpConnection *connection)
//----------------------------------------------------------------------------
{
// Reset all connections.
fd_set mask;
FD_ZERO(&mask);
FD_SET(master_connection.handle, &mask);
FD_SET(connection->handle, &mask);
// Setup timeout.
timeval tv;
tv.tv_usec = 0;
tv.tv_sec = 30;
// Select handle.
int i = (int)master_connection.handle;
if (i < connection->handle)
i = connection->handle;
i = select((int)(i + 1), &mask, NULL, NULL, &tv);
switch (i)
{
case -1: // Error.
strncpy(response, strerror(errno), sizeof(response));
break;
case 0: // Time out.
strcpy(response, "Time out waiting for connection.");
break;
default:
if (FD_ISSET(connection->handle, &mask))
{
sockaddr addr;
socklen_t l = sizeof(addr);
int handle = (int)accept(connection->handle, &addr, &l);
i = errno;
net_close(connection->handle);
if (handle > 0)
{
connection->handle = handle;
return true;
}
strncpy(response, strerror((int)i), sizeof(response));
connection->handle = 0;
return false;
}
else
if (FD_ISSET(connection->handle, &mask))
CheckResponse('2');
break;
}
net_close(connection->handle);
connection->handle = 0;
return false;
}
//------------------------------------------------------------------------------
FtpConnection *FtpLibrary::CreateConnection(const char *path, AccessType type, TransferMode mode)
{
if (!path && ((type == AccessFileWrite) || (type == AccessFileRead) || (type == AccessFileReadAppend) || (type == AccessFileWriteAppend)))
__ERR__(__LOG__ << "[!] (FTP) Missing path argument.\n", NULL)
// Setup transfer mode.
char ftp_command[256];
_snprintf(ftp_command, 255, "TYPE %c", mode);
if (!FtpSendCmd(ftp_command, '2'))
__ERR__(__LOG__ << "[!] (FTP) Failed to set tranfer mode.\n", NULL)
// Select sub command.
const char *sub_command;
FtpConnection::Direction direction = FtpConnection::Download;
switch (type)
{
case AccessDir:
sub_command = "NLST";
break;
case AccessDirVerbose:
sub_command = "LIST -aL";
break;
case AccessFileReadAppend:
case AccessFileRead:
sub_command = "RETR";
break;
case AccessFileWriteAppend:
case AccessFileWrite:
sub_command = "STOR";
direction = FtpConnection::Upload;
break;
default:
__ERR__(__LOG__ << "[!] (FTP) Invalid access type.\n", NULL)
}
// Append path.
if (path)
_snprintf(ftp_command, 255, "%s %s", sub_command, path);
// Open connection.
FtpConnection *connection = NULL;
switch (connection_mode)
{
case ConnectionPASV:
connection = CreatePASVConnection(mode, direction, ftp_command);
break;
case ConnectionPORT:
connection = CreatePORTConnection(mode, direction, ftp_command);
if (!connection || !connection->ready)
break;
if (!FtpAcceptConnection(connection))
{
CloseConnection(connection);
return NULL;
}
break;
}
return connection;
}
bool FtpLibrary::CloseConnection(FtpConnection *connection)
{
// Sanity check.
if (connection == &master_connection)
return false;
// Purge writing cache.
int length;
if (connection->direction == FtpConnection::Upload)
if (connection->buffer)
WriteASCII(NULL, 0, connection, length);
shutdown(connection->handle, 2);
net_close(connection->handle);
_safe_delete(connection);
return CheckResponse('2');
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
FtpLibrary::State FtpLibrary::ReadASCII(char *buf, int max, FtpConnection *connection, int &total_read_count)
{
/// TODO
// Early exit case.
if (max == 0)
return FtpOk;
if ((connection != &master_connection) && (connection->direction != FtpConnection::Download))
return FtpError;
// Read.
total_read_count = 0;
char *p_buffer = buf;
forever
{
// Check available data on cache.
if (connection->buffer_usage > 0)
{
// Determine read size.
char *eol = (char *)memchr(connection->buffer, '\n', connection->buffer_usage);
int read_size = (int)(eol ? eol - connection->buffer + 1 : connection->buffer_usage);
if (read_size > (max - 1))
read_size = max - 1;
// Perform reading.
memcpy(p_buffer, connection->buffer, read_size);
max -= read_size;
total_read_count += read_size;
p_buffer += read_size;
// Update cache.
if (read_size < connection->buffer_usage)
memcpy(connection->buffer, &connection->buffer[read_size], connection->buffer_usage - read_size);
connection->buffer_usage -= read_size;
// Catch end of buffer.
if ((max == 1) || eol)
{
p_buffer[0] = 0;
break;
}
}
// Wait socket.
FTP_PROPAGATE_ERROR__(WaitSocket(connection))
// Fill cache.
int buffer_left = (ConnectionBufferSize - connection->buffer_usage) - 1,
read_count = net_read(connection->handle, &connection->buffer[connection->buffer_usage], buffer_left);
connection->buffer_usage += read_count;
if (read_count == -1)
__ERR__(__LOG__ << "[!] (FTP) Read error.\n", FtpError)
else if (!read_count)
break; // EOF
}
return FtpOk;
}
FtpLibrary::State FtpLibrary::WriteASCII(char *output, int length, FtpConnection *connection, int &x)
{
/// TODO
if (connection->direction != FtpConnection::Upload)
return FtpError;
FTP_PROPAGATE_ERROR__(WaitSocket(connection))
if ((x = net_write(connection->handle, output, length)) != length)
return FtpError;
return FtpOk;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
FtpLibrary::State FtpLibrary::ReadBinary(void *buf, int max, FtpConnection *connection, int &length)
{
if (connection->direction != FtpConnection::Download)
return FtpError;
FTP_PROPAGATE_ERROR__(WaitSocket(connection))
length = net_read(connection->handle, buf, max);
if (length == -1)
return FtpError;
DataReadCallback(connection);
return FtpOk;
}
FtpLibrary::State FtpLibrary::WriteBinary(void *buf, int len, FtpConnection *connection)
{
if (connection->direction != FtpConnection::Upload)
return FtpError;
FTP_PROPAGATE_ERROR__(WaitSocket(connection))
if (net_write(connection->handle, buf, len) != len)
return FtpError;
DataWriteCallback(connection);
return FtpOk;
}
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
FtpLibrary::State FtpLibrary::DataTransfer(const char *localfile, const char *path, AccessType type, TransferMode mode)
//-----------------------------------------------------------------------------------------------------------------------
{
// Open local file or I/O stream.
FILE *file;
if (localfile)
{
const char *access;
switch (type)
{
default:
case AccessDir:
case AccessDirVerbose:
case AccessFileRead:
access = (mode == TransferBinary) ? "wb" : "w";
break;
case AccessFileReadAppend:
access = (mode == TransferBinary) ? "ab" : "a";
break;
case AccessFileWriteAppend:
case AccessFileWrite:
access = (mode == TransferBinary) ? "rb" : "r";
break;
}
file = fopen(localfile, access);
if (!file)
__ERR__(__LOG_E__ << "Failed to open FTP output file.\n", FtpError)
if (type == AccessFileWriteAppend)
if (fseek(file, offset, SEEK_SET))
{
fclose(file);
__ERR__(__LOG_E__ << "Failed to seek in FTP file for transfer.\n", FtpError)
}
}
else
file = (type == AccessFileWrite || type == AccessFileWriteAppend) ? stdin : stdout;
// Create a new connection.
FtpConnection *connection = CreateConnection(path, type, mode);
if (!connection)
{
if (localfile)
fclose(file);
return FtpError;
}
// Perform transfer.
State retv = FtpOk;
GS::Array <char> temp_buffer(ConnectionBufferSize);
int length;
if ((type == AccessFileWrite) || (type == AccessFileWriteAppend))
{
while ((length = (int)fread(temp_buffer, 1, ConnectionBufferSize, file)) > 0)
if (WriteBinary(temp_buffer, length, connection) != FtpOk)
{
retv = FtpError; // FTP write failed.
break;
}
}
else
{
while ((retv = ReadBinary(temp_buffer, ConnectionBufferSize, connection, length)) == FtpOk)
if (!length || (fwrite(temp_buffer, 1, length, file) <= 0))
break; // Done.
}
// Flush file.
fflush(file);
if (localfile)
fclose(file);
CloseConnection(connection);
return retv;
}
//------------------------------------------------------------------------------
FtpLibrary::State FtpLibrary::Download(const char *file, const char *path, TransferMode mode, int _offset)
{
offset = _offset;
if (!offset)
return DataTransfer(file, path, AccessFileRead, mode);
else return DataTransfer(file, path, AccessFileReadAppend, mode);
}
FtpLibrary::State FtpLibrary::Upload(const char *file, const char *path, TransferMode mode, int _offset)
{
offset = _offset;
if (!offset)
return DataTransfer(file, path, AccessFileWrite, mode);
else return DataTransfer(file, path, AccessFileWriteAppend, mode);
}
//------------------------------------------------------------------------------
//------------------------------------
bool FtpLibrary::Quit()
//------------------------------------
{
if (!master_connection.handle)
return true;
bool r = FtpSendCmd("QUIT", '2');
net_close(master_connection.handle);
master_connection.handle = 0;
return r;
}
//------------------------------------------------------------------------------
bool FtpLibrary::DeleteFile(const char *path)
{ return FtpSendCmd(String::Format("DELE %s", path).c_str(), '2'); }
bool FtpLibrary::ChangeDirectory(const char *path)
{ return FtpSendCmd(String::Format("CWD %s", path).c_str(), '2'); }
bool FtpLibrary::UpDirectory()
{ return FtpSendCmd("CDUP", '2'); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int FtpLibrary::GetFileSize(const char *path, TransferMode mode)
//------------------------------------------------------------------------------
{
int rs, sz = -1;
if ( FtpSendCmd(String::Format("TYPE %c", mode).c_str(), '2') &&
FtpSendCmd(String::Format("SIZE %s", path).c_str(), '2') &&
(sscanf(response, "%d %d", &rs, &sz) == 2) )
return sz;
return -1;
}
//----------------------------------------------------------------------------
bool FtpLibrary::Nlst(const char *outputfile, const char *path)
//----------------------------------------------------------------------------
{
offset = 0;
return DataTransfer(outputfile, path, FtpLibrary::AccessDir, FtpLibrary::TransferASCII) == FtpOk ? true : false;
}
//------------------------------------------------------------------------------
FtpLibrary::FtpLibrary()
{
#if __PLATFORM_WINDOWS__
WSADATA wsa;
if (WSAStartup(MAKEWORD(1, 1), &wsa))
__LOG__ << "[!] (FTP) WINSOCK startup error.\n";
#endif
connection_mode = ConnectionPORT;
master_connection.AllocateBuffer();
//
offset = 0;
correctpasv = false;
}
FtpLibrary::~FtpLibrary()
{ Quit(); }
//------------------------------------------------------------------------------
#endif
/*
int FtpLibrary::Site(const char *cmd)
{
char buf[256];
if ((strlen(cmd) + 7) > sizeof(buf)) return 0;
sprintf(buf,"SITE %s",cmd);
if (!FtpSendCmd(buf,'2',mp_ftphandle)) return 0;
return 1;
}
int FtpLibrary::Raw(const char *cmd)
{
char buf[256];
strncpy(buf, cmd, 256);
if (!FtpSendCmd(buf,'2',mp_ftphandle)) return 0;
return 1;
}
int FtpLibrary::SysType(char *buf, int max)
{
int l = max;
char *b = buf;
char *s;
if (!FtpSendCmd("SYST",'2',mp_ftphandle)) return 0;
s = &mp_ftphandle->response[4];
while ((--l) && (*s != ' ')) *b++ = *s++;
*b++ = '\0';
return 1;
}
int FtpLibrary::Mkdir(const char *path)
{
char buf[256];
if ((strlen(path) + 6) > sizeof(buf)) return 0;
sprintf(buf,"MKD %s",path);
if (!FtpSendCmd(buf,'2', mp_ftphandle)) return 0;
return 1;
}
int FtpLibrary::Rmdir(const char *path)
{
char buf[256];
if ((strlen(path) + 6) > sizeof(buf)) return 0;
sprintf(buf,"RMD %s",path);
if (!FtpSendCmd(buf,'2',mp_ftphandle)) return 0;
return 1;
}
int FtpLibrary::Pwd(char *path, int max)
{
int l = max;
char *b = path;
char *s;
if (!FtpSendCmd("PWD",'2',mp_ftphandle)) return 0;
s = strchr(mp_ftphandle->response, '"');
if (s == NULL) return 0;
s++;
while ((--l) && (*s) && (*s != '"')) *b++ = *s++;
*b++ = '\0';
return 1;
}
int FtpLibrary::Dir(const char *outputfile, const char *path)
{
mp_ftphandle->offset = 0;
return FtpXfer(outputfile, path, mp_ftphandle, FtpLibrary::dirverbose, FtpLibrary::ascii);
}
int FtpLibrary::ModDate(const char *path, char *dt, int max)
{
char buf[256];
int rv = 1;
if ((strlen(path) + 7) > sizeof(buf)) return 0;
sprintf(buf,"MDTM %s",path);
if (!FtpSendCmd(buf,'2',mp_ftphandle)) rv = 0;
else strncpy(dt, &mp_ftphandle->response[4], max);
return rv;
}
int FtpLibrary::Rename(const char *src, const char *dst)
{
char cmd[256];
if (((strlen(src) + 7) > sizeof(cmd)) || ((strlen(dst) + 7) > sizeof(cmd))) return 0;
sprintf(cmd,"RNFR %s",src);
if (!FtpSendCmd(cmd,'3',mp_ftphandle)) return 0;
sprintf(cmd,"RNTO %s",dst);
if (!FtpSendCmd(cmd,'2',mp_ftphandle)) return 0;
return 1;
}
void FtpLibrary::SetConnmode(connmode mode)
{
mp_ftphandle->cmode = mode;
}
ftphandle* FtpLibrary::RawOpen(const char *path, accesstype type, transfermode mode)
{
int ret;
ftphandle* datahandle;
ret = CreateConnection(path, type, mode, mp_ftphandle, &datahandle);
if (ret) return datahandle;
else return NULL;
}
int FtpLibrary::RawClose(ftphandle* handle)
{
return FtpClose(handle);
}
int FtpLibrary::RawWrite(void* buf, int len, ftphandle* handle)
{
return FtpWrite(buf, len, handle);
}
int FtpLibrary::RawRead(void* buf, int max, ftphandle* handle)
{
return FtpRead(buf, max, handle);
}
*/

View File

@ -0,0 +1,59 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "filesystem/io_base.h"
#include "filesystem/io_handle.h"
#include "memory/nauto_ptr.h"
#include "nstring/nstring.h"
#include "hash/nsha1.h"
#include "log/log.h"
using GS::String;
using namespace GS::IO;
//------------------------------------------------------------------------------
bool Base::FileLoad(const char *uri, GS::Array <char> &buffer)
{
AutoPtr <Handle> h(Open(uri));
if (h.IsNull())
return false;
size_t size = h->GetSize();
if (!buffer.Allocate(size))
return false;
return asbool(h->Read(buffer.c_ptr(), size) == size);
}
bool Base::FileSave(const char *uri, const GS::Array <char> &buffer)
{
AutoPtr <Handle> h(Open(uri, ModeWrite));
if (h.IsNull())
return false;
return asbool(h->Write(buffer.c_ptr(), buffer.GetSize()) == buffer.GetSize());
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Base::Exists(const char *uri)
{
AutoPtr <Handle> h(Open(uri, ModeRead));
return h.IsValid();
}
String Base::Hash(const char *uri)
{
Array <char> data;
return FileLoad(uri, data) ? SHA1::ComputeHexa(data) : String();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
String Base::MapToAbsolute(const char *uri) const
{ return String(uri); }
String Base::MapToRelative(const char *path) const
{ return String(path); }
//------------------------------------------------------------------------------

View File

@ -0,0 +1,130 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "filesystem/io_buffer.h"
#include "log/log.h"
#include "ntypes.h"
using namespace GS::IO;
//------------------------------------------------------------------------------
uint Buffer::GetCaps() const { return io->GetCaps(); }
Handle *Buffer::Open(const char *path, Mode mode)
{
AutoPtr <Handle> io_h(io->Open(path, mode));
if (io_h.IsNull())
return NULL;
AutoPtr <BufferHandle> b_h(new BufferHandle(this, io_h));
if (b_h.IsNull())
return NULL;
if (!b_h->read_buffer.buffer.Allocate(read_buffer_size))
return NULL;
b_h->size = io_h->GetSize();
io_h.Detach();
return b_h.Detach();
}
void Buffer::Close(Handle *h)
{
if (BufferHandle *b_h = (BufferHandle *)h)
b_h->handle = NULL;
}
bool Buffer::Delete(const char *path) { return io->Delete(path); }
size_t Buffer::Tell(Handle *h) { return ((BufferHandle *)h)->pos; }
size_t Buffer::Seek(Handle *h, ptrdiff_t offset, SeekRef seek)
{
if (BufferHandle *c_h = (BufferHandle *)h)
{
switch (seek)
{
case SeekStart:
c_h->pos = Types::Clamp <ptrdiff_t> (offset, 0, c_h->size);
break;
case SeekCurrent:
c_h->pos = Types::Clamp <ptrdiff_t> (c_h->pos + offset, 0, c_h->size);
break;
case SeekEnd:
c_h->pos = Types::Clamp <ptrdiff_t> (c_h->size + offset, 0, c_h->size);
break;
}
return 0;
}
return size_t(-1);
}
size_t Buffer::Read(Handle *h, void *data, size_t size)
{
// __LOG_V__ << "Buffer::Read: size = " << size << ".\n";
size_t read_size = 0;
if (BufferHandle *b_h = (BufferHandle *)h)
{
while (read_size < size)
{
ptrdiff_t buffer_pos = (b_h->pos + read_size) - b_h->read_buffer.start_pos;
if ((buffer_pos >= 0) && (buffer_pos < ptrdiff_t(b_h->read_buffer.usage)))
{
ptrdiff_t copy_size = Types::Min <ptrdiff_t> (b_h->read_buffer.usage - buffer_pos, size - read_size);
Memory::Copy((char *)data + read_size, b_h->read_buffer.buffer.c_ptr() + buffer_pos, copy_size);
// __LOG_V__ << "Buffer read: pos = " << buffer_pos << ", size = " << copy_size << ".\n";
read_size += copy_size;
}
else // refill cache
{
b_h->read_buffer.start_pos = b_h->pos + read_size;
if (b_h->read_buffer.start_pos >= b_h->size)
{
b_h->read_buffer.usage = 0;
break; // EJ 01/05: Improves EOF performance for the OGG streaming interface which makes many out of bound calls.
}
io->Seek(b_h->handle, b_h->read_buffer.start_pos, SeekStart);
b_h->read_buffer.usage = io->Read(b_h->handle, b_h->read_buffer.buffer.c_ptr(), b_h->read_buffer.buffer.GetSize());
// __LOG_V__ << "Buffer fill: pos = " << b_h->read_buffer.start_pos << ", size = " << b_h->read_buffer.usage << ".\n";
if (b_h->read_buffer.usage == 0)
break; // EOF
}
}
b_h->pos += read_size;
}
return read_size;
}
size_t Buffer::Write(Handle *h, const void *data, size_t size)
{
if (BufferHandle *b_h = (BufferHandle *)h)
{
size_t write_size = io->Write(b_h->handle, data, size);
b_h->pos += write_size;
return write_size;
}
return 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
GS::String Buffer::Hash(const char *path)
{ return io->Hash(path); } // [EJ] Do not perform a FileLoad here, IO::Buffer is typically sitting in front of a slow IO backend which potentially optimizes hash transfer.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Buffer::MkDir(const char *path)
{ return io->MkDir(path); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Buffer::Buffer(Base *base, size_t read_size, size_t write_size) : io(base)
{
read_buffer_size = Types::Clamp <size_t> (read_size, 0, Units::MB(16));
write_buffer_size = Types::Clamp <size_t> (write_size, 0, Units::MB(16));
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,280 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "filesystem/io_cache.h"
#include "hash/nsha1.h"
#include "platform.h"
#include "log/log.h"
#include "ntypes.h"
using namespace GS::IO;
//------------------------------------------------------------------------------
struct FreeEntry // should be in ReserveOnStore but local type on template is prohibited until C++0x
{
Cache::Entry *entry;
int score;
FreeEntry(Cache::Entry *e, int s) : entry(e), score(s) {}
static int ComputeScore(const Cache::Entry *e, size_t request_size, const GS::Time &ctime)
{
int time_bonus = (int)(ctime - e->last_use).toSec();
int size_bonus = e->size - request_size;
return time_bonus + size_bonus / 8;
}
static int CompareScore(FreeEntry *a, FreeEntry *b)
{ return b->score - a->score; }
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
GS::String Cache::ReserveOnStore(size_t size)
{
String id = store.Reserve(size);
if (!id.IsEmpty())
return id;
// Build a list of reference free entries.
Time ctime = Platform::Get().GetTime();
// No need to drop anything if the request can't fit anyway...
size_t total_freeable_store = 0;
ListForeachPtr(Entry *, e, entries)
if (e->refc == 0)
total_freeable_store += e->size;
if (size > (store.GetFreeStore() + total_freeable_store))
return "";
// Drop entries until the request fits in the store.
List <FreeEntry *> free_entries;
ListForeachPtr(Entry *, e, entries)
if (e->refc == 0)
free_entries.Add(new FreeEntry(e, FreeEntry::ComputeScore(e, size, ctime)));
free_entries.MergeSort(FreeEntry::CompareScore);
ListForeachPtr(FreeEntry *, e, free_entries)
{
__LOG_V__ << "IO::Cache: Disposing of cache entry '" << e->entry->path << "' (score: " << e->score << ").\n";
DeleteCacheEntry(e->entry);
id = store.Reserve(size);
if (!id.IsEmpty())
break;
}
ListDeleteAllPtr(FreeEntry *, free_entries)
store.Save();
return id;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Cache::Entry *Cache::GetCacheEntry(const char *path) const
{
ListForeachPtr(Entry *, entry, entries)
if (entry->path == path)
return entry;
return NULL;
}
Cache::Entry *Cache::CreateCacheEntry(const char *path)
{
__LOG_V__ << "Create cache entry for '" << path << "'.\n";
Array <char> data;
if (!io->FileLoad(path, data))
return NULL;
AutoPtr <Entry> entry(new Entry);
if (entry.IsNull())
return NULL;
entry->path = path;
entry->id = ReserveOnStore(data.GetSize());
if (entry->id.IsEmpty())
return NULL; // store full
Entry *e = entry.Detach();
entries.Add(e);
return UpdateCacheEntry(e, &data) ? e : NULL;
}
bool Cache::UpdateCacheEntry(Entry *entry, GS::Array <char> *preloaded_data)
{
__LOG_V__ << "Update cache entry for '" << entry->path << "'.\n";
Array <char> data;
if (preloaded_data)
data.Transfer(*preloaded_data);
else
if (!io->FileLoad(entry->path, data))
return false;
// Check current store entry size.
if (store.GetEntrySize(entry->id) != data.GetSize())
{
store.Free(entry->id);
entry->id = ReserveOnStore(data.GetSize());
if (entry->id.IsEmpty())
return false; // store is full
}
// Update store data.
if (!store.Store(entry->id, data.c_ptr(), data.GetSize(), entry->path))
return false;
store.Save();
entry->hash = SHA1::ComputeHexa(data);
entry->size = data.GetSize();
return true;
}
bool Cache::DeleteCacheEntry(Entry *entry)
{
if (entry->refc > 0)
return false;
store.Free(entry->id);
store.Save();
return entries.Remove(entry);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint Cache::GetCaps() const { return io->GetCaps(); }
Handle *Cache::Open(const char *path, Mode mode)
{
if (mode == ModeRead)
{
Threading::MutexLock lock(&mutex);
// Update cache.
Entry *entry = GetCacheEntry(path);
if (entry)
{
__LOG_V__ << "Entry match for '" << path << "'.\n";
if (entry->hash != io->Hash(path))
{
__LOG_V__ << "Hash mismatch for '" << path << "'.\n";
if (entry->refc > 0)
__LOG_W__ << "IO::Cache: Support file '" << entry->path << "' has changed but its cached version is in use and cannot be updated.\n";
else
{
if (!UpdateCacheEntry(entry)) // contention risk here due to the mutex lock and a potentially long update (eg. networked fs)
DeleteCacheEntry(entry);
// Check for a match in updated cache.
entry = GetCacheEntry(path);
}
}
}
else
entry = CreateCacheEntry(path);
// Return handler to store fs.
if (entry)
{
__LOG_V__ << "Opening '" << path << "' from cache.\n";
entry->last_use = Platform::Get().GetTime();
entry->refc++;
return new CacheHandle(this, path, store.GetIO()->Open(entry->id, mode));
}
}
// Direct access to the underlying fs.
return io->Open(path, mode);
}
void Cache::Close(Handle *h)
{
if (CacheHandle *c_h = (CacheHandle *)h)
{
Threading::MutexLock lock(&mutex);
if (Entry *entry = GetCacheEntry(c_h->path))
entry->refc--;
c_h->handle = NULL;
}
}
bool Cache::Delete(const char *path)
{
/*
[EJ] Minor synchronization issue warning.
If a cached handle is already in use and the support fs file is deleted
the cached handle will remain valid. Further open requests will then
unexpectedly succeed as long as a single cached handler remains open.
The correct fix would be to prevent deleting a support file as long as
a cached entry with a non-zero reference count exists for it.
*/
return io->Delete(path);
}
size_t Cache::Tell(Handle *h)
{ return ((CacheHandle *)h)->handle->Tell(); }
size_t Cache::Seek(Handle *h, ptrdiff_t offset, SeekRef seek)
{ return ((CacheHandle *)h)->handle->Seek(offset, seek); }
size_t Cache::Read(Handle *h, void *data, size_t size)
{ return ((CacheHandle *)h)->handle->Read(data, size); }
size_t Cache::Write(Handle *h, const void *data, size_t size)
{ return ((CacheHandle *)h)->handle->Write(data, size); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Cache::SynchronizeWithStore(const char *store_path)
{
if (!store.Load(store_path))
return false;
entries.Clear();
__LOG_H__ << "IO::Cache: Synchronizing with store.\n";
ListForeachPtr(DataStore::Entry *, e, store.GetEntries())
{
Entry *entry = new Entry;
entry->id = e->id;
entry->size = e->size;
entry->path = e->user;
entry->hash = store.GetIO()->Hash(entry->id);
entries.Add(entry);
}
__LOG__ << "Done, " << entries.GetCount() << " entries synchronized.\n";
return true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Cache::MkDir(const char *path)
{ return io->MkDir(path); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Cache::Cache(Base *base, Base *store_io, size_t store_size) : io(base), store(store_io, store_size) {}
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CacheHandle::~CacheHandle()
{ GetIOSystem()->Close(this); }
//-----------------------------------------------------------------------------

View File

@ -0,0 +1,137 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#if __PLATFORM_POSIX__
#include <unistd.h>
#include <sys/stat.h>
#elif __PLATFORM_WINDOWS__
#include <direct.h>
#endif
#include "filesystem/io_cfile.h"
#include "memory/nauto_ptr.h"
using GS::String;
using namespace GS::IO;
//------------------------------------------------------------------------------
void CFile::SetRootPath(const char *_root)
{ root = _root; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint CFile::GetCaps() const
{
uint flags = CanRead | CanWrite | CanSeek | CanMkDir;
#ifndef __PLATFORM_WINDOWS__
flags |= IsCaseSensitive;
#endif
return flags;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
String CFile::MapToAbsolute(const char *uri) const
{
if (!root.IsEmpty())
return root + "/" + uri;
return String(uri);
}
String CFile::MapToRelative(const char *path) const
{
String _path(path);
if (!root.IsEmpty() && _path.StartsWith(root, GetCaps() & IsCaseSensitive ? String::CaseSensitive : String::CaseInsensitive))
return _path.Mid(root.Len());
return _path;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Handle *CFile::Open(const char *path, Mode mode)
{
String _path(root.IsEmpty() ? path : (root + "/" + path).c_str()),
_access(mode == ModeRead ? "rb" : "wb");
AutoPtr <CFileHandle> h(new CFileHandle(this));
#if __PLATFORM_WINDOWS__
if (h->file = _wfopen((const wchar_t *)_path.toUcs2().c_ptr(), (const wchar_t *)_access.toUcs2().c_ptr()))
return h.Detach();
#else
if ((h->file = fopen(_path, _access)) != NULL)
return h.Detach();
#endif
return NULL;
}
void CFile::Close(Handle *h)
{
if (CFileHandle *ch = (CFileHandle *)h)
if (ch->file)
fclose(ch->file);
}
bool CFile::Delete(const char *uri)
{ return asbool(unlink(root + "/" + uri) == 0); }
size_t CFile::Seek(Handle *h, ptrdiff_t offset, SeekRef ref)
{
if (CFileHandle *ch = (CFileHandle *)h)
if (ch->file)
{
int c_seek[] = { SEEK_SET, SEEK_CUR, SEEK_END };
return fseek(ch->file, offset, c_seek[ref]);
}
return (size_t)-1;
}
size_t CFile::Tell(Handle *h)
{
if (CFileHandle *ch = (CFileHandle *)h)
if (ch->file)
return ftell(ch->file);
return (size_t)-1;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
size_t CFile::Read(Handle *h, void *b, size_t size)
{
if (CFileHandle *ch = (CFileHandle *)h)
if (ch->file)
return fread(b, 1, size, ch->file);
return 0;
}
size_t CFile::Write(Handle *h, const void *b, size_t size)
{
if (CFileHandle *ch = (CFileHandle *)h)
if (ch->file)
return fwrite(b, size, 1, ch->file) * size;
return 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool CFile::MkDir(const char *path)
{
String _path(root.IsEmpty() ? path : (root + "/" + path).c_str());
bool r = false;
#if __PLATFORM_WINDOWS__
r = _wmkdir((const wchar_t *)_path.toUcs2().c_ptr()) == 0;
#else
r = mkdir(path, 01777) == 0;
#endif
return r;
}
//------------------------------------------------------------------------------
CFile::CFile(const char *root_path)
{ SetRootPath(root_path); }
//------------------------------------------------------------------------------
CFileHandle::CFileHandle(Base *io) : Handle(io)
{ file = NULL; }
CFileHandle::~CFileHandle()
{ GetIOSystem()->Close(this); }
//------------------------------------------------------------------------------

View File

@ -0,0 +1,173 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "filesystem/io_crypto.h"
using namespace GS::IO;
//------------------------------------------------------------------------------
uint Crypto::GetCaps() const
{ return wrapped_io->GetCaps(); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Crypto::Encrypt(GS::Array <char> &data)
{
size_t len = key.Len();
for (size_t n = 0; n < data.GetSize(); ++n)
data[(int)n] = data[(int)n] ^ key[(int)(n % len)];
}
void Crypto::Decrypt(GS::Array <char> &data)
{
size_t len = key.Len();
for (size_t n = 0; n < data.GetSize(); ++n)
data[(int)n] = data[(int)n] ^ key[(int)(n % len)];
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Handle *Crypto::Open(const char *path, Mode mode)
{
/*
When opening a file in read mode, the wrapped io file is decrypted and
stored in the cached io file system for further access.
When opening a file in write mode, the file is first created in clear
on the cached io then encrypted and committed to the wrapped io.
*/
Handle *h = NULL;
switch (mode)
{
case ModeRead:
{
// Load wrapped IO file.
AutoPtr <Handle> _h(wrapped_io->Open(path, mode));
if (_h.IsNull())
break;
size_t size = _h->GetSize();
Array <char> data(size);
if (data.IsNull())
break;
if (_h->Read(data.c_ptr(), size) != size)
break;
// Decrypt buffer.
Decrypt(data);
// Write decrypted content to cache IO.
if ((h = cache_io->Open(path, ModeWrite)) != NULL)
h->Write(data.c_ptr(), size);
_safe_delete(h);
h = cache_io->Open(path, mode);
}
break;
case ModeWrite:
h = cache_io->Open(path, mode);
break;
default: break;
}
return h ? new CryptoHandle(this, h, path, mode) : NULL;
}
void Crypto::Close(Handle *_h)
{
if (CryptoHandle *h = (CryptoHandle *)_h)
{
h->cached_h = NULL;
switch (h->io_mode)
{
case ModeRead:
cache_io->Delete(h->path);
break;
case ModeWrite:
{
// Retrieve the whole cached file content and drop it from the cache IO.
h->cached_h = cache_io->Open(h->path);
size_t size = h->cached_h->GetSize();
Array <char> data(size);
if (data.IsValid())
h->cached_h->Read(data.c_ptr(), size);
h->cached_h = NULL;
cache_io->Delete(h->path);
// Encrypt buffer.
Encrypt(data);
// Commit file to the wrapped IO.
AutoPtr <Handle> _h(wrapped_io->Open(h->path, ModeWrite));
if (_h.IsValid())
_h->Write(data.c_ptr(), size);
}
break;
default: break;
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Crypto::Delete(const char *path)
{ return wrapped_io->Delete(path); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
size_t Crypto::Tell(Handle *_h)
{
if (CryptoHandle *h = (CryptoHandle *)_h)
return h->cached_h->Tell();
return (size_t)-1;
}
size_t Crypto::Seek(Handle *_h, ptrdiff_t offset, SeekRef seek)
{
if (CryptoHandle *h = (CryptoHandle *)_h)
return h->cached_h->Seek(offset, seek);
return (size_t)-1;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
size_t Crypto::Read(Handle *_h, void *p, size_t s)
{
if (CryptoHandle *h = (CryptoHandle *)_h)
return h->cached_h->Read(p, s);
return 0;
}
size_t Crypto::Write(Handle *_h, const void *p, size_t s)
{
if (CryptoHandle *h = (CryptoHandle *)_h)
return h->cached_h->Write(p, s);
return 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Crypto::MkDir(const char *path)
{ return wrapped_io->MkDir(path); }
//------------------------------------------------------------------------------
Crypto::Crypto(Base *_io, const char *_key) : wrapped_io(_io)
{
cache_io = new Memory;
key = _key;
}
//------------------------------------------------------------------------------
CryptoHandle::CryptoHandle(Base *io, Handle *h, const char *_path, Mode mode) : Handle(io), cached_h(h), path(_path), io_mode(mode)
{}
CryptoHandle::~CryptoHandle()
{ GetIOSystem()->Close(this); }
//------------------------------------------------------------------------------

View File

@ -0,0 +1,141 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#if __PLATFORM_POSIX__
#include <unistd.h>
#endif
#include "filesystem/io_dispatcher.h"
#include "memory/nauto_ptr.h"
using namespace GS;
using namespace GS::IO;
//------------------------------------------------------------------------------
bool Dispatcher::AddDispatch(Base *fs, const char *prefix)
{
if (prefix)
{
DispatchFS *d = new DispatchFS;
if (!d)
return false;
d->fs = fs;
d->prefix = prefix;
mounts.Add(d);
}
else
roots.Add(fs);
return true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint Dispatcher::GetCaps() const
{
uint flags = CanRead | CanWrite | CanSeek;
#ifndef __PLATFORM_WINDOWS__
flags |= IsCaseSensitive;
#endif
return flags;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Base *Dispatcher::Dispatch(String &uri, Mode mode)
{
ListForeachPtr(DispatchFS *, d, mounts)
if (uri.StartsWith(d->prefix))
{
uri = uri.Mid(d->prefix.Len());
return d->fs;
}
// Root FS make no sense for write operations.
if (mode == ModeRead)
ListForeachPtr(Base *, d, roots)
if (d->Exists(uri))
return d;
return NULL;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Handle *Dispatcher::Open(const char *uri, Mode mode)
{
String _uri(uri);
Base *base = Dispatch(_uri, mode);
if (!base)
return NULL;
Handle *h = base->Open(_uri, mode);
return h ? new DispatcherHandle(this, h) : NULL;
}
void Dispatcher::Close(Handle *h)
{
if (DispatcherHandle *dh = (DispatcherHandle *)h)
dh->handle->GetIOSystem()->Close(dh->handle);
}
bool Dispatcher::Delete(const char *uri)
{ return false; }
size_t Dispatcher::Seek(Handle *h, ptrdiff_t offset, SeekRef ref)
{
if (DispatcherHandle *dh = (DispatcherHandle *)h)
return dh->handle->GetIOSystem()->Seek(dh->handle, offset, ref);
return (size_t)-1;
}
size_t Dispatcher::Tell(Handle *h)
{
if (DispatcherHandle *dh = (DispatcherHandle *)h)
return dh->handle->GetIOSystem()->Tell(dh->handle);
return (size_t)-1;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
size_t Dispatcher::Read(Handle *h, void *b, size_t size)
{
if (DispatcherHandle *dh = (DispatcherHandle *)h)
return dh->handle->GetIOSystem()->Read(dh->handle, b, size);
return 0;
}
size_t Dispatcher::Write(Handle *h, const void *b, size_t size)
{
if (DispatcherHandle *dh = (DispatcherHandle *)h)
return dh->handle->GetIOSystem()->Write(dh->handle, b, size);
return 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Dispatcher::MkDir(const char *path)
{
String _path(path);
if (Base *base = Dispatch(_path, ModeWrite))
return base->MkDir(_path);
return false;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
String Dispatcher::Hash(const char *uri)
{
String _uri(uri);
if (Base *base = Dispatch(_uri, ModeRead))
return base->Hash(_uri);
return String();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
DispatcherHandle::DispatcherHandle(Base *io, Handle *h) : Handle(io), handle(h)
{}
DispatcherHandle::~DispatcherHandle()
{ GetIOSystem()->Close(this); }
//------------------------------------------------------------------------------

View File

@ -0,0 +1,58 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <string.h>
#include "filesystem/io_handle.h"
#include "filesystem/io_base.h"
using namespace GS::IO;
//------------------------------------------------------------------------------
size_t Handle::GetSize()
{
size_t p = Tell();
Seek(0, Base::SeekEnd);
size_t s = Tell();
Seek(p, Base::SeekStart);
return s;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Handle::IsEOF()
{ return Tell() >= GetSize(); }
size_t Handle::Rewind()
{ return Seek(0, Base::SeekStart); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
size_t Handle::Tell()
{ return io_sys.IsValid() ? io_sys->Tell(this) : 0; }
size_t Handle::Seek(ptrdiff_t offset, Base::SeekRef seek_ref)
{ return io_sys.IsValid() ? io_sys->Seek(this, offset, seek_ref) : 0; }
size_t Handle::Read(void *p, size_t size)
{ return io_sys.IsValid() ? io_sys->Read(this, p, size) : 0; }
size_t Handle::Write(const void *p, size_t size)
{ return io_sys.IsValid() ? io_sys->Write(this, p, size) : 0; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Handle &Handle::operator << (const char *s)
{
if (s)
Write(s, strlen(s));
return *this;
}
Handle &Handle::operator << (char *s)
{ return *this << ((const char *)s); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Handle::Handle(Base *io) : io_sys(io) {}
Handle::~Handle() {}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,80 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "filesystem/io_handle_segment.h"
using namespace GS::IO;
//------------------------------------------------------------------------------
size_t HandleSegment::GetSize()
{ return size; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
size_t HandleSegment::Tell()
{ return cursor; }
size_t HandleSegment::Seek(ptrdiff_t offset, Base::SeekRef ref)
{
switch (ref)
{
case Base::SeekStart:
cursor = offset;
break;
case Base::SeekCurrent:
cursor += offset;
break;
case Base::SeekEnd:
cursor = size - offset;
break;
}
if (cursor > size)
{
cursor = 0;
return (size_t)-1;
}
return 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/*
IO segment must always restore the original handle position and act as
transparently as possible.
*/
size_t HandleSegment::Read(void *b, size_t s)
{
size_t o = 0;
size_t t = handle->Tell();
if (!handle->Seek(offset + cursor, Base::SeekStart))
{
if (s > (size - cursor))
s = size - cursor;
o = handle->Read(b, s);
cursor += o;
}
handle->Seek(t, Base::SeekStart);
return o;
}
size_t HandleSegment::Write(const void *b, size_t s)
{
size_t o = 0;
size_t t = handle->Tell();
if (!handle->Seek(offset + cursor, Base::SeekStart))
{
o = handle->Write(b, s);
cursor += o;
}
handle->Seek(t, Base::SeekStart);
return o;
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,132 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "filesystem/io_memory.h"
using namespace GS::IO;
//------------------------------------------------------------------------------
uint Memory::GetCaps() const
{ return CanRead | CanWrite | CanSeek| IsCaseSensitive; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Handle *Memory::Open(const char *uri, Mode mode)
{
switch (mode)
{
case ModeRead:
ListForeachPtr(MemoryFile *, f, fat)
if (f->uri == uri)
return new MemoryHandle(this, f, mode);
break;
case ModeWrite:
{
MemoryFile *f_entry = NULL;
ListForeachPtr(MemoryFile *, f, fat)
if (f->uri == uri)
{
f_entry = f;
break;
}
if (!f_entry)
fat.Add(f_entry = new MemoryFile(uri));
return f_entry ? new MemoryHandle(this, f_entry, mode) : NULL;
}
break;
default: break;
}
return NULL;
}
void Memory::Close(Handle *h)
{ /* Nothing to be done. */ }
bool Memory::Delete(const char *uri)
{
ListForeachPtr(MemoryFile *, f, fat)
if (f->uri == uri)
return fat.Remove(f);
return false;
}
size_t Memory::Tell(Handle *h)
{
if (MemoryHandle *_h = (MemoryHandle *)h)
if (_h->file)
return _h->cursor;
return (size_t)-1;
}
size_t Memory::Seek(Handle *h, ptrdiff_t offset, SeekRef seek_ref)
{
if (MemoryHandle *_h = (MemoryHandle *)h)
if (_h->file)
{
switch (seek_ref)
{
case SeekStart:
_h->cursor = Types::Clamp <ptrdiff_t> (offset, 0, _h->file->size);
break;
case SeekCurrent:
_h->cursor = Types::Clamp <ptrdiff_t> (_h->cursor + offset, 0, _h->file->size);
break;
case SeekEnd:
_h->cursor = Types::Clamp <ptrdiff_t> (_h->file->size - offset, 0, _h->file->size);
break;
}
return 0;
}
return (size_t)-1;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
size_t Memory::Read(Handle *h, void *ptr, size_t size)
{
size_t read_size = 0;
if (MemoryHandle *_h = (MemoryHandle *)h)
if (_h->file && (_h->mode == ModeRead))
{
read_size = Types::Min <ptrdiff_t> (size, _h->file->size - _h->cursor);
GS::Memory::Copy(ptr, &_h->file->data[(int)_h->cursor], read_size);
_h->cursor += read_size;
}
return read_size;
}
size_t Memory::Write(Handle *h, const void *ptr, size_t size)
{
size_t write_size = 0;
if (MemoryHandle *_h = (MemoryHandle *)h)
if (_h->file && (_h->mode == ModeWrite))
{
size_t req_size = _h->cursor + size;
if (req_size > _h->file->data.GetSize())
if (!_h->file->data.Reallocate(req_size + 16384)) // required size + 16 kilobytes
return 0;
GS::Memory::Copy(&_h->file->data[(int)_h->cursor], ptr, size);
write_size = size;
_h->cursor += size;
_h->file->size = Types::Max(_h->file->size, req_size);
}
return write_size;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
MemoryHandle::MemoryHandle(Base *io, MemoryFile *_file, Mode _mode) : Handle(io), file(_file), cursor(0), mode(_mode)
{}
MemoryHandle::~MemoryHandle()
{ GetIOSystem()->Close(this); }
//------------------------------------------------------------------------------

View File

@ -0,0 +1,374 @@
/*
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.
----------------------------------------------------------------------------- */
#include <string.h>
#include "hash/md5.h"
#include "memory/endian.h"
using namespace GS::MD5;
#define T_MASK ((md5_word_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
#define T3 0x242070db
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
#define T6 0x4787c62a
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
#define T9 0x698098d8
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
#define T13 0x6b901122
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
#define T16 0x49b40821
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
#define T19 0x265e5a51
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
#define T22 0x02441453
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
#define T25 0x21e1cde6
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
#define T28 0x455a14ed
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
#define T31 0x676f02d9
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
#define T35 0x6d9d6122
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
#define T38 0x4bdecfa9
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
#define T41 0x289b7ec6
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
#define T44 0x04881d05
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
#define T47 0x1fa27cf8
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
#define T50 0x432aff97
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
#define T53 0x655b59c3
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
#define T57 0x6fa87e4f
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
#define T60 0x4e0811a1
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
//------------------------------------------------------------------------------
void Digest::Process(const md5_byte_t *data /*[64]*/)
{
md5_word_t a = abcd[0], b = abcd[1],
c = abcd[2], d = abcd[3],
t;
md5_word_t xbuf[16];
const md5_word_t *X;
if (GS::Endian::GetHostConfiguration() == GS::Endian::Little)
{
/*
On little-endian machines, we can process properly aligned
data without copying it.
*/
if (!((data - (const md5_byte_t *)0) & 3))
// Data are properly aligned.
X = (const md5_word_t *)data;
else
{
// Not aligned.
memcpy(xbuf, data, 64);
X = xbuf;
}
}
else // Dynamic big-endian.
{
/*
On big-endian machines, we must arrange the bytes in the
right order.
*/
const md5_byte_t *xp = data;
X = xbuf;
for (int i = 0; i < 16; ++i, xp += 4)
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
}
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + F(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
SET(c, d, a, b, 2, 17, T3);
SET(b, c, d, a, 3, 22, T4);
SET(a, b, c, d, 4, 7, T5);
SET(d, a, b, c, 5, 12, T6);
SET(c, d, a, b, 6, 17, T7);
SET(b, c, d, a, 7, 22, T8);
SET(a, b, c, d, 8, 7, T9);
SET(d, a, b, c, 9, 12, T10);
SET(c, d, a, b, 10, 17, T11);
SET(b, c, d, a, 11, 22, T12);
SET(a, b, c, d, 12, 7, T13);
SET(d, a, b, c, 13, 12, T14);
SET(c, d, a, b, 14, 17, T15);
SET(b, c, d, a, 15, 22, T16);
#undef SET
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define _G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + _G(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
SET(c, d, a, b, 11, 14, T19);
SET(b, c, d, a, 0, 20, T20);
SET(a, b, c, d, 5, 5, T21);
SET(d, a, b, c, 10, 9, T22);
SET(c, d, a, b, 15, 14, T23);
SET(b, c, d, a, 4, 20, T24);
SET(a, b, c, d, 9, 5, T25);
SET(d, a, b, c, 14, 9, T26);
SET(c, d, a, b, 3, 14, T27);
SET(b, c, d, a, 8, 20, T28);
SET(a, b, c, d, 13, 5, T29);
SET(d, a, b, c, 2, 9, T30);
SET(c, d, a, b, 7, 14, T31);
SET(b, c, d, a, 12, 20, T32);
#undef SET
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define SET(a, b, c, d, k, s, Ti)\
t = a + H(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 5, 4, T33);
SET(d, a, b, c, 8, 11, T34);
SET(c, d, a, b, 11, 16, T35);
SET(b, c, d, a, 14, 23, T36);
SET(a, b, c, d, 1, 4, T37);
SET(d, a, b, c, 4, 11, T38);
SET(c, d, a, b, 7, 16, T39);
SET(b, c, d, a, 10, 23, T40);
SET(a, b, c, d, 13, 4, T41);
SET(d, a, b, c, 0, 11, T42);
SET(c, d, a, b, 3, 16, T43);
SET(b, c, d, a, 6, 23, T44);
SET(a, b, c, d, 9, 4, T45);
SET(d, a, b, c, 12, 11, T46);
SET(c, d, a, b, 15, 16, T47);
SET(b, c, d, a, 2, 23, T48);
#undef SET
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + I(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
SET(c, d, a, b, 14, 15, T51);
SET(b, c, d, a, 5, 21, T52);
SET(a, b, c, d, 12, 6, T53);
SET(d, a, b, c, 3, 10, T54);
SET(c, d, a, b, 10, 15, T55);
SET(b, c, d, a, 1, 21, T56);
SET(a, b, c, d, 8, 6, T57);
SET(d, a, b, c, 15, 10, T58);
SET(c, d, a, b, 6, 15, T59);
SET(b, c, d, a, 13, 21, T60);
SET(a, b, c, d, 4, 6, T61);
SET(d, a, b, c, 11, 10, T62);
SET(c, d, a, b, 2, 15, T63);
SET(b, c, d, a, 9, 21, T64);
#undef SET
/*
Then perform the following additions. (That is increment each of the
four registers by the value it had before this block was started.)
*/
abcd[0] += a;
abcd[1] += b;
abcd[2] += c;
abcd[3] += d;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Digest::Reset()
{
count[0] = count[1] = 0;
abcd[0] = 0x67452301;
abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
abcd[3] = 0x10325476;
}
void Digest::Append(const md5_byte_t *data, int nbytes)
{
const md5_byte_t *p = data;
int left = nbytes,
offset = (count[0] >> 3) & 63;
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
return;
// Update the message length.
count[1] += nbytes >> 29;
count[0] += nbits;
if (count[0] < nbits)
count[1]++;
// Process an initial partial block.
if (offset)
{
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
Process(buf);
}
// Process full blocks.
for (; left >= 64; p += 64, left -= 64)
Process(p);
// Process a final partial block.
if (left)
memcpy(buf, p, left);
}
void Digest::Finish(md5_byte_t digest[16])
{
static const md5_byte_t pad[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
md5_byte_t data[8];
int i;
// Save the length before padding.
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t)(count[i >> 2] >> ((i & 3) << 3));
// Pad to 56 bytes mod 64.
Append(pad, ((55 - (count[0] >> 3)) & 63) + 1);
// Append the length.
Append(data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t)(abcd[i >> 2] >> ((i & 3) << 3));
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void GS::MD5::DigestToString(const md5_byte_t digest[16], char *s)
{
const char hex_table[17] = "0123456789abcdef";
for (int n = 0; n < 16; ++n)
{
*s++ = hex_table[(digest[n] >> 4) & 15];
*s++ = hex_table[digest[n] & 15];
}
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,47 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "hash/nsha1.h"
#include "hash/sha1.h"
#include "container/narray.h"
#include "nstring/nstring.h"
using namespace GS;
//------------------------------------------------------------------------------
void SHA1::ComputeHash(const String &source, Array <unsigned char> &hash)
{
if (hash.Allocate(20))
sha1::calc(source.c_str(), source.Len(), hash.c_ptr());
}
String SHA1::ComputeHexa(const String &source)
{
Array <unsigned char> hash;
ComputeHash(source, hash);
char hex[41];
sha1::toHexString(hash.c_ptr(), hex);
return String(hex);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void SHA1::ComputeHash(const Array <char> &data, Array <unsigned char> &hash)
{
if (hash.Allocate(20))
sha1::calc(data.c_ptr(), data.GetSize(), hash.c_ptr());
}
String SHA1::ComputeHexa(const Array <char> &data)
{
Array <unsigned char> hash;
ComputeHash(data, hash);
char hex[41];
sha1::toHexString(hash.c_ptr(), hex);
return String(hex);
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,185 @@
/*
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.
*/
/*
Contributors:
Gustav
Several members in the gamedev.se forum.
Gregory Petrosyan
*/
#include "hash/sha1.h"
namespace sha1
{
namespace // local
{
// Rotate an integer value to left.
inline const unsigned int rol(const unsigned int value,
const unsigned int steps)
{
return ((value << steps) | (value >> (32 - steps)));
}
// Sets the first 16 integers in the buffert to zero.
// Used for clearing the W buffert.
inline void clearWBuffert(unsigned int* buffert)
{
for (int pos = 16; --pos >= 0;)
{
buffert[pos] = 0;
}
}
void innerHash(unsigned int* result, unsigned int* w)
{
unsigned int a = result[0];
unsigned int b = result[1];
unsigned int c = result[2];
unsigned int d = result[3];
unsigned int e = result[4];
int round = 0;
#define sha1macro(func,val) \
{ \
const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
e = d; \
d = c; \
c = rol(b, 30); \
b = a; \
a = t; \
}
while (round < 16)
{
sha1macro((b & c) | (~b & d), 0x5a827999)
++round;
}
while (round < 20)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro((b & c) | (~b & d), 0x5a827999)
++round;
}
while (round < 40)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro(b ^ c ^ d, 0x6ed9eba1)
++round;
}
while (round < 60)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
++round;
}
while (round < 80)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro(b ^ c ^ d, 0xca62c1d6)
++round;
}
#undef sha1macro
result[0] += a;
result[1] += b;
result[2] += c;
result[3] += d;
result[4] += e;
}
} // namespace
void calc(const void* src, const int bytelength, unsigned char* hash)
{
// Init the result array.
unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
// Cast the void src pointer to be the byte array we can work with.
const unsigned char* sarray = (const unsigned char*) src;
// The reusable round buffer
unsigned int w[80];
// Loop through all complete 64byte blocks.
const int endOfFullBlocks = bytelength - 64;
int endCurrentBlock;
int currentBlock = 0;
while (currentBlock <= endOfFullBlocks)
{
endCurrentBlock = currentBlock + 64;
// Init the round buffer with the 64 byte block data.
for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
{
// This line will swap endian on big endian and keep endian on little endian.
w[roundPos++] = (unsigned int) sarray[currentBlock + 3]
| (((unsigned int) sarray[currentBlock + 2]) << 8)
| (((unsigned int) sarray[currentBlock + 1]) << 16)
| (((unsigned int) sarray[currentBlock]) << 24);
}
innerHash(result, w);
}
// Handle the last and not full 64 byte block if existing.
endCurrentBlock = bytelength - currentBlock;
clearWBuffert(w);
int lastBlockBytes = 0;
for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes)
{
w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3);
}
w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3);
if (endCurrentBlock >= 56)
{
innerHash(result, w);
clearWBuffert(w);
}
w[15] = bytelength << 3;
innerHash(result, w);
// Store hash in result pointer, and make sure we get in in the correct order on both endian models.
for (int hashByte = 20; --hashByte >= 0;)
{
hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
}
}
void toHexString(const unsigned char* hash, char* hexstring)
{
const char hexDigits[] = { "0123456789abcdef" };
for (int hashByte = 20; --hashByte >= 0;)
{
hexstring[hashByte << 1] = hexDigits[(hash[hashByte] >> 4) & 0xf];
hexstring[(hashByte << 1) + 1] = hexDigits[hash[hashByte] & 0xf];
}
hexstring[40] = 0;
}
} // namespace sha1

View File

@ -0,0 +1,19 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "input/input_keyboard.h"
#include "memory/memory.h"
using namespace GS::Input;
//------------------------------------------------------------------------------
Keyboard::Keyboard()
{
GS::Memory::Set(is_down, 0, sizeof(bool) * (uint)Key_Last);
GS::Memory::Set(was_down, 0, sizeof(bool) * (uint)Key_Last);
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,102 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "input/input_mouse.h"
using namespace GS::Input;
//------------------------------------------------------------------------------
bool Mouse::IsDown(KeyCode key) const
{
switch (key)
{
case Key_Button0: return state.left_button;
case Key_Button1: return state.right_button;
case Key_Button2: return state.middle_button;
default: break;
}
return false;
}
bool Mouse::WasDown(KeyCode key) const
{
switch (key)
{
case Key_Button0: return last_state.left_button;
case Key_Button1: return last_state.right_button;
case Key_Button2: return last_state.middle_button;
default: break;
}
return false;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Mouse::GetInputRange(InputCode i, float &mn, float &mx) const
{
switch (i)
{
case Input_AxisX:
case Input_AxisY:
mn = 0; mx = 1;
return true;
case Input_RotX: // Horizontal wheel.
case Input_RotY: // Vertical wheel.
mn = 0; mx = 1024;
return true;
default: break;
}
return false;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
float Mouse::GetValue(InputCode i) const
{
switch (i)
{
case Input_AxisX: return state.x;
case Input_AxisY: return state.y;
case Input_RotX: return state.hwheel;
case Input_RotY: return state.wheel;
default: break;
}
return 0;
}
float Mouse::GetLastValue(InputCode i) const
{
switch (i)
{
case Input_AxisX: return last_state.x;
case Input_AxisY: return last_state.y;
case Input_RotX: return last_state.hwheel;
case Input_RotY: return last_state.wheel;
default: break;
}
return 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Mouse::Mouse()
{
state.x = 0; state.y = 0;
state.left_button = false;
state.right_button = false;
state.middle_button = false;
state.wheel = 0;
state.hwheel = 0;
last_state = state;
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,96 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "input/input_touch.h"
#include "nstring/nstring.h"
using namespace GS::Input;
//------------------------------------------------------------------------------
void TouchDevice::RegisterTouchEvent(float x, float y, float weight)
{
pending_state.button = asbool(weight > 0);
pending_state.x = x;
pending_state.y = y;
}
void TouchDevice::Update()
{
last_state = state;
state = pending_state;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool TouchDevice::IsDown(KeyCode key) const
{ return key == Key_Button0 ? state.button : false; }
bool TouchDevice::WasDown(KeyCode key) const
{ return key == Key_Button0 ? last_state.button : false; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool TouchDevice::GetInputRange(InputCode i, float &mn, float &mx) const
{
switch (i)
{
case Input_AxisX:
case Input_AxisY:
mn = 0; mx = 1;
return true;
case Input_RotX: // Horizontal wheel.
case Input_RotY: // Vertical wheel.
mn = 0; mx = 1024;
return true;
default: break;
}
return false;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
float TouchDevice::GetValue(InputCode i) const
{
switch (i)
{
case Input_AxisX: return state.x;
case Input_AxisY: return state.y;
default: break;
}
return 0;
}
float TouchDevice::GetLastValue(InputCode i) const
{
switch (i)
{
case Input_AxisX: return last_state.x;
case Input_AxisY: return last_state.y;
default: break;
}
return 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void TouchDevice::SetIndex(int _index)
{ index = _index; }
Device::Type TouchDevice::GetType() const
{ return index == -1 ? Type_Mouse : Type_Touch; }
const char *TouchDevice::GetName() const
{ return index == -1 ? "mouse" : GS::String::Format("touch%d", index).c_str(); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
TouchDevice::TouchDevice(int i) : index(i)
{
state.x = 0; state.y = 0;
state.button = false;
pending_state = last_state = state;
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,285 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "locale/country.h"
namespace GS {
namespace Locale {
//------------------------------------------------------------------------------
static Info countries[] =
{
{ "Asia", "South Asia", "Afghanistan", "AF", "AF", "AFG", 4, "AF" },
{ "Europe", "South East Europe", "Albania", "AL", "AL", "ALB", 8, "AL" },
{ "Africa", "Northern Africa", "Algeria", "AG", "DZ", "DZA", 12, "DZ" },
{ "Oceania", "Pacific", "American Samoa", "AQ", "AS", "ASM", 16, "AS" },
{ "Europe", "South West Europe", "Andorra", "AN", "AD", "AND", 20, "AD" },
{ "Africa", "Southern Africa", "Angola", "AO", "AO", "AGO", 24, "AO" },
{ "Americas", "West Indies", "Anguilla", "AV", "AI", "AIA", 660, "AI" },
{ "Americas", "West Indies", "Antigua and Barbuda", "AC", "AG", "ATG", 28, "AG" },
{ "Americas", "South America", "Argentina", "AR", "AR", "ARG", 32, "AR" },
{ "Asia", "South West Asia", "Armenia", "AM", "AM", "ARM", 51, "AM" },
{ "Americas", "West Indies", "Aruba", "AA", "AW", "ABW", 533, "AW" },
{ "Oceania", "Pacific", "Australia", "AS", "AU", "AUS", 36, "AU" },
{ "Europe", "Central Europe", "Austria", "AU", "AT", "AUT", 40, "AT" },
{ "Asia", "South West Asia", "Azerbaijan", "AJ", "AZ", "AZE", 31, "AZ" },
{ "Americas", "West Indies", "Bahamas, The", "BF", "BS", "BHS", 44, "BS" },
{ "Asia", "South West Asia", "Bahrain", "BA", "BH", "BHR", 48, "BH" },
{ "Asia", "South Asia", "Bangladesh", "BG", "BD", "BGD", 50, "BD" },
{ "Americas", "West Indies", "Barbados", "BB", "BB", "BRB", 52, "BB" },
{ "Europe", "Eastern Europe", "Belarus", "BO", "BY", "BLR", 112, "BY" },
{ "Europe", "Western Europe", "Belgium", "BE", "BE", "BEL", 56, "BE" },
{ "Americas", "Central America", "Belize", "BH", "BZ", "BLZ", 84, "BZ" },
{ "Africa", "Western Africa", "Benin", "BN", "BJ", "BEN", 204, "BJ" },
{ "Americas", "West Indies", "Bermuda", "BD", "BM", "BMU", 60, "BM" },
{ "Asia", "South Asia", "Bhutan", "BT", "BT", "BTN", 64, "BT" },
{ "Americas", "South America", "Bolivia", "BL", "BO", "BOL", 68, "BO" },
{ "Europe", "South East Europe", "Bosnia and Herzegovina", "BK", "BA", "BIH", 70, "BA" },
{ "Africa", "Southern Africa", "Botswana", "BC", "BW", "BWA", 72, "BW" },
{ "Americas", "South America", "Brazil", "BR", "BR", "BRA", 76, "BR" },
{ "Americas", "West Indies", "British Virgin Islands", "VI", "VG", "VGB", 92, "VG" },
{ "Asia", "South East Asia", "Brunei", "BX", "BN", "BRN", 96, "BN" },
{ "Europe", "South East Europe", "Bulgaria", "BU", "BG", "BGR", 100, "BG" },
{ "Africa", "Western Africa", "Burkina Faso", "UV", "BF", "BFA", 854, "BF" },
{ "Africa", "Central Africa", "Burundi", "BY", "BI", "BDI", 108, "BI" },
{ "Asia", "South East Asia", "Cambodia", "CB", "KH", "KHM", 116, "KH" },
{ "Africa", "Western Africa", "Cameroon", "CM", "CM", "CMR", 120, "CM" },
{ "Americas", "North America", "Canada", "CA", "CA", "CAN", 124, "CA" },
{ "Africa", "Western Africa", "Cape Verde", "CV", "CV", "CPV", 132, "CV" },
{ "Americas", "West Indies", "Cayman Islands", "CJ", "KY", "CYM", 136, "KY" },
{ "Africa", "Central Africa", "Central African Republic", "CT", "CF", "CAF", 140, "CF" },
{ "Africa", "Central Africa", "Chad", "CD", "TD", "TCD", 148, "TD" },
{ "Americas", "South America", "Chile", "CI", "CL", "CHL", 152, "CL" },
{ "Asia", "East Asia", "China", "CH", "CN", "CHN", 156, "CN" },
{ "Asia", "South East Asia", "Christmas Island", "KT", "CX", "CXR", 162, "CX" },
{ "Asia", "South East Asia", "Cocos (Keeling) Islands", "CK", "CC", "CCK", 166, "CC" },
{ "Americas", "South America", "Colombia", "CO", "CO", "COL", 170, "CO" },
{ "Africa", "Indian Ocean", "Comoros", "CN", "KM", "COM", 174, "KM" },
{ "Africa", "Central Africa", "Congo, Republic of the", "CF", "CG", "COG", 178, "CG" },
{ "Oceania", "Pacific", "Cook Islands", "CW", "CK", "COK", 184, "CK" },
{ "Americas", "Central America", "Costa Rica", "CS", "CR", "CRI", 188, "CR" },
{ "Africa", "Western Africa", "Cote d'Ivoire", "IV", "CI", "CIV", 384, "CI" },
{ "Europe", "South East Europe", "Croatia", "HR", "HR", "HRV", 191, "HR" },
{ "Americas", "West Indies", "Cuba", "CU", "CU", "CUB", 192, "CU" },
{ "Asia", "South West Asia", "Cyprus", "CY", "CY", "CYP", 196, "CY" },
{ "Europe", "Central Europe", "Czech Republic", "EZ", "CZ", "CZE", 203, "CZ" },
{ "Europe", "Northern Europe", "Denmark", "DA", "DK", "DNK", 208, "DK" },
{ "Africa", "Eastern Africa", "Djibouti", "DJ", "DJ", "DJI", 262, "DJ" },
{ "Americas", "West Indies", "Dominica", "DO", "DM", "DMA", 212, "DM" },
{ "Americas", "West Indies", "Dominican Republic", "DR", "DO", "DOM", 214, "DO" },
{ "Americas", "South America", "Ecuador", "EC", "EC", "ECU", 218, "EC" },
{ "Africa", "Northern Africa", "Egypt", "EG", "EG", "EGY", 818, "EG" },
{ "Americas", "Central America", "El Salvador", "ES", "SV", "SLV", 222, "SV" },
{ "Africa", "Western Africa", "Equatorial Guinea", "EK", "GQ", "GNQ", 226, "GQ" },
{ "Africa", "Eastern Africa", "Eritrea", "ER", "ER", "ERI", 232, "ER" },
{ "Europe", "Eastern Europe", "Estonia", "EN", "EE", "EST", 233, "EE" },
{ "Africa", "Eastern Africa", "Ethiopia", "ET", "ET", "ETH", 231, "ET" },
{ "Americas", "South America", "Falkland Islands (Islas Malvinas)", "FA", "FK", "FLK", 238, "FK" },
{ "Europe", "Northern Europe", "Faroe Islands", "FO", "FO", "FRO", 234, "FO" },
{ "Oceania", "Pacific", "Fiji", "FJ", "FJ", "FJI", 242, "FJ" },
{ "Europe", "Northern Europe", "Finland", "FI", "FI", "FIN", 246, "FI" },
{ "Europe", "Western Europe", "France", "FR", "FR", "FRA", 250, "FR" },
{ "Americas", "South America", "French Guiana", "FG", "GF", "GUF", 254, "GF" },
{ "Oceania", "Pacific", "French Polynesia", "FP", "PF", "PYF", 258, "PF" },
{ "Africa", "Western Africa", "Gabon", "GB", "GA", "GAB", 266, "GA" },
{ "Africa", "Western Africa", "Gambia, The", "GA", "GM", "GMB", 270, "GM" },
{ "Asia", "South West Asia", "Georgia", "GG", "GE", "GEO", 268, "GE" },
{ "Europe", "Western Europe", "Germany", "GM", "DE", "DEU", 276, "DE" },
{ "Africa", "Western Africa", "Ghana", "GH", "GH", "GHA", 288, "GH" },
{ "Europe", "South West Europe", "Gibraltar", "GI", "GI", "GIB", 292, "GI" },
{ "Europe", "South East Europe", "Greece", "GR", "GR", "GRC", 300, "GR" },
{ "Americas", "North America", "Greenland", "GL", "GL", "GRL", 304, "GL" },
{ "Americas", "West Indies", "Grenada", "GJ", "GD", "GRD", 308, "GD" },
{ "Americas", "West Indies", "Guadeloupe", "GP", "GP", "GLP", 312, "GP" },
{ "Oceania", "Pacific", "Guam", "GQ", "GU", "GUM", 316, "GU" },
{ "Americas", "Central America", "Guatemala", "GT", "GT", "GTM", 320, "GT" },
{ "Europe", "Western Europe", "Guernsey", "--", "--", "--", 0, "--" },
{ "Africa", "Western Africa", "Guinea", "GV", "GN", "GIN", 324, "GN" },
{ "Africa", "Western Africa", "Guinea-Bissau", "PU", "GW", "GNB", 624, "GW" },
{ "Americas", "South America", "Guyana", "GY", "GY", "GUY", 328, "GY" },
{ "Americas", "West Indies", "Haiti", "HA", "HT", "HTI", 332, "HT" },
{ "Europe", "Southern Europe", "Holy See (Vatican City)", "VT", "VA", "VAT", 336, "VA" },
{ "Americas", "Central America", "Honduras", "HO", "HN", "HND", 340, "HN" },
{ "Europe", "Central Europe", "Hungary", "HU", "HU", "HUN", 348, "HU" },
{ "Europe", "Northern Europe", "Iceland", "IC", "IS", "ISL", 352, "IS" },
{ "Asia", "South Asia", "India", "IN", "IN", "IND", 356, "IN" },
{ "Asia", "South East Asia", "Indonesia", "ID", "ID", "IDN", 360, "ID" },
{ "Asia", "South West Asia", "Iran", "IR", "IR", "IRN", 364, "IR" },
{ "Asia", "South West Asia", "Iraq", "IZ", "IQ", "IRQ", 368, "IQ" },
{ "Europe", "Western Europe", "Ireland", "EI", "IE", "IRL", 372, "IE" },
{ "Asia", "South West Asia", "Israel", "IS", "IL", "ISR", 376, "IL" },
{ "Europe", "Southern Europe", "Italy", "IT", "IT", "ITA", 380, "IT" },
{ "Americas", "West Indies", "Jamaica", "JM", "JM", "JAM", 388, "JM" },
{ "Europe", "Northern Europe", "Jan Mayen", "--", "--", "--", 0, "--" },
{ "Asia", "East Asia", "Japan", "JA", "JP", "JPN", 392, "JP" },
{ "Europe", "Western Europe", "Jersey", "--", "--", "--", 0, "--" },
{ "Asia", "South West Asia", "Jordan", "JO", "JO", "JOR", 400, "JO" },
{ "Asia", "Central Asia", "Kazakhstan", "KZ", "KZ", "KAZ", 398, "KZ" },
{ "Africa", "Eastern Africa", "Kenya", "KE", "KE", "KEN", 404, "KE" },
{ "Oceania", "Pacific", "Kiribati", "KR", "KI", "KIR", 296, "KI" },
{ "Asia", "East Asia", "Korea, North", "KN", "KP", "PRK", 408, "KP" },
{ "Asia", "East Asia", "Korea, South", "KS", "KR", "KOR", 410, "KR" },
{ "Asia", "South West Asia", "Kuwait", "KU", "KW", "KWT", 414, "KW" },
{ "Asia", "Central Asia", "Kyrgyzstan", "KG", "KG", "KGZ", 417, "KG" },
{ "Asia", "South East Asia", "Laos", "LA", "LA", "LAO", 418, "LA" },
{ "Europe", "Eastern Europe", "Latvia", "LG", "LV", "LVA", 428, "LV" },
{ "Asia", "South West Asia", "Lebanon", "LE", "LB", "LBN", 422, "LB" },
{ "Africa", "Southern Africa", "Lesotho", "LT", "LS", "LSO", 426, "LS" },
{ "Africa", "Western Africa", "Liberia", "LI", "LR", "LBR", 430, "LR" },
{ "Africa", "Northern Africa", "Libya", "LY", "LY", "LBY", 434, "LY" },
{ "Europe", "Central Europe", "Liechtenstein", "LS", "LI", "LIE", 438, "LI" },
{ "Europe", "Eastern Europe", "Lithuania", "LH", "LT", "LTU", 440, "LT" },
{ "Europe", "Western Europe", "Luxembourg", "LU", "LU", "LUX", 442, "LU" },
{ "Europe", "South East Europe", "Macedonia", "MK", "MK", "MKD", 807, "MK" },
{ "Africa", "Indian Ocean", "Madagascar", "MA", "MG", "MDG", 450, "MG" },
{ "Africa", "Southern Africa", "Malawi", "MI", "MW", "MWI", 454, "MW" },
{ "Asia", "South East Asia", "Malaysia", "MY", "MY", "MYS", 458, "MY" },
{ "Asia", "South Asia", "Maldives", "MV", "MV", "MDV", 462, "MV" },
{ "Africa", "Western Africa", "Mali", "ML", "ML", "MLI", 466, "ML" },
{ "Europe", "Southern Europe", "Malta", "MT", "MT", "MLT", 470, "MT" },
{ "Europe", "Western Europe", "Man, Isle of", "--", "--", "--", 0, "--" },
{ "Oceania", "Pacific", "Marshall Islands", "RM", "MH", "MHL", 584, "MH" },
{ "Americas", "West Indies", "Martinique", "MB", "MQ", "MTQ", 474, "MQ" },
{ "Africa", "Western Africa", "Mauritania", "MR", "MR", "MRT", 478, "MR" },
{ "Africa", "Indian Ocean", "Mauritius", "MP", "MU", "MUS", 480, "MU" },
{ "Africa", "Indian Ocean", "Mayotte", "MF", "YT", "MYT", 175, "YT" },
{ "Americas", "Central America", "Mexico", "MX", "MX", "MEX", 484, "MX" },
{ "Oceania", "Pacific", "Micronesia, Federated States of", "FM", "FSM", "583", 0, "--" },
{ "Europe", "Eastern Europe", "Moldova", "MD", "MD", "MDA", 498, "MD" },
{ "Europe", "Western Europe", "Monaco", "MN", "MC", "MCO", 492, "MC" },
{ "Asia", "Northern Asia", "Mongolia", "MG", "MN", "MNG", 496, "MN" },
{ "Americas", "West Indies", "Montserrat", "MH", "MS", "MSR", 500, "MS" },
{ "Africa", "Northern Africa", "Morocco", "MO", "MA", "MAR", 504, "MA" },
{ "Africa", "Southern Africa", "Mozambique", "MZ", "MZ", "MOZ", 508, "MZ" },
{ "Asia", "South East Asia", "Myanmar (Burma)", "BM", "MM", "MMR", 104, "MM" },
{ "Africa", "Southern Africa", "Namibia", "WA", "NA", "NAM", 516, "NA" },
{ "Oceania", "Pacific", "Nauru", "NR", "NR", "NRU", 520, "NR" },
{ "Asia", "South Asia", "Nepal", "NP", "NP", "NPL", 524, "NP" },
{ "Europe", "Western Europe", "Netherlands", "NL", "NL", "NLD", 528, "NL" },
{ "Americas", "West Indies", "Netherlands Antilles", "NT", "AN", "ANT", 530, "AN" },
{ "Oceania", "Pacific", "New Caledonia", "NC", "NC", "NCL", 540, "NC" },
{ "Oceania", "Pacific", "New Zealand", "NZ", "NZ", "NZL", 554, "NZ" },
{ "Americas", "Central America", "Nicaragua", "NU", "NI", "NIC", 558, "NI" },
{ "Africa", "Western Africa", "Niger", "NG", "NE", "NER", 562, "NE" },
{ "Africa", "Western Africa", "Nigeria", "NI", "NG", "NGA", 566, "NG" },
{ "Oceania", "Pacific", "Niue", "NE", "NU", "NIU", 570, "NU" },
{ "Oceania", "Pacific", "Norfolk Island", "NF", "NF", "NFK", 574, "NF" },
{ "Oceania", "Pacific", "Northern Mariana Islands", "CQ", "MP", "MNP", 580, "MP" },
{ "Europe", "Northern Europe", "Norway", "NO", "NO", "NOR", 578, "NO" },
{ "Asia", "South West Asia", "Oman", "MU", "OM", "OMN", 512, "OM" },
{ "Asia", "South Asia", "Pakistan", "PK", "PK", "PAK", 586, "PK" },
{ "Oceania", "Pacific", "Palau", "PS", "PW", "PLW", 585, "PW" },
{ "Asia", "South West Asia", "Palestine", "--", "--", "--", 0, "--" },
{ "Americas", "Central America", "Panama", "PM", "PA", "PAN", 591, "PA" },
{ "Oceania", "Pacific", "Papua New Guinea", "PP", "PG", "PNG", 598, "PG" },
{ "Americas", "South America", "Paraguay", "PA", "PY", "PRY", 600, "PY" },
{ "Americas", "South America", "Peru", "PE", "PE", "PER", 604, "PE" },
{ "Asia", "South East Asia", "Philippines", "RP", "PH", "PHL", 608, "PH" },
{ "Oceania", "Pacific", "Pitcairn Islands", "PC", "PN", "PCN", 612, "PN" },
{ "Europe", "Eastern Europe", "Poland", "PL", "PL", "POL", 616, "PL" },
{ "Europe", "South West Europe", "Portugal", "PO", "PT", "PRT", 620, "PT" },
{ "Americas", "West Indies", "Puerto Rico", "RQ", "PR", "PRI", 630, "PR" },
{ "Asia", "South West Asia", "Qatar", "QA", "QA", "QAT", 634, "QA" },
{ "Africa", "Indian Ocean", "Reunion", "RE", "RE", "REU", 638, "RE" },
{ "Europe", "South East Europe", "Romania", "RO", "RO", "ROM", 642, "RO" },
{ "Asia", "Northern Asia", "Russia", "RS", "RU", "RUS", 643, "RU" },
{ "Africa", "Central Africa", "Rwanda", "RW", "RW", "RWA", 646, "RW" },
{ "Americas", "West Indies", "Saint Kitts and Nevis", "SC", "KN", "KNA", 659, "KN" },
{ "Americas", "West Indies", "Saint Lucia", "ST", "LC", "LCA", 662, "LC" },
{ "Americas", "North America", "Saint Pierre and Miquelon", "SB", "PM", "SPM", 666, "PM" },
{ "Americas", "West Indies", "Saint Vincent and the Grenadines", "VC", "VC", "VCT", 670, "VC" },
{ "Europe", "Southern Europe", "San Marino", "SM", "SM", "SMR", 674, "SM" },
{ "Africa", "Western Africa", "Sao Tome and Principe", "TP", "ST", "STP", 678, "ST" },
{ "Asia", "South West Asia", "Saudi Arabia", "SA", "SA", "SAU", 682, "SA" },
{ "Africa", "Western Africa", "Senegal", "SG", "SN", "SEN", 686, "SN" },
{ "Europe", "South East Europe", "Serbia and Montenegro", "SR", "--", "--", 0, "--" },
{ "Africa", "Indian Ocean", "Seychelles", "SE", "SC", "SYC", 690, "SC" },
{ "Africa", "Western Africa", "Sierra Leone", "SL", "SL", "SLE", 694, "SL" },
{ "Asia", "South East Asia", "Singapore", "SN", "SG", "SGP", 702, "SG" },
{ "Europe", "Central Europe", "Slovakia", "LO", "SK", "SVK", 703, "SK" },
{ "Europe", "South East Europe", "Slovenia", "SI", "SI", "SVN", 705, "SI" },
{ "Oceania", "Pacific", "Solomon Islands", "BP", "SB", "SLB", 90, "SB" },
{ "Africa", "Eastern Africa", "Somalia", "SO", "SO", "SOM", 706, "SO" },
{ "Africa", "Southern Africa", "South Africa", "SF", "ZA", "ZAF", 710, "ZA" },
{ "Europe", "South West Europe", "Spain", "SP", "ES", "ESP", 724, "ES" },
{ "Asia", "South Asia", "Sri Lanka", "CE", "LK", "LKA", 144, "LK" },
{ "Africa", "Northern Africa", "Sudan", "SU", "SD", "SDN", 736, "SD" },
{ "Americas", "South America", "Suriname", "NS", "SR", "SUR", 740, "SR" },
{ "Europe", "Northern Europe", "Svalbard", "SV", "SJ", "SJM", 744, "SJ" },
{ "Africa", "Southern Africa", "Swaziland", "WZ", "SZ", "SWZ", 748, "SZ" },
{ "Europe", "Northern Europe", "Sweden", "SW", "SE", "SWE", 752, "SE" },
{ "Europe", "Central Europe", "Switzerland", "SZ", "CH", "CHE", 756, "CH" },
{ "Asia", "South West Asia", "Syria", "SY", "SY", "SYR", 760, "SY" },
{ "Asia", "East Asia", "Taiwan", "TW", "TW", "TWN", 158, "TW" },
{ "Asia", "Central Asia", "Tajikistan", "TI", "TJ", "TJK", 762, "TJ" },
{ "Africa", "Eastern Africa", "Tanzania", "TZ", "TZ", "TZA", 834, "TZ" },
{ "Asia", "South East Asia", "Thailand", "TH", "TH", "THA", 764, "TH" },
{ "Africa", "Western Africa", "Togo", "TO", "TG", "TGO", 768, "TG" },
{ "Oceania", "Pacific", "Tokelau", "TL", "TK", "TKL", 772, "TK" },
{ "Oceania", "Pacific", "Tonga", "TN", "TO", "TON", 776, "TO" },
{ "Americas", "West Indies", "Trinidad and Tobago", "TD", "TT", "TTO", 780, "TT" },
{ "Africa", "Northern Africa", "Tunisia", "TS", "TN", "TUN", 788, "TN" },
{ "Asia", "South West Asia", "Turkey", "TU", "TR", "TUR", 792, "TR" },
{ "Asia", "Central Asia", "Turkmenistan", "TX", "TM", "TKM", 795, "TM" },
{ "Americas", "West Indies", "Turks and Caicos Islands", "TK", "TC", "TCA", 796, "TC" },
{ "Oceania", "Pacific", "Tuvalu", "TV", "TV", "TUV", 798, "TV" },
{ "Africa", "Eastern Africa", "Uganda", "UG", "UG", "UGA", 800, "UG" },
{ "Europe", "Eastern Europe", "Ukraine", "UP", "UA", "UKR", 804, "UA" },
{ "Asia", "South West Asia", "United Arab Emirates", "TC", "AE", "ARE", 784, "AE" },
{ "Europe", "Western Europe", "United Kingdom", "UK", "GB", "GBR", 826, "UK/GB" },
{ "Americas", "North America", "United States", "US", "US", "USA", 840, "US" },
{ "Americas", "South America", "Uruguay", "UY", "UY", "URY", 858, "UY" },
{ "Asia", "Central Asia", "Uzbekistan", "UZ", "UZ", "UZB", 860, "UZ" },
{ "Oceania", "Pacific", "Vanuatu", "NH", "VU", "VUT", 548, "VU" },
{ "Americas", "South America", "Venezuela", "VE", "VE", "VEN", 862, "UE" },
{ "Asia", "South East Asia", "Vietnam", "VM", "VN", "VNM", 704, "VN" },
{ "Americas", "West Indies", "Virgin Islands", "VQ", "VI", "VIR", 850, "VI" },
{ "Oceania", "Pacific", "Wallis and Futuna", "WF", "WF", "WLF", 876, "WF" },
{ "Africa", "Northern Africa", "Western Sahara", "WI", "EH", "ESH", 732, "EH" },
{ "Oceania", "Pacific", "Western Samoa", "WS", "WS", "WSM", 882, "WS" },
{ "Asia", "South West Asia", "Yemen", "YM", "YE", "YEM", 887, "YE" },
{ "Africa", "Central Africa", "Zaire (Dem Rep of Congo)", "CG", "ZR", "ZAR", 180, "ZR" },
{ "Africa", "Southern Africa", "Zambia", "ZA", "ZM", "ZWB", 894, "ZM" },
{ "Africa", "Southern Africa", "Zimbabwe", "ZI", "ZW", "ZWE", 716, "ZW" },
{ 0, 0, 0, 0, 0, 0, -1, 0 }
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
const Info *GetFIPSCountry(const char *fips)
{
for (int n = 0; countries[n].iso != -1; ++n)
if (countries[n].fips == fips)
return &countries[n];
return NULL;
}
const Info *GetISO2Country(const char *iso)
{
for (int n = 0; countries[n].iso != -1; ++n)
if (countries[n].iso2 == iso)
return &countries[n];
return NULL;
}
const Info *GetISO3Country(const char *iso)
{
for (int n = 0; countries[n].iso != -1; ++n)
if (countries[n].iso3 == iso)
return &countries[n];
return NULL;
}
const Info *GetISOCountry(int iso)
{
for (int n = 0; countries[n].iso != -1; ++n)
if (countries[n].iso == iso)
return &countries[n];
return NULL;
}
//------------------------------------------------------------------------------
} // Locale
} // GS

View File

@ -0,0 +1,39 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <stdio.h>
#include "log/file_log.h"
#include "filesystem/filesystem.h"
#include "platform.h"
using namespace GS;
//------------------------------------------------------------------------------
void FileLog::NewLog(const char *log, char entry_level)
{
if (FILE *f = fopen(path, initial_write ? "w" : "a"))
{
initial_write = false;
if (do_timestamp)
{
String timestamp = Platform::Get().GetTime().toString() + ": ";
fwrite(timestamp.c_str(), 1, timestamp.Len(), f);
}
fwrite(log, 1, String::strlen(log), f);
fclose(f);
}
}
FileLog::FileLog(const char *_path, bool _do_timestamp) : path(_path), do_timestamp(_do_timestamp)
{
initial_write = true;
FILE *f = fopen(path, "w");
if(f)
fclose(f);
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,160 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <cstdio>
#include <cstring>
#include <iostream>
#include "log/log.h"
#include "nstring/nstring.h"
#include "thread/mutex.h"
#include "platform_config.h"
#include "alloc/ialloc.h"
using namespace GS;
template<> LogSystem *Singleton <LogSystem> ::i = NULL;
//------------------------------------------------------------------------------
LogSystem::LogSystem()
{ SetLog(); }
void LogSystem::SetLog(Log *l)
{
static Log s_log;
log = l ? l : &s_log;
}
Log &LogSystem::GetLog()
{ return *log; }
//------------------------------------------------------------------------------
#if __PLATFORM_LOG_SUPPORT__
//------------------------------------------------------------------------------
void Log::NewLog(const char *log, char)
{
// std::cout << log;
}
void Log::LogProcessed()
{
full_a[0] = 0;
full_b[0] = 0;
}
//------------------------------------------------------------------------------
#define _FORMAT_LOG(__F__, __V__) \
{\
Threading::MutexLock lock(mutex);\
if (a)\
{\
_snprintf(b, LOG_LINE_MAX_LEN - 1, __F__, a, __V__);\
char *swp = a; a = b; b = swp;\
}\
return *this;\
}
//------------------------------------------------------------------------------
Log &Log::operator << (const char v)
{ _FORMAT_LOG("%s%d", v) }
Log &Log::operator << (const short v)
{ _FORMAT_LOG("%s%d", v) }
Log &Log::operator << (const int v)
{ _FORMAT_LOG("%s%d", v) }
Log &Log::operator << (const uchar v)
{ _FORMAT_LOG("%s%d", v) }
Log &Log::operator << (const ushort v)
{ _FORMAT_LOG("%s%d", v) }
Log &Log::operator << (const uint v)
{ _FORMAT_LOG("%s%d", (int)v) }
Log &Log::operator << (const size_t v)
{ _FORMAT_LOG("%s%d", v) }
Log &Log::operator << (const float v)
{ _FORMAT_LOG("%s%.3f", v) }
Log &Log::operator << (const bool v)
{ _FORMAT_LOG("%s%s", v ? "True" : "False") }
Log &Log::operator << (const void *v)
{ _FORMAT_LOG("%s0x%p", v) }
Log &Log::operator << (const char *v)
{
if (a && v)
{
Threading::MutexLock lock(mutex);
_snprintf(b, LOG_LINE_MAX_LEN - 1, "%s%s", a, v);
char *swp = a; a = b; b = swp;
// Look out for ENDL.
for (const char *p = v; p[0]; ++p)
if (p[0] == '\n')
{
// Compute entry level.
char entry_level = EngineLogStandard;
if ((std::strlen(a) >= 3) && (a[0] == '[') && (a[2] == ']'))
switch (a[1])
{
case '*': entry_level |= EngineLogWarning; break;
case '!': entry_level |= EngineLogError; break;
case 'H': entry_level |= EngineLogHeader; break;
case 'V': entry_level |= EngineLogVerbose; break;
case 'S': entry_level |= EngineLogScript; break;
}
// Process output.
if (entry_level & log_level)
NewLog(a, entry_level);
LogProcessed();
}
}
return *this;
}
Log &Log::operator << (const String &v)
{ return *this << v.toUtf8(); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Log::Log()
{
LogProcessed();
a = full_a;
b = full_b;
log_level = (uint)EngineLogAll;
mutex = new Threading::Mutex;
}
Log::~Log()
{
_safe_delete(mutex);
}
//------------------------------------------------------------------------------
#else
//------------------------------------------------------------------------------
void Log::NewLog(const char *, char) {}
void Log::LogProcessed() {}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Log &Log::operator << (const char) { return *this; }
Log &Log::operator << (const short) { return *this; }
Log &Log::operator << (const int) { return *this; }
Log &Log::operator << (const uchar) { return *this; }
Log &Log::operator << (const ushort) { return *this; }
Log &Log::operator << (const uint) { return *this; }
Log &Log::operator << (const size_t) { return *this; }
Log &Log::operator << (const float) { return *this; }
Log &Log::operator << (const bool) { return *this; }
Log &Log::operator << (const char *) { return *this; }
Log &Log::operator << (const String &) { return *this; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Log::Log() {}
Log::~Log() {}
//------------------------------------------------------------------------------
#endif

View File

@ -34,7 +34,7 @@ namespace GS {
* __LOG_H__: Header (eg: __LOG_H__ << "Physics entry point.\n")
* __LOG_W__: Warning
* __LOG_E__: Error
* __LOG_E__: Non-maskable
* __LOG_N__: Non-maskable
Standard logs may be output to the __LOG__ stream.
@ -81,9 +81,9 @@ public:
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 *);
@ -117,7 +117,6 @@ public:
//------------------------------------------------------------------------------
#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
@ -126,6 +125,8 @@ public:
#define __LOG_E__ __LOG__ << "[!] "
#endif
#define __LOG_V__ __LOG__ << "[V] " // Verbose
#define __LOG_SENS__ __LOG__ << "[REALSENSE] " // Verbose
#define __LOG_CAM__ __LOG__ << "[WEBCAM] " // Verbose
#define __LOG_F__ __LOG__ << __FUNCTION__ << ": "
#define __LOG_FUNC__ __LOG_V__ << __FUNCTION__ << "\n";

View File

@ -0,0 +1,18 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "log/log_scope.h"
#include "log/log.h"
using namespace GS;
//------------------------------------------------------------------------------
LogScope::LogScope(const char *s, const char *e) : exit(e)
{ __LOG_H__ << s; }
LogScope::~LogScope()
{ __LOG_H__ << exit; }
//------------------------------------------------------------------------------

View File

@ -0,0 +1,127 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <cmath>
#include <cfloat>
#include "math/nmath.h"
using namespace GS;
//------------------------------------------------------------------------------
Math::rOrder Math::ReverserRotationOrder(rOrder r)
{
switch (r)
{
case rOrder_ZYX: return rOrder_XYZ;
case rOrder_YZX: return rOrder_XZY;
case rOrder_ZXY: return rOrder_YXZ;
case rOrder_XZY: return rOrder_YZX;
case rOrder_YXZ: return rOrder_ZXY;
case rOrder_XYZ: return rOrder_ZYX;
default: return rOrder_Default;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
float Math::Sqrt(float v)
{ return sqrtf(v); }
float Math::TestEqual(float a, float b, float e)
{ return Types::Abs(b - a) < e ? true : false; }
bool Math::EqualZero(float v, float e)
{ return (v < -e) || (v > e) ? false : true; }
float Math::Pow(float v, float e)
{ return pow(v, e); }
float Math::Ceil(float v)
{ return (v < 0) ? (float)((int)v) : (float)((int)(v + 1)); }
float Math::Floor(float v)
{ return (v < 0) ? (float)((int)(v - 1)) : (float)((int)v); }
float Math::Mod(float v)
{
double integral;
return (float)modf(v, &integral);
}
float Math::RangeAdjust(float v, float old_min, float old_max, float new_min, float new_max)
{ return Types::Clamp((v - old_min) / (old_max - old_min) * (new_max - new_min) + new_min, new_min, new_max); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Math::IsFinite(float v) { return (v <= FLT_MAX && v >= -FLT_MAX); }
//------------------------------------------------------------------------------
#define __USE_LUT_BASED_TRIG__ 0
#if (__USE_LUT_BASED_TRIG__ == 0)
void Math::Init() {}
//------------------------------------------------------------------------------
float Math::Quantize(float v, float q) { return Floor(v / q) * q; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
float Math::Sin(float v) { return sin(v); }
float Math::ASin(float v) { return asin(Types::Clamp(v, -1.f, 1.f)); }
float Math::Cos(float v) { return cos(v); }
float Math::ACos(float v) { return acos(Types::Clamp(v, -1.f, 1.f)); }
float Math::Tan(float v) { return tan(v); }
float Math::ATan(float v) { return atan(v); }
//------------------------------------------------------------------------------
#else
#include "container/narray.h"
// keep as power of 2
#define __LUT_PRECISION 64
static nArray <float> lCos, lSin, lTan, lACos, lASin, lAtan;
//------------------------------------------------------------------------------
void Math::Init()
{
lCos.Allocate(__LUT_PRECISION);
lSin.Allocate(__LUT_PRECISION);
lTan.Allocate(__LUT_PRECISION);
lACos.Allocate(__LUT_PRECISION);
lASin.Allocate(__LUT_PRECISION);
for (int v = 0; v < __LUT_PRECISION; ++v)
{
const float deg = ((float)v / __LUT_PRECISION) * (Pi * 2.f);
lSin[v] = sin(deg);
lCos[v] = cos(deg);
lTan[v] = tan(deg);
const float inv = ((float)v / __LUT_PRECISION) * 2.f - 1.f;
lASin[v] = asin(inv);
lACos[v] = acos(inv);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
float Math::Sin(float v)
{ return lSin[int(v * (__LUT_PRECISION / (Pi * 2.f))) & (__LUT_PRECISION - 1)]; }
float Math::ASin(float v)
{ return lASin[int((v + 1.f) * (__LUT_PRECISION / 2)) & (__LUT_PRECISION - 1)]; }
float Math::Cos(float v)
{ return lCos[int(v * (__LUT_PRECISION / (Pi * 2.f))) & (__LUT_PRECISION - 1)]; }
float Math::ACos(float v)
{ return lACos[int((v + 1.f) * (__LUT_PRECISION / 2)) & (__LUT_PRECISION - 1)]; }
float Math::Tan(float v)
{ return lTan[int(v * (__LUT_PRECISION / (Pi * 2.f))) & (__LUT_PRECISION - 1)]; }
float Math::ATan(float v)
{ return atan(v); }
//------------------------------------------------------------------------------
#endif

View File

@ -0,0 +1,63 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "memory/endian.h"
#include "platform_config.h"
#include "log/log.h"
namespace GS {
namespace Endian {
static Config g_host_endian = Undefined;
//------------------------------------------------------------------------------
void SwapBytes(void *in_p, size_t n)
{
if (n == 1)
return;
__ASSERT__(!(n & 1));
char *p = (char *)in_p;
for (size_t c = 0; c < n / 2; ++c)
{
char tmp = p[c];
p[c] = p[n - c - 1];
p[n - c - 1] = tmp;
}
}
Config GetHostConfiguration()
{
if (g_host_endian == Undefined)
{
union
{
uint i;
char c[4];
} bint = { 0x01020304 };
g_host_endian = bint.c[0] == 1 ? Big : Little;
if (g_host_endian == Big)
__LOG__ << "Memory configuration: Big endian.\n";
else __LOG__ << "Memory configuration: Little endian.\n";
}
return g_host_endian;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void *ToHost(void *p, size_t size, Config source_endian)
{
if (GetHostConfiguration() != source_endian)
SwapBytes(p, size);
return p;
}
//------------------------------------------------------------------------------
}
}

View File

@ -0,0 +1,116 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <string.h>
#include "memory/memory.h"
using namespace GS;
//------------------------------------------------------------------------------
uchar Memory::GetBitCount(int v)
{
uchar n;
for (n = 0; v; ++n)
v &= (v - 1);
return n;
}
uchar Memory::GetShiftCount(int v)
{
uchar n;
for (n = 0; !(v & 1) && (n < 32); ++n)
v >>= 1;
return n;
}
uchar Memory::CountSetBit(int v)
{
uchar count = 0;
for (int n = 0; n < 32; ++n)
{
count += v & 1;
v >>= 1;
}
return count;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Memory::WriteBit(uchar *mem , uint bitoffset, uint bitcount, uint v)
{
mem += bitoffset >> 3;
bitoffset &= 7;
while (bitcount--)
{
mem[0] |= ((v >> bitcount) & 1) << bitoffset;
if (bitoffset == 7)
{
bitoffset = 0;
mem++;
}
else
++bitoffset;
}
}
uint Memory::ReadBit(uchar *base, uint offsetbit, uint nbit)
{
base += offsetbit >> 3;
offsetbit &= 7;
uint v = 0;
while (nbit--)
{
v += v;
if (base[0] & (1 << offsetbit))
v |= 1;
if (offsetbit == 7) {offsetbit = 0; base++;} else offsetbit++;
}
return v;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Memory::Compare(const void *a, const void *b, size_t n)
{
if (!a || !b)
return true;
// 8 bit padding.
uchar *ba = (uchar *)a, *bb = (uchar *)b;
for (uint c = n & 3; c; --c)
if (*ba++ != *bb++)
return true;
// 32 bit compare.
uint *la = (uint *)ba, *lb = (uint *)bb;
for (uint l = n >> 2; l; --l)
if (*la++ != *lb++)
return true;
return false;
}
void Memory::Copy(void *d, const void *s, size_t n)
{ memcpy(d, s, n); }
void Memory::Set(void *a, char v, size_t s)
{ memset(a, v, s); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Memory::Fill(void *p, const char *pattern, size_t s)
{
size_t p_l = 0;
for ( ; pattern[p_l] != 0; ++p_l) {}
char *out = (char *)p;
for (; s >= p_l; s -= p_l)
{
Copy((void *)out, pattern, p_l);
out += p_l;
}
Copy((void *)out, pattern, s);
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,22 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "network/network_interface.h"
#include "nstring/nstring.h"
using namespace GS::Network;
//------------------------------------------------------------------------------
bool INetwork::SendString(void *peer, const GS::String &s)
{
return Send(peer, (void *)s.c_str(), (size_t)(s.Len() + 1));
}
bool INetwork::BroadcastString(const GS::String &s)
{
return Broadcast((void *)s.c_str(), (size_t)(s.Len() + 1));
}
//------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "platform.h"
#include "async/job.h"
#include "filesystem/filesystem.h"
#include "filesystem/io_base.h"
#include "input/input_system.h"
#include "licensing/licensing.h"
#include "analytics/analytics.h"
#include "billing/billing.h"
#include "log/file_log.h"
#include "log/log.h"
using namespace GS;
#define __ENABLE_PLATFORM_TRACE 0
template<> Platform *Singleton <Platform> ::i = NULL;
String Platform::app_dir;
static int g_start_clock = 0;
static Time g_start_time;
//------------------------------------------------------------------------------
void Platform::Trace(const char *trace, const char *source, int line)
{
#if __ENABLE_PLATFORM_TRACE
static FileLog platform_trace("c:/platform_trace.log");
platform_trace << trace << "(" << source << "@" << line << ")\n";
#endif
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
String Platform::GetAppPluginPath(const char *plugin) const
{ return ((app_dir + "/") + plugin).CleanFilePath(); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint Types::getPOT(uint v)
{ uint n = 1; for (; n < v; n *= 2) {} return n; }
bool Types::isPOT(uint v)
{ return ((v != 0) && ((v & (~v + 1)) == v)); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int Platform::GetStartClock() const
{ return g_start_clock; }
Time Platform::GetStartTime() const
{ return g_start_time; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Platform::Initialize()
{
if (initialized)
return;
g_start_clock = GetClock();
g_start_time = GetTime();
job_manager->CreateJobThreadPool(Types::Max(GetSystemCoreCount() - 1, 1)); // keep 1 core for the master thread
initialized = true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Platform::Platform() : initialized(false)
{
io = new IO::Filesystem;
job_manager = new ASync::JobManager;
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,69 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "rand/rand.h"
using namespace GS;
#define __USE_CUSTOM_RAND 1
static uint high = 0xDEADBEEF, low = high ^ 0x49616E42;
static uint _rg_pn = 0;
//------------------------------------------------------------------------------
void Random::Seed(uint s)
{
#if __USE_CUSTOM_RAND
high = 0xDEADBEEF;
low = high ^ 0x49616E42;
for (uint n = 0; n < (s & 0x1fff); ++n)
Rand(1);
#else
srand(s);
#endif
}
uint Random::Rand(uint r)
{
if (!r)
return 0;
#if __USE_CUSTOM_RAND
high = (high << 16) + (high >> 16);
high += low;
low += high;
return high % r;
#else
return rand() % r;
#endif
}
float Random::FRand(float r)
{
return (float)Rand(65536) * r / 65536.0f;;
}
float Random::FRRand(float lo, float hi)
{
const float v = (float)(Rand(65536)) / 65536.0f;
return v * (hi - lo) + lo;
}
uint Random::CRand(uint r)
{
uint it;
uint _rg_cn = 0;
if (!r)
return 0;
it = 4;
while (it--)
{
_rg_cn = Rand(r);
if (_rg_cn != _rg_pn)
break;
}
_rg_pn = _rg_cn;
return _rg_cn;
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,2 @@
GS framework core source files.
This project compiles with no other dependency than stdlib.

View File

@ -0,0 +1,29 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "reflection/nenum_string.h"
#include "nstring/nstring.h"
using namespace GS::Reflection;
//------------------------------------------------------------------------------
const char *Enum::toString(int v, Dict *dict)
{
for (int n = 0; dict[n].string_v; ++n)
if (dict[n].enum_v == v)
return dict[n].string_v;
return 0;
}
int Enum::fromString(const char *s, Dict *dict)
{
GS::String string_v(s);
for (int n = 0; dict[n].string_v; ++n)
if (string_v == dict[n].string_v)
return dict[n].enum_v;
return -1;
}
//------------------------------------------------------------------------------

View File

View File

@ -0,0 +1,102 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "thread/atomic_value.h"
#include "assert/nassert.h"
#if __PLATFORM_WINDOWS__
#include <windows.h>
namespace GS {
namespace Threading {
//------------------------------------------------------------------------------
int Atomic32::Inc()
{ return (int)InterlockedIncrement((LONG volatile *)v); }
int Atomic32::Dec()
{ return (int)InterlockedDecrement((LONG volatile *)v); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int Atomic32::Get() const
{ return *((int volatile *)v); }
int Atomic32::Set(int _v)
{ return InterlockedExchange((LONG volatile *)v, _v); }
int Atomic32::Cas(int cmp, int _v)
{ return InterlockedCompareExchange((LONG volatile *)v, _v, cmp); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Atomic32::Atomic32(int _v)
{
v = _aligned_malloc(sizeof(LONG), 4);
__ASSERT__(v != NULL);
Set(_v);
}
Atomic32::~Atomic32()
{ _aligned_free(v); }
//------------------------------------------------------------------------------
}
}
#elif (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)) // use >GCC4.1 builtins
#include <malloc.h>
namespace GS {
namespace Threading {
//------------------------------------------------------------------------------
int Atomic32::Inc()
{ return __sync_fetch_and_add((long volatile *)v, 1) + 1; }
int Atomic32::Dec()
{ return __sync_fetch_and_add((long volatile *)v, -1) - 1; }
int Atomic32::Get() const
{ return *((int volatile *)v); }
int Atomic32::Set(int _v)
{ return __sync_lock_test_and_set((long volatile *)v, _v); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int Atomic32::Cas(int cmp, int _v)
{ return __sync_val_compare_and_swap((long volatile *)v, cmp, _v); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Atomic32::Atomic32(int _v)
{
v = memalign(4, sizeof(long));
__ASSERT__(v != NULL);
*(long *)v = _v;
}
Atomic32::~Atomic32()
{ free(v); }
//------------------------------------------------------------------------------
}
}
#else
namespace GS {
namespace Threading {
//------------------------------------------------------------------------------
int Atomic32::Get() const
{ __ASSERT(true); }
int Atomic32::Set(int _v)
{ __ASSERT(true); }
int Atomic32::Cas(int cmp, int _v)
{ __ASSERT(true); }
//------------------------------------------------------------------------------
}
}
#endif

View File

@ -0,0 +1,90 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "thread/mutex.h"
#include "alloc/ialloc.h"
using namespace GS::Threading;
#if __PLATFORM_WINDOWS__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//------------------------------------------------------------------------------
bool Mutex::TryLock()
{ return asbool(TryEnterCriticalSection((LPCRITICAL_SECTION)mutex)); }
void Mutex::Lock()
{
if (mutex)
EnterCriticalSection((LPCRITICAL_SECTION)mutex);
}
void Mutex::Unlock()
{
if (mutex)
LeaveCriticalSection((LPCRITICAL_SECTION)mutex);
}
Mutex::Mutex()
{
mutex = new CRITICAL_SECTION;
InitializeCriticalSection((LPCRITICAL_SECTION)mutex);
}
Mutex::~Mutex()
{
DeleteCriticalSection((LPCRITICAL_SECTION)mutex);
_safe_delete(mutex);
}
//------------------------------------------------------------------------------
#elif __PLATFORM_POSIX__
#include <errno.h>
//------------------------------------------------------------------------------
bool Mutex::TryLock()
{ return pthread_mutex_trylock(&mutex) != EBUSY ? true : false; }
void Mutex::Lock()
{ pthread_mutex_lock(&mutex); }
void Mutex::Unlock()
{ pthread_mutex_unlock(&mutex); }
Mutex::Mutex()
{ pthread_mutex_init(&mutex, NULL); }
Mutex::~Mutex()
{ pthread_mutex_destroy(&mutex); }
//------------------------------------------------------------------------------
#elif __PLATFORM_NINTENDO_WII__
//------------------------------------------------------------------------------
bool Mutex::TryLock()
{ return OSTryLockMutex(&mutex); }
void Mutex::Lock()
{ OSLockMutex(&mutex); }
void Mutex::Unlock()
{ OSUnlockMutex(&mutex); }
Mutex::Mutex()
{ OSInitMutex(&mutex); }
Mutex::~Mutex()
{}
//------------------------------------------------------------------------------
#else
//------------------------------------------------------------------------------
bool Mutex::TryLock()
{ return true; }
void Mutex::Lock()
{}
void Mutex::Unlock()
{}
Mutex::Mutex()
{}
Mutex::~Mutex()
{}
//------------------------------------------------------------------------------
#endif

View File

@ -0,0 +1,230 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#if __PLATFORM_WINDOWS__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#elif __PLATFORM_POSIX__
#include <pthread.h>
#endif
#include <string.h>
#include "thread/thread.h"
#include "assert/nassert.h"
#include "log/log.h"
#include <processthreadsapi.h>
#include <string>
#if __PLATFORM_WINDOWS__
namespace GS {
namespace Threading {
//------------------------------------------------------------------------------
static unsigned __stdcall win32_thread_entrypoint(void *parm)
{
Thread *t = (Thread *)parm;
__ASSERT__(t != NULL);
t->Execute();
return 1;
}
void Thread::Join()
{
if (handle != 0)
{
WaitForSingleObject((HANDLE)handle, INFINITE);
CloseHandle((HANDLE)handle);
handle = 0;
}
}
bool Thread::Start()
{
handle = (void *)_beginthreadex(NULL, 0, &win32_thread_entrypoint, (void *)this, 0, NULL);
return handle != 0;
}
bool Thread::SetPriority(int)
{
return false;
}
void Thread::Kill()
{
if (handle != 0)
{
CloseHandle((HANDLE)handle);
handle = 0;
}
}
void Thread::SetName(const char *name)
{
if (name == nullptr)
return;
// Conversion UTF-8 (ou ANSI selon votre projet) vers UTF-16
int length = MultiByteToWideChar(CP_UTF8, 0, name, -1, nullptr, 0);
if (length == 0)
return;
std::wstring wname(length, L'\0');
MultiByteToWideChar(CP_UTF8, 0, name, -1, &wname[0], length);
SetThreadDescription(GetCurrentThread(), wname.c_str());
}
void Thread::Switch()
{ SwitchToThread(); }
Thread::Thread()
{ handle = 0; }
Thread::~Thread()
{ Kill(); }
}
}
//------------------------------------------------------------------------------
#elif __PLATFORM_EMSCRIPTEN__
namespace GS {
namespace Threading {
//------------------------------------------------------------------------------
void *pthread_execute(void *parm)
{ return NULL; }
void Thread::Join()
{}
bool Thread::Start()
{ return false; }
bool Thread::SetPriority(int priority)
{ return false; }
void Thread::Kill()
{}
void Thread::SetName(const char *)
{}
void Thread::Switch()
{}
Thread::Thread()
{}
Thread::~Thread()
{}
}
}
//------------------------------------------------------------------------------
#elif __PLATFORM_POSIX__
namespace GS {
namespace Threading {
//------------------------------------------------------------------------------
void *pthread_execute(void *parm)
{
Thread *t = (Thread * const)parm;
t->Execute();
return NULL;
}
void Thread::Join()
{
pthread_join(*((pthread_t *)handle), NULL);
}
bool Thread::Start()
{
if (!(handle = (void *)new pthread_t))
return false;
return pthread_create((pthread_t *)handle, NULL, pthread_execute, this) == 0;
}
bool Thread::SetPriority(int priority)
{
#ifdef EMSCRIPTEN
return false;
#else
if (!handle)
return false;
sched_param param;
memset(&param, 0, sizeof(param));
param.sched_priority = priority;
return asbool(pthread_setschedparam(*((pthread_t *)handle), SCHED_OTHER, &param) == 0);
#endif
}
void Thread::Kill()
{
#if __PLATFORM_ANDROID_NDK__
__ASSERT_MSG__(true, "Android NDK cannot kill a thread.");
#else
if (handle)
pthread_cancel(*((pthread_t *)handle));
delete (pthread_t *)handle;
handle = NULL;
#endif
}
void Thread::SetName(const char *)
{}
void Thread::Switch()
{ sched_yield(); }
Thread::Thread()
{ handle = NULL; }
Thread::~Thread()
{ delete (pthread_t *)handle; }
}
}
//------------------------------------------------------------------------------
#elif __PLATFORM_NINTENDO_WII__
namespace GS {
namespace Threading {
//------------------------------------------------------------------------------
void *__OSthread_wii_execute(void *parm)
{
nThread *t = (nThread * const)parm;
t->alive.Set(1);
return (void *)(t->Execute() ? 1 : 0);
}
void Thread::Join()
{
void *rv;
if (alive.Get())
OSJoinThread(&thread, &rv);
alive.Set(0);
}
void Thread::Resume()
{
if (alive.Get())
OSResumeThread(&thread);
}
void Thread::Suspend()
{
if (alive.Get())
OSSuspendThread(&thread);
}
bool Thread::Start()
{ return OSCreateThread(&thread, &__OSthread_wii_execute, this, thread_stack + 32768, 32768, 20, 0); }
bool Thread::SetPriority(int priority)
{ return alive.Get() ? OSSetThreadPriority(&thread, priority) : false; }
void Thread::Kill()
{
if (alive.Get())
OSCancelThread(&thread);
alive.Set(0);
}
void Thread::SetName(const char *)
{}
Thread::Thread()
{}
Thread::~Thread()
{ Kill(); }
//------------------------------------------------------------------------------
}
}
#endif

View File

@ -0,0 +1,120 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "thread/thread_event.h"
#include "time/ntime.h"
using namespace GS;
using namespace GS::Threading;
#if __PLATFORM_WINDOWS__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//------------------------------------------------------------------------------
void Event::Wait(Time *t)
{ WaitForSingleObject((HANDLE)event, t ? DWORD(t->toMs()) : INFINITE); }
void Event::Trigger()
{ SetEvent((HANDLE)event); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Event::Event()
{ event = (void *)CreateEvent(NULL, false, false, NULL); }
Event::~Event()
{ if (event) CloseHandle(event); }
//------------------------------------------------------------------------------
#elif __PLATFORM_EMSCRIPTEN__
//------------------------------------------------------------------------------
void Event::Wait(Time *t)
{}
void Event::Trigger()
{}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Event::Event()
{}
Event::~Event()
{}
//------------------------------------------------------------------------------
#elif __PLATFORM_POSIX__
#include <errno.h>
#include <pthread.h>
#include <stdbool.h>
#include <sys/time.h>
struct pthread_event
{
pthread_mutex_t mutex;
pthread_cond_t cond;
bool triggered;
};
//------------------------------------------------------------------------------
void Event::Wait(Time *t)
{
pthread_event *ev = (pthread_event *)event;
timespec time;
if (t)
{
timeval ctime;
gettimeofday(&ctime, NULL);
time.tv_sec = t->getSec() + ctime.tv_sec;
time.tv_nsec = t->getNanoSec() + ctime.tv_usec * 1000;
}
pthread_mutex_lock(&ev->mutex);
while (!ev->triggered)
{
if (!t)
pthread_cond_wait(&ev->cond, &ev->mutex);
else
if (pthread_cond_timedwait(&ev->cond, &ev->mutex, &time) == ETIMEDOUT)
break;
}
ev->triggered = false;
pthread_mutex_unlock(&ev->mutex);
}
void Event::Trigger()
{
pthread_event *ev = (pthread_event *)event;
pthread_mutex_lock(&ev->mutex);
ev->triggered = true;
pthread_cond_signal(&ev->cond);
pthread_mutex_unlock(&ev->mutex);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Event::Event()
{
pthread_event *ev = new pthread_event;
event = (void *)ev;
pthread_mutex_init(&ev->mutex, 0);
pthread_cond_init(&ev->cond, 0);
ev->triggered = false;
}
Event::~Event()
{
pthread_event *ev = (pthread_event *)event;
pthread_mutex_destroy(&ev->mutex);
pthread_cond_destroy(&ev->cond);
delete ev;
}
//------------------------------------------------------------------------------
#endif

View File

@ -0,0 +1,125 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <cmath>
#include <limits>
#include "time/ntime.h"
using namespace GS;
Time Time::Inf(std::numeric_limits <int> ::max());
//------------------------------------------------------------------------------
void Time::operator += (const Time &b)
{
sec += b.sec;
nsec += b.nsec;
Normalize();
}
void Time::operator -= (const Time &b)
{
sec -= b.sec;
nsec -= b.nsec;
Normalize();
}
Time Time::operator + (const Time &b) const
{ return Time(sec + b.sec, nsec + b.nsec); }
Time Time::operator - (const Time &b) const
{ return Time(sec - b.sec, nsec - b.nsec); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Time::operator == (const Time &b) const
{ return (sec == b.sec) && (nsec == b.nsec); }
bool Time::operator != (const Time &b) const
{ return (sec != b.sec) || (nsec != b.nsec); }
bool Time::operator > (const Time &b) const
{ return (sec > b.sec) || ((sec == b.sec) && (nsec > b.nsec)); }
bool Time::operator < (const Time &b) const
{ return (sec < b.sec) || ((sec == b.sec) && (nsec < b.nsec)); }
bool Time::operator >= (const Time &b) const
{ return (*this > b) || (*this == b); }
bool Time::operator <= (const Time &b) const
{ return (*this < b) || (*this == b); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
float Time::toDay() const
{ return toHour() / 24.f; }
float Time::toHour() const
{ return toMin() / 60.f; }
float Time::toMin() const
{ return toSec() / 60.f; }
float Time::toSec() const
{ return sec + nsec / 1000000000.f; }
float Time::toMs() const
{ return sec * 1000.f + nsec / 1000000.f; }
float Time::toNs() const
{ return sec * 1000000000.f + nsec; }
String Time::toString() const
{ return String::Format("%02d:%02d:%02d:%03d", int(toHour()) % 60, int(toMin()) % 60, int(toSec()) % 60, int(toMs()) % 1000); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Time::setSec(int s)
{ sec = s; nsec = 0; }
void Time::setSec(float s)
{
double integral, fractional = modf(s, &integral);
sec = int(integral); nsec = int(fractional * 1000000000.0);
Normalize();
}
void Time::setMs(int m)
{
sec = m / 1000; nsec = (m - sec * 1000) * 1000000;
}
void Time::setNs(int n)
{
sec = 0; nsec = n;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Time Time::fromSec(float s)
{
double integral, fractional = modf(s, &integral);
return Time(int(integral), int(fractional * 1000000000.0));
}
Time Time::fromSec(int s)
{ return Time(s); }
Time Time::fromMs(int m)
{ return Time(0, m * 1000000); }
Time Time::fromNs(int n)
{ return Time(0, n); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Time Time::Abs() const
{ return Time(Types::Abs(sec), nsec); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Time::Normalize()
{
for (; nsec >= 1000000000; nsec -= 1000000000)
sec++;
for (; nsec < 0; nsec += 1000000000)
sec--;
}
Time Time::Normalized() const
{ return Time(sec, nsec); }
//------------------------------------------------------------------------------
Time::Time(int s, int n)
{
sec = s; nsec = n;
Normalize();
}
Time::Time(float s)
{ setSec(s); }
Time::Time(int s)
{ sec = s; nsec = 0; }

View File

@ -0,0 +1,15 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "unit/nunit.h"
//------------------------------------------------------------------------------
size_t GS::Units::KB(const size_t v)
{ return v * 1024; }
size_t GS::Units::MB(const size_t v)
{ return v * 1024 * 1024; }
//------------------------------------------------------------------------------

View File

@ -0,0 +1,62 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/
#include "video/video_mode.h"
using namespace nVideoMode;
//------------------------------------------------------------------------------
Mode nVideoMode::mode_desc[NameLast] =
{
{ "CGA", 320, 200, 32, true },
{ "QVGA", 320, 240, 32, true },
{ "WQVGA", 480, 272, 32, true },
{ "VGA", 640, 480, 32, true },
{ "SVGA", 800, 600, 32, true },
{ "XGA", 1024, 768, 32, true },
{ "XGAPlus", 1152, 864, 32, true },
{ "HD", 1366, 768, 32, true },
{ "WXGA_922K", 1280, 720, 32, false },
{ "WXGA_1024K", 1280, 800, 32, true },
{ "HDPlus", 1600, 900, 32, true },
{ "SXGA", 1280, 1024, 32, true },
{ "WXGAPlus", 1440, 900, 32, true },
{ "UXGA", 1600, 1200, 32, true },
{ "WSXGAPlus", 1680, 1050, 32, true },
{ "FullHD", 1920, 1080, 32, false },
{ "WUXGA", 1920, 1200, 32, true },
{ "QXGA", 2048, 1536, 32, true },
{ "QWXGA", 2048, 1152, 32, true },
{ "WQHD", 2560, 1440, 32, true },
{ "WQXGA", 2560, 1600, 32, true }
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
AspectRatio nVideoMode::GetModeAspectRatio(const Mode &mode)
{
if (((mode.width * 3) / 4) == mode.height)
return AR_4_3;
if (((mode.width * 9) / 16) == mode.height)
return AR_16_9;
if (((mode.width * 10) / 16) == mode.height)
return AR_16_10;
return AR_Unknown;
}
Mode *nVideoMode::GetMode(uint w, uint h)
{
for (uint n = 0; n < NameLast; ++n)
if ((mode_desc[n].width == w) && (mode_desc[n].height == h))
return &mode_desc[n];
return NULL;
}
//------------------------------------------------------------------------------