initial commit
This commit is contained in:
87
engine/Utilities/Activated.h
Normal file
87
engine/Utilities/Activated.h
Normal file
@ -0,0 +1,87 @@
|
||||
#ifndef BLUECORE_ACTIVATED_H
|
||||
#define BLUECORE_ACTIVATED_H
|
||||
|
||||
namespace BlueCore
|
||||
{
|
||||
class Activated
|
||||
{
|
||||
private:
|
||||
|
||||
bool _Active;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* inital state is active
|
||||
*/
|
||||
inline Activated()
|
||||
{
|
||||
_Active = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param set inital state
|
||||
*/
|
||||
inline Activated(bool state) :
|
||||
_Active(state )
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual inline ~Activated()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the object.
|
||||
*/
|
||||
inline void activate()
|
||||
{
|
||||
_Active = true;
|
||||
onActivation();
|
||||
}
|
||||
|
||||
virtual void onActivation()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivate the object.
|
||||
*/
|
||||
inline void deactivate()
|
||||
{
|
||||
_Active = false;
|
||||
onDeactivation();
|
||||
}
|
||||
|
||||
virtual void onDeactivation()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* toggles the object's state
|
||||
*/
|
||||
inline void toggleActive()
|
||||
{
|
||||
if (_Active )
|
||||
deactivate();
|
||||
else
|
||||
activate();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the object's state
|
||||
*/
|
||||
inline bool isActive()
|
||||
{
|
||||
return _Active;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace BlueCore
|
||||
|
||||
#endif // BLUECORE_ACTIVATED_H
|
151
engine/Utilities/Buffer.h
Normal file
151
engine/Utilities/Buffer.h
Normal file
@ -0,0 +1,151 @@
|
||||
#ifndef BLUECORE_BUFFER_H
|
||||
#define BLUECORE_BUFFER_H
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace BlueCore
|
||||
{
|
||||
template<class T>
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T type;
|
||||
|
||||
private:
|
||||
|
||||
type *_buffer;
|
||||
unsigned int _count;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* default constructor
|
||||
*/
|
||||
Buffer() :
|
||||
_buffer( 0 ),
|
||||
_count( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor with initial size
|
||||
*/
|
||||
Buffer( unsigned int count ) :
|
||||
_buffer( 0 ),
|
||||
_count( 0 )
|
||||
{
|
||||
create( count );
|
||||
}
|
||||
|
||||
/**
|
||||
* destructor
|
||||
*/
|
||||
virtual ~Buffer()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* create the buffer
|
||||
*/
|
||||
bool create( unsigned int count )
|
||||
{
|
||||
destroy();
|
||||
|
||||
_buffer = new type[count];
|
||||
|
||||
if( _buffer )
|
||||
{
|
||||
_count = count;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* destroy the buffer
|
||||
*/
|
||||
void destroy()
|
||||
{
|
||||
delete [] _buffer;
|
||||
_buffer = 0;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
void resize( unsigned int new_count )
|
||||
{
|
||||
type *new_buffer = new type[new_count];
|
||||
|
||||
for( unsigned int i = 0; i<_count; i++ )
|
||||
new_buffer[i] = _buffer[i];
|
||||
|
||||
destroy();
|
||||
|
||||
_buffer = new_buffer;
|
||||
_count = new_count;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the item count
|
||||
*/
|
||||
unsigned int count() const
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the buffer size in bytes
|
||||
*/
|
||||
unsigned int size() const
|
||||
{
|
||||
return _count * sizeof(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a pointer to the data
|
||||
*/
|
||||
type *data()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a pointer to the(const) data
|
||||
*/
|
||||
const type *const_data() const
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* array operator
|
||||
*/
|
||||
type &operator[](const unsigned int index)
|
||||
{
|
||||
if( index >= _count )
|
||||
throw std::range_error("Buffer::[] index_out_of_bound!");
|
||||
return _buffer[index];
|
||||
}
|
||||
|
||||
type &item(const unsigned int index)
|
||||
{
|
||||
if( index >= _count )
|
||||
throw std::range_error("Buffer::[] index_out_of_bound!");
|
||||
return _buffer[index];
|
||||
}
|
||||
|
||||
const type &const_item(const unsigned int index) const
|
||||
{
|
||||
if( index >= _count )
|
||||
throw std::range_error("Buffer::[] index_out_of_bound!");
|
||||
return _buffer[index];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
198
engine/Utilities/CfgParser.cpp
Normal file
198
engine/Utilities/CfgParser.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
#include "CfgParser.h"
|
||||
#include "StringUtilities.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace BlueCore {
|
||||
|
||||
void CfgParser::parseFile (const std::string& filename)
|
||||
{
|
||||
ifstream file (filename.c_str(), ios::in);
|
||||
std::string line;
|
||||
|
||||
while (file.good())
|
||||
{
|
||||
getline (file, line);
|
||||
parseLine (line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgParser::parseLine (const std::string& line)
|
||||
{
|
||||
std::string::size_type i (line.find_first_of ('='));
|
||||
|
||||
if (i == std::string::npos)
|
||||
return;
|
||||
|
||||
std::string key = trim (string (line, 0, i-1));
|
||||
std::string value = trim (string (line, i+1));
|
||||
|
||||
_Pairs[key] = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CfgParser::parse (const char* buffer, unsigned int length)
|
||||
{
|
||||
const char* ptr = buffer;
|
||||
const char* end = buffer + length;
|
||||
unsigned int l = 0;
|
||||
|
||||
while (ptr < end)
|
||||
{
|
||||
// find end of line
|
||||
while (ptr[l] != '\n')
|
||||
{
|
||||
l++;
|
||||
if (ptr + l >= end)
|
||||
break;
|
||||
}
|
||||
|
||||
parseLine (string(ptr, l));
|
||||
ptr += l+1;
|
||||
l = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
double CfgParser::get (const std::string& key, double defaultValue)
|
||||
{
|
||||
double value;
|
||||
|
||||
if (getDouble (key, value) == false)
|
||||
return defaultValue;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CfgParser::getDouble (const std::string& key, double& value)
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator result;
|
||||
result = _Pairs.find (key);
|
||||
|
||||
if (result != _Pairs.end())
|
||||
{
|
||||
value = atof (result->second.c_str());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CfgParser::get (const std::string& key, int defaultValue)
|
||||
{
|
||||
int value;
|
||||
|
||||
if (getInteger (key, value) == false)
|
||||
return defaultValue;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CfgParser::getInteger (const std::string& key, int& value)
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator result;
|
||||
result = _Pairs.find (key);
|
||||
|
||||
if (result != _Pairs.end())
|
||||
{
|
||||
value = atoi (result->second.c_str());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CfgParser::get (const std::string& key, bool defaultValue)
|
||||
{
|
||||
bool value;
|
||||
|
||||
if (getBoolean (key, value) == false)
|
||||
return defaultValue;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CfgParser::getBoolean (const std::string& key, bool& value)
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator result;
|
||||
result = _Pairs.find (key);
|
||||
|
||||
if (result != _Pairs.end())
|
||||
{
|
||||
value = false;
|
||||
|
||||
if (result->second == "true")
|
||||
value = true;
|
||||
else if (result->second == "1")
|
||||
value = true;
|
||||
else if (result->second == "yes")
|
||||
value = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string CfgParser::get (const std::string& key, std::string defaultValue)
|
||||
{
|
||||
std::string value;
|
||||
|
||||
if (getString (key, value) == false)
|
||||
return defaultValue;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CfgParser::getString (const std::string& key, std::string& value)
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator result;
|
||||
result = _Pairs.find (key);
|
||||
|
||||
if (result != _Pairs.end())
|
||||
{
|
||||
value = result->second;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CfgParser::getStrings (const std::string& key, std::vector<string>& strings)
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator result;
|
||||
result = _Pairs.find (key);
|
||||
|
||||
if (result != _Pairs.end())
|
||||
{
|
||||
explode (result->second, strings, true, ",");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace BlueCore
|
||||
|
39
engine/Utilities/CfgParser.h
Normal file
39
engine/Utilities/CfgParser.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef BLUECORE_UTILITIES_CFGPARSER
|
||||
#define BLUECORE_UTILITIES_CFGPARSER
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace BlueCore {
|
||||
|
||||
class CfgParser
|
||||
{
|
||||
public:
|
||||
void parseFile (const std::string& filename);
|
||||
void parseLine (const std::string& line);
|
||||
void parse (const char* buffer, unsigned int length);
|
||||
|
||||
double get (const std::string& key, double value = 0.0);
|
||||
bool getDouble (const std::string& key, double& defaultValue);
|
||||
|
||||
int get (const std::string& key, int value = 0);
|
||||
bool getInteger (const std::string& key, int& defaultValue);
|
||||
|
||||
bool get (const std::string& key, bool value = false);
|
||||
bool getBoolean (const std::string& key, bool& defaultValue);
|
||||
|
||||
std::string get (const std::string& key, std::string value = "");
|
||||
bool getString (const std::string& key, std::string& defaultValue);
|
||||
|
||||
bool getStrings (const std::string& key, std::vector<std::string>& strings);
|
||||
|
||||
private:
|
||||
|
||||
std::map<std::string, std::string> _Pairs;
|
||||
};
|
||||
|
||||
} // namespace BlueCore
|
||||
|
||||
#endif
|
||||
|
11
engine/Utilities/IniParser.h
Normal file
11
engine/Utilities/IniParser.h
Normal file
@ -0,0 +1,11 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
class IniParser
|
||||
{
|
||||
std::map<std::string, std::string> _Pairs;
|
||||
|
||||
void parse (const std::string &text)
|
||||
{
|
||||
}
|
||||
}
|
82
engine/Utilities/Kernel.cpp
Normal file
82
engine/Utilities/Kernel.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include "Kernel.h"
|
||||
|
||||
namespace BlueCore
|
||||
{
|
||||
|
||||
Kernel::Kernel() :
|
||||
_Changed(true), _Clear(false)
|
||||
{
|
||||
}
|
||||
|
||||
void Kernel::addTask(KernelTask* task, int priority)
|
||||
{
|
||||
_AddedTasks.push_back(KernelTaskContainer (task, priority));
|
||||
_Changed = true;
|
||||
}
|
||||
|
||||
void Kernel::removeTask(KernelTask* task)
|
||||
{
|
||||
_RemovedTasks.push_back(task );
|
||||
_Changed = true;
|
||||
}
|
||||
|
||||
void Kernel::removeAllTasks()
|
||||
{
|
||||
_Clear = true;
|
||||
}
|
||||
|
||||
void Kernel::setTaskPriority(KernelTask* task, int priority)
|
||||
{
|
||||
std::list<KernelTaskContainer>::iterator i;
|
||||
for (i = _Tasks.begin(); i != _Tasks.end(); i++)
|
||||
{
|
||||
if ((*i)._Task.get() == task)
|
||||
{
|
||||
(*i)._Priority = priority;
|
||||
_Changed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Kernel::tick()
|
||||
{
|
||||
if (_Changed)
|
||||
{
|
||||
std::list<KernelTaskContainer>::iterator i;
|
||||
for (i = _AddedTasks.begin(); i != _AddedTasks.end(); i++)
|
||||
{
|
||||
_Tasks.push_back( *i );
|
||||
}
|
||||
|
||||
_AddedTasks.clear();
|
||||
_RemovedTasks.clear();
|
||||
_Tasks.sort();
|
||||
_Changed = false;
|
||||
}
|
||||
|
||||
std::list<KernelTaskContainer>::iterator i = _Tasks.begin();
|
||||
std::list<KernelTaskContainer>::iterator end = _Tasks.end();
|
||||
|
||||
if (i == end)
|
||||
return false;
|
||||
|
||||
while (i != end)
|
||||
{
|
||||
if ((*i)._Task.valid())
|
||||
(*i)._Task->tick();
|
||||
i++;
|
||||
}
|
||||
|
||||
if (_Clear)
|
||||
{
|
||||
_Tasks.clear();
|
||||
_Clear = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace BlueCore
|
||||
|
83
engine/Utilities/Kernel.h
Normal file
83
engine/Utilities/Kernel.h
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef KERNEL_H_
|
||||
#define KERNEL_H_
|
||||
|
||||
#include "Referenced.h"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <list>
|
||||
|
||||
namespace BlueCore
|
||||
{
|
||||
|
||||
class Kernel;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class KernelTask : public Referenced
|
||||
{
|
||||
protected:
|
||||
|
||||
~KernelTask()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
KernelTask()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void tick()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class Kernel : public Referenced
|
||||
{
|
||||
private:
|
||||
|
||||
struct KernelTaskContainer
|
||||
{
|
||||
ref_ptr<KernelTask> _Task;
|
||||
int _Priority;
|
||||
|
||||
KernelTaskContainer(KernelTask* task, int priority) :
|
||||
_Task(task), _Priority(priority)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator <(const KernelTaskContainer& other) const
|
||||
{
|
||||
return (_Priority > other._Priority);
|
||||
}
|
||||
};
|
||||
|
||||
std::list<KernelTaskContainer> _Tasks;
|
||||
std::list<KernelTaskContainer> _AddedTasks;
|
||||
std::list<KernelTask*> _RemovedTasks;
|
||||
bool _Changed;
|
||||
bool _Clear;
|
||||
|
||||
protected:
|
||||
|
||||
~Kernel()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Kernel();
|
||||
|
||||
void addTask(KernelTask* task, int priority);
|
||||
void removeTask(KernelTask* task);
|
||||
void removeAllTasks();
|
||||
void setTaskPriority(KernelTask* task, int priority);
|
||||
bool tick();
|
||||
};
|
||||
|
||||
} // namespace BlueCore
|
||||
|
||||
#endif /*KERNEL_H_*/
|
||||
|
75
engine/Utilities/Log.cpp
Normal file
75
engine/Utilities/Log.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include "Log.h"
|
||||
#include <ctime>
|
||||
|
||||
namespace BlueCore
|
||||
{
|
||||
//--------------------------------------------------------------------------
|
||||
Log::Log() :
|
||||
_LogFilename( "log.txt" )
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void Log::reset()
|
||||
{
|
||||
std::ifstream testfile( _LogFilename.c_str() );
|
||||
if( testfile.is_open() )
|
||||
{
|
||||
testfile.close();
|
||||
_LogFile.open( _LogFilename.c_str(), std::ios::trunc );
|
||||
_LogFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void Log::setFilename( const std::string &name )
|
||||
{
|
||||
_LogFilename = name;
|
||||
reset();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
Log &Log::operator << (const EndLine &e)
|
||||
{
|
||||
_LogFile << '\n';
|
||||
std::cout << '\n';
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
Log &Log::operator << (const EndLog &e)
|
||||
{
|
||||
_LogFile << '\n';
|
||||
_LogFile.close();
|
||||
std::cout << '\n';
|
||||
std::cout.flush();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
Log &Log::operator << (const Time &t)
|
||||
{
|
||||
std::time_t rawtime;
|
||||
std::time ( &rawtime );
|
||||
char *tc = std::ctime( &rawtime );
|
||||
_LogFile << tc;
|
||||
std::cout << tc;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
Log &Log::operator << (const Flush &f)
|
||||
{
|
||||
_LogFile.close();
|
||||
std::cout.flush();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
Log::EndLine endline;
|
||||
Log::EndLog endlog;
|
||||
Log::Time time;
|
||||
Log::Flush flush;
|
||||
Log clog;
|
||||
}
|
60
engine/Utilities/Log.h
Normal file
60
engine/Utilities/Log.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef BLUECORE_LOG_H
|
||||
#define BLUECORE_LOG_H
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
namespace BlueCore
|
||||
{
|
||||
class Log
|
||||
{
|
||||
std::string _LogFilename;
|
||||
std::ofstream _LogFile;
|
||||
|
||||
public:
|
||||
class EndLine
|
||||
{
|
||||
};
|
||||
|
||||
class EndLog
|
||||
{
|
||||
};
|
||||
|
||||
class Time
|
||||
{
|
||||
};
|
||||
|
||||
class Flush
|
||||
{
|
||||
};
|
||||
|
||||
Log();
|
||||
|
||||
void setFilename( const std::string &name );
|
||||
void reset();
|
||||
|
||||
template<class T>
|
||||
Log &operator << (const T &v)
|
||||
{
|
||||
if( !_LogFile.is_open() )
|
||||
_LogFile.open(_LogFilename.c_str(), std::ios::app);
|
||||
_LogFile << v;
|
||||
std::cout << v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Log &operator << (const EndLine &e);
|
||||
Log &operator << (const EndLog &e);
|
||||
Log &operator << (const Time &t);
|
||||
Log &operator << (const Flush &f);
|
||||
};
|
||||
|
||||
extern Log::EndLine endline;
|
||||
extern Log::EndLog endlog;
|
||||
extern Log::Time time;
|
||||
extern Log::Flush flush;
|
||||
extern Log clog;
|
||||
|
||||
} // namespace bc
|
||||
|
||||
#endif // BLUECORE_LOG_H
|
423
engine/Utilities/MersenneTwister.h
Normal file
423
engine/Utilities/MersenneTwister.h
Normal file
@ -0,0 +1,423 @@
|
||||
// MersenneTwister.h
|
||||
// Mersenne Twister random number generator -- a C++ class MTRand
|
||||
// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
|
||||
// Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com
|
||||
|
||||
// The Mersenne Twister is an algorithm for generating random numbers. It
|
||||
// was designed with consideration of the flaws in various other generators.
|
||||
// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
|
||||
// are far greater. The generator is also fast; it avoids multiplication and
|
||||
// division, and it benefits from caches and pipelines. For more information
|
||||
// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
|
||||
|
||||
// Reference
|
||||
// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
|
||||
// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
|
||||
// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
|
||||
|
||||
// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
|
||||
// Copyright (C) 2000 - 2003, Richard J. Wagner
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The names of its contributors may not be used to endorse or promote
|
||||
// products derived from this software without specific prior written
|
||||
// permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "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 THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// The original code included the following notice:
|
||||
//
|
||||
// When you use this, send an email to: matumoto@math.keio.ac.jp
|
||||
// with an appropriate reference to your work.
|
||||
//
|
||||
// It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
|
||||
// when you write.
|
||||
|
||||
#ifndef MERSENNETWISTER_H
|
||||
#define MERSENNETWISTER_H
|
||||
|
||||
// Not thread safe (unless auto-initialization is avoided and each thread has
|
||||
// its own MTRand object)
|
||||
|
||||
#include <iostream>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
class MTRand {
|
||||
// Data
|
||||
public:
|
||||
typedef unsigned long uint32; // unsigned integer type, at least 32 bits
|
||||
|
||||
enum { N = 624 }; // length of state vector
|
||||
enum { SAVE = N + 1 }; // length of array for save()
|
||||
|
||||
protected:
|
||||
enum { M = 397 }; // period parameter
|
||||
|
||||
uint32 state[N]; // internal state
|
||||
uint32 *pNext; // next value to get from state
|
||||
int left; // number of values left before reload needed
|
||||
|
||||
|
||||
//Methods
|
||||
public:
|
||||
MTRand( const uint32& oneSeed ); // initialize with a simple uint32
|
||||
MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
|
||||
MTRand(); // auto-initialize with /dev/urandom or time() and clock()
|
||||
|
||||
// Do NOT use for CRYPTOGRAPHY without securely hashing several returned
|
||||
// values together, otherwise the generator state can be learned after
|
||||
// reading 624 consecutive values.
|
||||
|
||||
// Access to 32-bit random numbers
|
||||
double rand(); // real number in [0,1]
|
||||
double rand( const double& n ); // real number in [0,n]
|
||||
double randExc(); // real number in [0,1)
|
||||
double randExc( const double& n ); // real number in [0,n)
|
||||
double randDblExc(); // real number in (0,1)
|
||||
double randDblExc( const double& n ); // real number in (0,n)
|
||||
uint32 randInt(); // integer in [0,2^32-1]
|
||||
uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
|
||||
double operator()() { return rand(); } // same as rand()
|
||||
|
||||
// Access to 53-bit random numbers (capacity of IEEE double precision)
|
||||
double rand53(); // real number in [0,1)
|
||||
|
||||
// Access to nonuniform random number distributions
|
||||
double randNorm( const double& mean = 0.0, const double& variance = 0.0 );
|
||||
|
||||
// Re-seeding functions with same behavior as initializers
|
||||
void seed( const uint32 oneSeed );
|
||||
void seed( uint32 *const bigSeed, const uint32 seedLength = N );
|
||||
void seed();
|
||||
|
||||
// Saving and loading generator state
|
||||
void save( uint32* saveArray ) const; // to array of size SAVE
|
||||
void load( uint32 *const loadArray ); // from such array
|
||||
friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
|
||||
friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
|
||||
|
||||
protected:
|
||||
void initialize( const uint32 oneSeed );
|
||||
void reload();
|
||||
uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
|
||||
uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
|
||||
uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
|
||||
uint32 mixBits( const uint32& u, const uint32& v ) const
|
||||
{ return hiBit(u) | loBits(v); }
|
||||
uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
|
||||
{ return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
|
||||
static uint32 hash( time_t t, clock_t c );
|
||||
};
|
||||
|
||||
|
||||
inline MTRand::MTRand( const uint32& oneSeed )
|
||||
{ seed(oneSeed); }
|
||||
|
||||
inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
|
||||
{ seed(bigSeed,seedLength); }
|
||||
|
||||
inline MTRand::MTRand()
|
||||
{ seed(); }
|
||||
|
||||
inline double MTRand::rand()
|
||||
{ return double(randInt()) * (1.0/4294967295.0); }
|
||||
|
||||
inline double MTRand::rand( const double& n )
|
||||
{ return rand() * n; }
|
||||
|
||||
inline double MTRand::randExc()
|
||||
{ return double(randInt()) * (1.0/4294967296.0); }
|
||||
|
||||
inline double MTRand::randExc( const double& n )
|
||||
{ return randExc() * n; }
|
||||
|
||||
inline double MTRand::randDblExc()
|
||||
{ return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
|
||||
|
||||
inline double MTRand::randDblExc( const double& n )
|
||||
{ return randDblExc() * n; }
|
||||
|
||||
inline double MTRand::rand53()
|
||||
{
|
||||
uint32 a = randInt() >> 5, b = randInt() >> 6;
|
||||
return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
|
||||
}
|
||||
|
||||
inline double MTRand::randNorm( const double& mean, const double& variance )
|
||||
{
|
||||
// Return a real number from a normal (Gaussian) distribution with given
|
||||
// mean and variance by Box-Muller method
|
||||
double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
|
||||
double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
|
||||
return mean + r * cos(phi);
|
||||
}
|
||||
|
||||
inline MTRand::uint32 MTRand::randInt()
|
||||
{
|
||||
// Pull a 32-bit integer from the generator state
|
||||
// Every other access function simply transforms the numbers extracted here
|
||||
|
||||
if( left == 0 ) reload();
|
||||
--left;
|
||||
|
||||
register uint32 s1;
|
||||
s1 = *pNext++;
|
||||
s1 ^= (s1 >> 11);
|
||||
s1 ^= (s1 << 7) & 0x9d2c5680UL;
|
||||
s1 ^= (s1 << 15) & 0xefc60000UL;
|
||||
return ( s1 ^ (s1 >> 18) );
|
||||
}
|
||||
|
||||
inline MTRand::uint32 MTRand::randInt( const uint32& n )
|
||||
{
|
||||
// Find which bits are used in n
|
||||
// Optimized by Magnus Jonsson (magnus@smartelectronix.com)
|
||||
uint32 used = n;
|
||||
used |= used >> 1;
|
||||
used |= used >> 2;
|
||||
used |= used >> 4;
|
||||
used |= used >> 8;
|
||||
used |= used >> 16;
|
||||
|
||||
// Draw numbers until one is found in [0,n]
|
||||
uint32 i;
|
||||
do
|
||||
i = randInt() & used; // toss unused bits to shorten search
|
||||
while( i > n );
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::seed( const uint32 oneSeed )
|
||||
{
|
||||
// Seed the generator with a simple uint32
|
||||
initialize(oneSeed);
|
||||
reload();
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
|
||||
{
|
||||
// Seed the generator with an array of uint32's
|
||||
// There are 2^19937-1 possible initial states. This function allows
|
||||
// all of those to be accessed by providing at least 19937 bits (with a
|
||||
// default seed length of N = 624 uint32's). Any bits above the lower 32
|
||||
// in each element are discarded.
|
||||
// Just call seed() if you want to get array from /dev/urandom
|
||||
initialize(19650218UL);
|
||||
register int i = 1;
|
||||
register uint32 j = 0;
|
||||
register int k = ( N > seedLength ? N : seedLength );
|
||||
for( ; k; --k )
|
||||
{
|
||||
state[i] =
|
||||
state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
|
||||
state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
|
||||
state[i] &= 0xffffffffUL;
|
||||
++i; ++j;
|
||||
if( i >= N ) { state[0] = state[N-1]; i = 1; }
|
||||
if( j >= seedLength ) j = 0;
|
||||
}
|
||||
for( k = N - 1; k; --k )
|
||||
{
|
||||
state[i] =
|
||||
state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
|
||||
state[i] -= i;
|
||||
state[i] &= 0xffffffffUL;
|
||||
++i;
|
||||
if( i >= N ) { state[0] = state[N-1]; i = 1; }
|
||||
}
|
||||
state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
|
||||
reload();
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::seed()
|
||||
{
|
||||
// Seed the generator with an array from /dev/urandom if available
|
||||
// Otherwise use a hash of time() and clock() values
|
||||
|
||||
// First try getting an array from /dev/urandom
|
||||
FILE* urandom = fopen( "/dev/urandom", "rb" );
|
||||
if( urandom )
|
||||
{
|
||||
uint32 bigSeed[N];
|
||||
register uint32 *s = bigSeed;
|
||||
register int i = N;
|
||||
register bool success = true;
|
||||
while( success && i-- )
|
||||
success = fread( s++, sizeof(uint32), 1, urandom );
|
||||
fclose(urandom);
|
||||
if( success ) { seed( bigSeed, N ); return; }
|
||||
}
|
||||
|
||||
// Was not successful, so use time() and clock() instead
|
||||
seed( hash( time(NULL), clock() ) );
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::initialize( const uint32 seed )
|
||||
{
|
||||
// Initialize generator state with seed
|
||||
// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
|
||||
// In previous versions, most significant bits (MSBs) of the seed affect
|
||||
// only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
|
||||
register uint32 *s = state;
|
||||
register uint32 *r = state;
|
||||
register int i = 1;
|
||||
*s++ = seed & 0xffffffffUL;
|
||||
for( ; i < N; ++i )
|
||||
{
|
||||
*s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::reload()
|
||||
{
|
||||
// Generate N new values in state
|
||||
// Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
|
||||
register uint32 *p = state;
|
||||
register int i;
|
||||
for( i = N - M; i--; ++p )
|
||||
*p = twist( p[M], p[0], p[1] );
|
||||
for( i = M; --i; ++p )
|
||||
*p = twist( p[M-N], p[0], p[1] );
|
||||
*p = twist( p[M-N], p[0], state[0] );
|
||||
|
||||
left = N, pNext = state;
|
||||
}
|
||||
|
||||
|
||||
inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
|
||||
{
|
||||
// Get a uint32 from t and c
|
||||
// Better than uint32(x) in case x is floating point in [0,1]
|
||||
// Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
|
||||
|
||||
static uint32 differ = 0; // guarantee time-based seeds will change
|
||||
|
||||
uint32 h1 = 0;
|
||||
unsigned char *p = (unsigned char *) &t;
|
||||
for( size_t i = 0; i < sizeof(t); ++i )
|
||||
{
|
||||
h1 *= UCHAR_MAX + 2U;
|
||||
h1 += p[i];
|
||||
}
|
||||
uint32 h2 = 0;
|
||||
p = (unsigned char *) &c;
|
||||
for( size_t j = 0; j < sizeof(c); ++j )
|
||||
{
|
||||
h2 *= UCHAR_MAX + 2U;
|
||||
h2 += p[j];
|
||||
}
|
||||
return ( h1 + differ++ ) ^ h2;
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::save( uint32* saveArray ) const
|
||||
{
|
||||
register uint32 *sa = saveArray;
|
||||
register const uint32 *s = state;
|
||||
register int i = N;
|
||||
for( ; i--; *sa++ = *s++ ) {}
|
||||
*sa = left;
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::load( uint32 *const loadArray )
|
||||
{
|
||||
register uint32 *s = state;
|
||||
register uint32 *la = loadArray;
|
||||
register int i = N;
|
||||
for( ; i--; *s++ = *la++ ) {}
|
||||
left = *la;
|
||||
pNext = &state[N-left];
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
|
||||
{
|
||||
register const MTRand::uint32 *s = mtrand.state;
|
||||
register int i = mtrand.N;
|
||||
for( ; i--; os << *s++ << "\t" ) {}
|
||||
return os << mtrand.left;
|
||||
}
|
||||
|
||||
|
||||
inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
|
||||
{
|
||||
register MTRand::uint32 *s = mtrand.state;
|
||||
register int i = mtrand.N;
|
||||
for( ; i--; is >> *s++ ) {}
|
||||
is >> mtrand.left;
|
||||
mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
|
||||
return is;
|
||||
}
|
||||
|
||||
#endif // MERSENNETWISTER_H
|
||||
|
||||
// Change log:
|
||||
//
|
||||
// v0.1 - First release on 15 May 2000
|
||||
// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
|
||||
// - Translated from C to C++
|
||||
// - Made completely ANSI compliant
|
||||
// - Designed convenient interface for initialization, seeding, and
|
||||
// obtaining numbers in default or user-defined ranges
|
||||
// - Added automatic seeding from /dev/urandom or time() and clock()
|
||||
// - Provided functions for saving and loading generator state
|
||||
//
|
||||
// v0.2 - Fixed bug which reloaded generator one step too late
|
||||
//
|
||||
// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
|
||||
//
|
||||
// v0.4 - Removed trailing newline in saved generator format to be consistent
|
||||
// with output format of built-in types
|
||||
//
|
||||
// v0.5 - Improved portability by replacing static const int's with enum's and
|
||||
// clarifying return values in seed(); suggested by Eric Heimburg
|
||||
// - Removed MAXINT constant; use 0xffffffffUL instead
|
||||
//
|
||||
// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
|
||||
// - Changed integer [0,n] generator to give better uniformity
|
||||
//
|
||||
// v0.7 - Fixed operator precedence ambiguity in reload()
|
||||
// - Added access for real numbers in (0,1) and (0,n)
|
||||
//
|
||||
// v0.8 - Included time.h header to properly support time_t and clock_t
|
||||
//
|
||||
// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
|
||||
// - Allowed for seeding with arrays of any length
|
||||
// - Added access for real numbers in [0,1) with 53-bit resolution
|
||||
// - Added access for real numbers from normal (Gaussian) distributions
|
||||
// - Increased overall speed by optimizing twist()
|
||||
// - Doubled speed of integer [0,n] generation
|
||||
// - Fixed out-of-range number generation on 64-bit machines
|
||||
// - Improved portability by substituting literal constants for long enum's
|
||||
// - Changed license from GNU LGPL to BSD
|
64
engine/Utilities/Named.h
Normal file
64
engine/Utilities/Named.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef BLUECORE_NAMED_H
|
||||
#define BLUECORE_NAMED_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace BlueCore
|
||||
{
|
||||
class Named
|
||||
{
|
||||
private:
|
||||
|
||||
std::string _Name;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
inline Named() :
|
||||
_Name( "" )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param strName set initial name
|
||||
*/
|
||||
inline Named( const std::string &name ) :
|
||||
_Name( name )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual inline ~Named()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the name.
|
||||
* @return returns the name
|
||||
*/
|
||||
inline const std::string &getName() const
|
||||
{
|
||||
return _Name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the name.
|
||||
*/
|
||||
inline void setName( const std::string &name )
|
||||
{
|
||||
_Name = name;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
236
engine/Utilities/Referenced.h
Normal file
236
engine/Utilities/Referenced.h
Normal file
@ -0,0 +1,236 @@
|
||||
#ifndef BLUECORE_REFERENCED_COUNTER_H
|
||||
#define BLUECORE_REFERENCED_COUNTER_H
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace BlueCore
|
||||
{
|
||||
|
||||
class Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
class DestructionListener
|
||||
{
|
||||
public:
|
||||
virtual void onDestruction(Referenced *referenced) = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
std::list<DestructionListener*> _DestructionListeners;
|
||||
|
||||
unsigned int _ReferenceCount;
|
||||
|
||||
virtual void destroyReferenced()
|
||||
{
|
||||
while (_DestructionListeners.begin() != _DestructionListeners.end())
|
||||
{
|
||||
if (_DestructionListeners.front() != 0)
|
||||
_DestructionListeners.front()->onDestruction(this);
|
||||
_DestructionListeners.pop_front();
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
inline Referenced() :
|
||||
_ReferenceCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual inline ~Referenced()
|
||||
{
|
||||
}
|
||||
|
||||
inline void addReference()
|
||||
{
|
||||
_ReferenceCount += 1;
|
||||
}
|
||||
|
||||
inline void removeReference()
|
||||
{
|
||||
if (_ReferenceCount > 0)
|
||||
{
|
||||
_ReferenceCount -= 1;
|
||||
|
||||
if ( 0 == _ReferenceCount)
|
||||
{
|
||||
destroyReferenced();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned int getReferenceCount()
|
||||
{
|
||||
return _ReferenceCount;
|
||||
}
|
||||
|
||||
inline void addDestructionListener(DestructionListener *listener)
|
||||
{
|
||||
if (listener != 0)
|
||||
_DestructionListeners.push_back(listener);
|
||||
}
|
||||
|
||||
inline void removeDestructionListener(DestructionListener *listener)
|
||||
{
|
||||
_DestructionListeners.remove(listener);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> class ref_ptr
|
||||
{
|
||||
public:
|
||||
ref_ptr() :
|
||||
_Referenced(0)
|
||||
{
|
||||
}
|
||||
|
||||
ref_ptr(T* referenced) :
|
||||
_Referenced(referenced)
|
||||
{
|
||||
if (_Referenced)
|
||||
_Referenced->addReference();
|
||||
}
|
||||
|
||||
ref_ptr(const ref_ptr& op) :
|
||||
_Referenced(op._Referenced)
|
||||
{
|
||||
if (_Referenced)
|
||||
_Referenced->addReference();
|
||||
}
|
||||
|
||||
~ref_ptr()
|
||||
{
|
||||
if (_Referenced)
|
||||
_Referenced->removeReference();
|
||||
}
|
||||
|
||||
T* operator ->() const
|
||||
{
|
||||
return _Referenced;
|
||||
}
|
||||
|
||||
ref_ptr& operator =(T* op)
|
||||
{
|
||||
if (op != _Referenced)
|
||||
{
|
||||
if (_Referenced != 0)
|
||||
_Referenced->removeReference();
|
||||
|
||||
_Referenced = op;
|
||||
|
||||
if (_Referenced)
|
||||
_Referenced->addReference();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator ==(const ref_ptr& ref)
|
||||
{
|
||||
if (_Referenced == ref._Referenced)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return (_Referenced != 0);
|
||||
}
|
||||
|
||||
operator T*() const
|
||||
{
|
||||
return _Referenced;
|
||||
}
|
||||
|
||||
T* get() const
|
||||
{
|
||||
return _Referenced;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T* _Referenced;
|
||||
};
|
||||
|
||||
template<class T> class weak_ptr : public Referenced::DestructionListener
|
||||
{
|
||||
public:
|
||||
weak_ptr() :
|
||||
_Referenced(0)
|
||||
{
|
||||
}
|
||||
|
||||
weak_ptr(T* referenced) :
|
||||
_Referenced(referenced)
|
||||
{
|
||||
if (_Referenced)
|
||||
_Referenced->addDestructionListener(this);
|
||||
}
|
||||
|
||||
weak_ptr(const weak_ptr& op) :
|
||||
_Referenced(op._Referenced)
|
||||
{
|
||||
if (_Referenced)
|
||||
_Referenced->addDestructionListener(this);
|
||||
}
|
||||
|
||||
virtual ~weak_ptr()
|
||||
{
|
||||
if (_Referenced)
|
||||
_Referenced->removeDestructionListener(this);
|
||||
}
|
||||
|
||||
T* operator ->() const
|
||||
{
|
||||
return _Referenced;
|
||||
}
|
||||
|
||||
weak_ptr& operator =(T* op)
|
||||
{
|
||||
if (op != _Referenced && _Referenced != 0)
|
||||
_Referenced->removeDestructionListener(this);
|
||||
|
||||
_Referenced = op;
|
||||
_Referenced->addDestructionListener(this);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator ==(const weak_ptr& ref)
|
||||
{
|
||||
if (_Referenced == ref._Referenced)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return (_Referenced != 0);
|
||||
}
|
||||
|
||||
|
||||
T* get() const
|
||||
{
|
||||
return _Referenced;
|
||||
}
|
||||
|
||||
|
||||
void onDestruction(Referenced *referenced)
|
||||
{
|
||||
_Referenced = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T* _Referenced;
|
||||
};
|
||||
|
||||
} // namespace BlueCore
|
||||
|
||||
#endif
|
119
engine/Utilities/StringUtilities.h
Normal file
119
engine/Utilities/StringUtilities.h
Normal file
@ -0,0 +1,119 @@
|
||||
#ifndef BLUECORE_STRING_UTILITIES_H
|
||||
#define BLUECORE_STRING_UTILITIES_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace BlueCore {
|
||||
|
||||
|
||||
#define SPACES " \t\r\n"
|
||||
|
||||
|
||||
/**
|
||||
* Function to remove whitespaces from the end of the string.
|
||||
* @param s String to be trimmed.
|
||||
* @param t String containing whitespaces. Default: space, tab, carriage return and newline.
|
||||
*/
|
||||
inline std::string trim_right(
|
||||
const std::string &s,
|
||||
const std::string &t = SPACES )
|
||||
{
|
||||
std::string::size_type i (s.find_last_not_of (t));
|
||||
|
||||
if (i == std::string::npos)
|
||||
return "";
|
||||
else
|
||||
return std::string( s, 0, i );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Function to remove whitespaces from the beginning of the string.
|
||||
* @param s String to be trimmed.
|
||||
* @param t String containing whitespaces. Default: space, tab, carriage return and newline.
|
||||
*/
|
||||
inline std::string trim_left(
|
||||
const std::string &s,
|
||||
const std::string &t = SPACES )
|
||||
{
|
||||
return std::string( s, s.find_first_not_of(t) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to remove whitespaces from the beginning and the end of the string.
|
||||
* @param s String to be trimmed.
|
||||
* @param t String containing whitespaces. Default: space, tab, carriage return and newline.
|
||||
*/
|
||||
inline std::string trim(
|
||||
const std::string &s,
|
||||
const std::string &t = SPACES )
|
||||
{
|
||||
std::string::size_type a = s.find_first_not_of(t), b = s.find_last_not_of(t);
|
||||
|
||||
if ( a == std::string::npos || b == std::string::npos )
|
||||
return "";
|
||||
|
||||
return std::string( s, a, b-a+1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string into pieces, and returns them in an array.
|
||||
* @param s String to be exploded.
|
||||
* @param v Vector which receives the pieces.
|
||||
* @param t String containing whitespaces. Default: space, tab, carriage return and newline.
|
||||
* @param trim_spaces Flag to decide if pieces should be trimmed. Default: false.
|
||||
*/
|
||||
inline void explode(
|
||||
const std::string &s,
|
||||
std::vector<std::string> &v,
|
||||
const bool trim_spaces = false,
|
||||
const std::string &t = SPACES )
|
||||
{
|
||||
std::string::size_type a, b;
|
||||
|
||||
a = s.find_first_not_of(t), b = s.find_first_of(t, a);
|
||||
|
||||
while( a != std::string::npos )
|
||||
{
|
||||
if( trim_spaces )
|
||||
v.push_back( trim( s.substr(a, b-a) ) );
|
||||
else
|
||||
v.push_back( s.substr(a, b-a) );
|
||||
|
||||
a = s.find_first_not_of(t, b), b = s.find_first_of(t, a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Function to assemble strings from a vector into one strng.
|
||||
* @param v Vector which conatins the string pieces.
|
||||
* @param t String which is places between peaces. Default: one space " ".
|
||||
* @return Assembled string.
|
||||
*/
|
||||
inline std::string implode(
|
||||
const std::vector<std::string> &v,
|
||||
const std::string &t = " " )
|
||||
{
|
||||
unsigned int i;
|
||||
std::string s;
|
||||
|
||||
for( i = 0; i < (v.size() - 1); i++)
|
||||
{
|
||||
s.append( v[i] );
|
||||
s.append( t );
|
||||
}
|
||||
|
||||
return s+v[i];
|
||||
}
|
||||
|
||||
} // namespace BlueCore
|
||||
|
||||
#endif
|
142
engine/Utilities/format.cpp
Normal file
142
engine/Utilities/format.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
#include "format.h"
|
||||
|
||||
#ifndef NFORMAT
|
||||
|
||||
void Format::CFormat::reset()
|
||||
{
|
||||
valid = false;
|
||||
adjust = RIGHT;
|
||||
special = false;
|
||||
precision = 6;
|
||||
precision_explicit = false;
|
||||
zero = false;
|
||||
sign = false;
|
||||
width = 0;
|
||||
internal = false;
|
||||
setupper = false;
|
||||
grouping = false;
|
||||
conversion = false;
|
||||
base = DEC;
|
||||
floating = FIXED;
|
||||
showbase = false;
|
||||
strlength = 0;
|
||||
}
|
||||
|
||||
int Format::skip_atoi( std::string s, ST start, ST& pos )
|
||||
{
|
||||
pos = start;
|
||||
ST len = s.size();
|
||||
|
||||
while( (pos < len) && isdigit( s[pos] ) )
|
||||
pos++;
|
||||
|
||||
return atoi( s.substr( start, start-pos ).c_str() );
|
||||
}
|
||||
|
||||
void Format::CFormat::set( std::ostream& out )
|
||||
{
|
||||
if( !valid )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
printf( "valid: %d\n", valid );
|
||||
printf( "adjust: %d\n", adjust );
|
||||
printf( "special: %d\n", special );
|
||||
printf( "precision: %d\n", precision );
|
||||
printf( "precision_explicit: %d\n", precision_explicit );
|
||||
printf( "zero: %d\n", zero );
|
||||
printf( "sign: %d\n", sign );
|
||||
printf( "width: %d\n", width );
|
||||
printf( "internal: %d\n", internal );
|
||||
printf( "setupper: %d\n", setupper );
|
||||
printf( "grouping: %d\n", grouping );
|
||||
printf( "conversion: %d\n", conversion );
|
||||
printf( "base: %d\n", base );
|
||||
printf( "floating: %d\n", floating );
|
||||
printf( "showbase: %d\n", showbase );
|
||||
printf( "strlength: %d\n", strlength );
|
||||
*/
|
||||
|
||||
if( base == HEX && special && showbase && zero )
|
||||
{
|
||||
// without this correction:
|
||||
// printf( "[%#08x]", 0x42 ) => [0x000042]
|
||||
// fromat( "[%#08x]", 0x42 ) => [00000x42]
|
||||
|
||||
showbase = false;
|
||||
out << '0' << ( setupper ? 'X' : 'x' );
|
||||
width -= 2;
|
||||
}
|
||||
|
||||
if( base == HEX && special && showbase && strlength )
|
||||
{
|
||||
/*
|
||||
sprintf( buffer, "[%#8.3x]", 0x42 ) => [ 0x042]
|
||||
*/
|
||||
|
||||
showbase = false;
|
||||
|
||||
if( width )
|
||||
{
|
||||
for( int i = 0; i + strlength + 2 + 1 < width; ++i )
|
||||
out << ' ';
|
||||
width = 0;
|
||||
}
|
||||
|
||||
out << '0' << ( setupper ? 'X' : 'x' );
|
||||
for( int i = 0; i + strlength < precision; ++i )
|
||||
out << '0';
|
||||
}
|
||||
|
||||
if( adjust == LEFT && zero )
|
||||
{
|
||||
/*
|
||||
sprintf( buffer, "[%-#08x]", 0x42 ); => [0x42 ]
|
||||
not => [0x420000]
|
||||
*/
|
||||
zero = false;
|
||||
}
|
||||
|
||||
switch( adjust )
|
||||
{
|
||||
case LEFT: out.setf( std::ios::left, std::ios::adjustfield ); break;
|
||||
case RIGHT: out.setf( std::ios::right, std::ios::adjustfield ); break;
|
||||
}
|
||||
|
||||
if( zero ) out << std::setfill('0');
|
||||
else out << std::setfill( ' ' );
|
||||
|
||||
if( sign ) out.setf( std::ios::showpos );
|
||||
else out.unsetf( std::ios::showpos );
|
||||
|
||||
if( internal )
|
||||
out.setf( std::ios::internal, std::ios::adjustfield );
|
||||
|
||||
switch( base )
|
||||
{
|
||||
case OCT: out.setf( std::ios::oct, std::ios::basefield ); break;
|
||||
case DEC: out.setf( std::ios::dec, std::ios::basefield ); break;
|
||||
case HEX: out.setf( std::ios::hex, std::ios::basefield ); break;
|
||||
}
|
||||
|
||||
if( setupper ) out.setf( std::ios::uppercase );
|
||||
else out.unsetf( std::ios::uppercase );
|
||||
|
||||
switch( floating )
|
||||
{
|
||||
case FIXED: out.setf( std::ios::fixed, std::ios::floatfield ); break;
|
||||
case SCIENTIFIC: out.setf( std::ios::scientific, std::ios::floatfield ); break;
|
||||
}
|
||||
|
||||
if( showbase )
|
||||
out.setf( std::ios::showbase );
|
||||
else
|
||||
out.unsetf( std::ios::showbase );
|
||||
|
||||
out << std::setw( width );
|
||||
out << std::setprecision( precision );
|
||||
}
|
||||
|
||||
#endif
|
919
engine/Utilities/format.h
Normal file
919
engine/Utilities/format.h
Normal file
@ -0,0 +1,919 @@
|
||||
/*
|
||||
Format a C++ library for typesafe string formating in printf style
|
||||
(C) 2001 - 2003 by Martin Oberzalek <kingleo@gmx.at>
|
||||
|
||||
Examples:
|
||||
std::cout << format( "Hello %s, I have $05d$ in my pocket", "world", 5 ) << std::endl;
|
||||
std::cout << format( "Do not try this with printf: %s", 10101 ) << std::endl;
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#ifndef format_h
|
||||
#define format_h
|
||||
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
Can we use stringstreams or do we have to use the deprecated strstreams instead?
|
||||
If we have to use strstreams, simple comment the next #define
|
||||
**/
|
||||
#define HAVE_STL_SSTREAM
|
||||
#define NFORMAT
|
||||
|
||||
|
||||
#if __GNUC__ == 2
|
||||
#undef HAVE_STL_SSTREAM
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STL_SSTREAM
|
||||
# include <sstream>
|
||||
# include <cctype>
|
||||
# define IS_DIGIT( x ) std::isdigit( x )
|
||||
#else
|
||||
extern "C" {
|
||||
# include <ctype.h>
|
||||
}
|
||||
# include <strstream>
|
||||
# define IS_DIGIT( x ) isdigit( x )
|
||||
#endif
|
||||
|
||||
#ifndef NFORMAT
|
||||
|
||||
namespace Format
|
||||
{
|
||||
typedef std::string::size_type ST;
|
||||
|
||||
class CFormat
|
||||
{
|
||||
public:
|
||||
|
||||
typedef enum Adjust
|
||||
{
|
||||
LEFT,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
typedef enum Base
|
||||
{
|
||||
OCT,
|
||||
DEC,
|
||||
HEX
|
||||
};
|
||||
|
||||
typedef enum Floating
|
||||
{
|
||||
FIXED,
|
||||
SCIENTIFIC
|
||||
};
|
||||
|
||||
bool valid;
|
||||
Adjust adjust;
|
||||
bool special;
|
||||
bool sign;
|
||||
bool grouping; // SUSv2 extension
|
||||
bool conversion; // glibc 2.2 extension
|
||||
bool zero;
|
||||
bool precision_explicit;
|
||||
bool internal;
|
||||
Base base;
|
||||
bool setupper;
|
||||
Floating floating;
|
||||
bool showbase;
|
||||
|
||||
int width;
|
||||
int precision;
|
||||
int strlength;
|
||||
|
||||
std::string format;
|
||||
|
||||
public:
|
||||
CFormat() { reset(); }
|
||||
|
||||
void set( std::ostream& out );
|
||||
|
||||
private:
|
||||
void reset();
|
||||
};
|
||||
|
||||
/****************************************/
|
||||
// all the errors that are thrown
|
||||
// are a cause of a mistake with %* or %*m$
|
||||
class Error
|
||||
{
|
||||
public:
|
||||
std::string err;
|
||||
Error( std::string s ) : err( s ) {}
|
||||
};
|
||||
|
||||
/****************************************/
|
||||
|
||||
template <class A, class B, class C, class D, class E, class F>
|
||||
class Format
|
||||
{
|
||||
private:
|
||||
struct Arg
|
||||
{
|
||||
bool is_int;
|
||||
bool is_string;
|
||||
};
|
||||
|
||||
Arg args[6];
|
||||
|
||||
std::string format;
|
||||
|
||||
A a;
|
||||
B b;
|
||||
C c;
|
||||
D d;
|
||||
E e;
|
||||
F f;
|
||||
|
||||
unsigned int num_of_args;
|
||||
|
||||
std::string s;
|
||||
|
||||
public:
|
||||
Format( const std::string &format, A a, B b, C c, D d, E e, F f, unsigned int num_of_args );
|
||||
|
||||
std::string get_string() const { return s; }
|
||||
|
||||
private:
|
||||
void parse();
|
||||
|
||||
template <class N> bool is_int( N &n ) { return false; }
|
||||
bool is_int( int &n ) { return true; }
|
||||
bool is_int( unsigned int &n ) { return true; }
|
||||
bool is_int( short &n ) { return true; }
|
||||
bool is_int( unsigned short ) { return true; }
|
||||
|
||||
template <class S> bool is_string( S &s ) { return false; }
|
||||
bool is_string( std::string& s ) { return true; }
|
||||
bool is_string( const std::string& s ) { return true; }
|
||||
bool is_string( char* ) { return true; }
|
||||
bool is_string( const char* ) { return true; }
|
||||
|
||||
int get_int_arg( unsigned int num );
|
||||
void gen_arg_list();
|
||||
std::string use_arg( unsigned int i, const CFormat &cf );
|
||||
|
||||
template <class S> std::string x2s( S ss, const CFormat &cf )
|
||||
{
|
||||
#ifdef HAVE_STL_SSTREAM
|
||||
std::stringstream str;
|
||||
str << cf << ss;
|
||||
std::string st = str.str();
|
||||
return st;
|
||||
#else
|
||||
std::strstream str;
|
||||
str << cf << ss << std::ends;
|
||||
std::string st = str.str();
|
||||
str.freeze(0);
|
||||
return st;
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
int skip_atoi( std::string s, ST start, ST& pos );
|
||||
|
||||
} // namespace Format
|
||||
|
||||
inline std::ostream& operator<<( std::ostream& out, Format::CFormat cf )
|
||||
{
|
||||
cf.set( out );
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
template <class A, class B, class C, class D, class E, class F>
|
||||
Format::Format<A,B,C,D,E,F>::Format( std::string const &format, A a, B b, C c, D d, E e, F f, unsigned int num_of_args )
|
||||
: format( format ), a(a), b(b), c(c), d(d), e(e), f(f), num_of_args( num_of_args )
|
||||
{
|
||||
if( num_of_args > 6 )
|
||||
throw Error( "Number of args out of range" );
|
||||
|
||||
gen_arg_list();
|
||||
|
||||
parse();
|
||||
}
|
||||
|
||||
template <class A, class B, class C, class D, class E, class F>
|
||||
int Format::Format<A,B,C,D,E,F>::get_int_arg( unsigned int num )
|
||||
{
|
||||
if( static_cast<unsigned int>(num) > num_of_args - 1 )
|
||||
throw Error( "The arg you wan't to use is out of range" );
|
||||
|
||||
if( num < 0 )
|
||||
throw Error( "negativ number for arg number not allowed" );
|
||||
|
||||
if( args[num].is_int )
|
||||
{
|
||||
switch( num )
|
||||
{
|
||||
case 0: return *((int*) &a); // I have to cast here cause the compiler
|
||||
case 1: return *((int*) &b); // will make troubles if any of these
|
||||
case 2: return *((int*) &c); // values is not an unsigned int.
|
||||
case 3: return *((int*) &d); // Even if we are sure that
|
||||
case 4: return *((int*) &e); // an unsigned int value will be returned
|
||||
case 5: return *((int*) &f);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw Error( "expecting int arg" );
|
||||
|
||||
return 0; // should never be reached
|
||||
}
|
||||
|
||||
template <class A, class B, class C, class D, class E, class F>
|
||||
void Format::Format<A,B,C,D,E,F>::gen_arg_list()
|
||||
{
|
||||
for( unsigned int i = 0; i < num_of_args; i++ )
|
||||
{
|
||||
switch( i )
|
||||
{
|
||||
case 0:
|
||||
args[i].is_int = is_int( a );
|
||||
args[i].is_string = is_string( a );
|
||||
break;
|
||||
case 1:
|
||||
args[i].is_int = is_int( b );
|
||||
args[i].is_string = is_string( b );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
args[i].is_int = is_int( c );
|
||||
args[i].is_string = is_string( c );
|
||||
break;
|
||||
|
||||
case 3:
|
||||
args[i].is_int = is_int( d );
|
||||
args[i].is_string = is_string( d );
|
||||
break;
|
||||
|
||||
case 4:
|
||||
args[i].is_int = is_int( e );
|
||||
args[i].is_string = is_string( e );
|
||||
break;
|
||||
|
||||
case 5:
|
||||
args[i].is_int = is_int( f );
|
||||
args[i].is_string = is_string( f );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class A, class B, class C, class D, class E, class F>
|
||||
std::string Format::Format<A,B,C,D,E,F>::use_arg( unsigned int i, const CFormat &cf )
|
||||
{
|
||||
if( i > num_of_args || i < 0 )
|
||||
throw Error( "out of arg range" );
|
||||
|
||||
switch( i )
|
||||
{
|
||||
case 0: return x2s( a, cf );
|
||||
case 1: return x2s( b, cf );
|
||||
case 2: return x2s( c, cf );
|
||||
case 3: return x2s( d, cf );
|
||||
case 4: return x2s( e, cf );
|
||||
case 5: return x2s( f, cf );
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
template <class A, class B, class C, class D, class E, class F>
|
||||
void Format::Format<A,B,C,D,E,F>::parse()
|
||||
{
|
||||
if( format.empty() )
|
||||
return;
|
||||
|
||||
unsigned int par = 0;
|
||||
unsigned int use_par = 0;
|
||||
ST pos = 0;
|
||||
ST len = format.size();
|
||||
s = "";
|
||||
bool had_precision = false;
|
||||
|
||||
while( par < num_of_args && pos < len )
|
||||
{ // while
|
||||
|
||||
use_par = par;
|
||||
|
||||
if( pos >= len )
|
||||
break;
|
||||
|
||||
if( format[pos] != '%' )
|
||||
{
|
||||
s += format[pos];
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// % digit found
|
||||
pos++;
|
||||
|
||||
if( !(pos < len ) || (format[pos] == '%') )
|
||||
{
|
||||
// %% -> %
|
||||
s += format[pos];
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// format string found
|
||||
|
||||
ST start = pos - 1;
|
||||
CFormat f;
|
||||
|
||||
// process flags
|
||||
|
||||
while( (pos < len) )
|
||||
{
|
||||
bool finished = false;
|
||||
|
||||
switch( format[pos] )
|
||||
{
|
||||
case '-' : f.adjust = CFormat::LEFT; break;
|
||||
case '+' : f.sign = true; break;
|
||||
case ' ' : f.zero = false; break;
|
||||
case '#' : f.special = true; break;
|
||||
case '\'': f.grouping = true; break;
|
||||
case 'I' : f.conversion = true; break;
|
||||
case '0' : f.zero = true; break;
|
||||
default: finished = true; break;
|
||||
}
|
||||
|
||||
if( finished )
|
||||
break;
|
||||
|
||||
pos++;
|
||||
} // while( (pos < len) )
|
||||
|
||||
// get argument number
|
||||
if( pos < len )
|
||||
{
|
||||
// search for the $ digit
|
||||
unsigned int dp = pos;
|
||||
|
||||
while( dp < len && IS_DIGIT( format[dp] ) )
|
||||
dp++;
|
||||
|
||||
if( dp < len && format[dp] == '$' )
|
||||
{
|
||||
use_par = skip_atoi( format, pos, pos ) - 1;
|
||||
pos = dp + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// get field with
|
||||
if( pos < len )
|
||||
{
|
||||
if( IS_DIGIT( format[pos] ) )
|
||||
f.width = skip_atoi( format, pos, pos );
|
||||
else if( format[pos] == '*' )
|
||||
{
|
||||
pos++;
|
||||
|
||||
// search for the $ digit
|
||||
unsigned int dp = pos;
|
||||
|
||||
while( dp < len && IS_DIGIT( format[dp] ) )
|
||||
dp++;
|
||||
|
||||
if( dp < len && format[dp] == '$' )
|
||||
{
|
||||
f.width = get_int_arg( skip_atoi( format, pos, pos ) - 1 );
|
||||
// skip $ sign
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
f.width = get_int_arg( par );
|
||||
|
||||
if( use_par == par )
|
||||
use_par++;
|
||||
|
||||
par++;
|
||||
}
|
||||
|
||||
if( f.width < 0 )
|
||||
{
|
||||
f.width *= -1;
|
||||
f.adjust = CFormat::LEFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// precision
|
||||
if( pos < len )
|
||||
{
|
||||
if( format[pos] == '.' )
|
||||
{
|
||||
pos++;
|
||||
if( !(pos < len) )
|
||||
return;
|
||||
|
||||
had_precision = true;
|
||||
|
||||
if( IS_DIGIT( format[pos] ) )
|
||||
f.precision = skip_atoi( format, pos, pos );
|
||||
else if( format[pos] == '*' )
|
||||
{
|
||||
pos++;
|
||||
|
||||
|
||||
// search for the $ digit
|
||||
unsigned int dp = pos;
|
||||
|
||||
while( dp < len && IS_DIGIT( format[dp] ) )
|
||||
dp++;
|
||||
|
||||
if( dp < len && format[dp] == '$' )
|
||||
{
|
||||
f.precision = get_int_arg( skip_atoi( format, pos, pos ) - 1 );
|
||||
// skip $ sign
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
f.precision = get_int_arg( par );
|
||||
|
||||
if( use_par == par )
|
||||
use_par++;
|
||||
|
||||
par++;
|
||||
}
|
||||
|
||||
if( f.precision == 0)
|
||||
f.precision_explicit = true;
|
||||
|
||||
if( f.precision < 0 )
|
||||
f.precision = 0;
|
||||
}
|
||||
else
|
||||
f.precision = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// lenght modifier
|
||||
/*
|
||||
they will be ignored
|
||||
cause we know the types of the parameter
|
||||
*/
|
||||
if( (pos < len) )
|
||||
{
|
||||
bool hh = false;
|
||||
bool ll = false;
|
||||
bool found = false;
|
||||
|
||||
switch( format[pos] )
|
||||
{
|
||||
case 'h': hh = true; found = true; break;
|
||||
case 'l': ll = true; found = true; break;
|
||||
case 'L':
|
||||
case 'q':
|
||||
case 'j':
|
||||
case 'z':
|
||||
case 't': found = true; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if(found )
|
||||
{
|
||||
pos++;
|
||||
|
||||
if( pos < len )
|
||||
if( hh == true )
|
||||
{
|
||||
if( format[pos] == 'h' )
|
||||
pos++;
|
||||
}
|
||||
else if( ll = true )
|
||||
if( format[pos] == 'l' )
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
// conversion specifier
|
||||
|
||||
if( pos < len )
|
||||
{
|
||||
bool invalid = false;
|
||||
switch( format[pos] )
|
||||
{
|
||||
case 'd':
|
||||
case 'i':
|
||||
f.base = CFormat::DEC;
|
||||
if( f.zero && (f.adjust != CFormat::LEFT) )
|
||||
f.internal = true;
|
||||
break;
|
||||
|
||||
case 'X': f.setupper = true;
|
||||
case 'x':
|
||||
f.base = CFormat::HEX;
|
||||
if( f.special )
|
||||
f.showbase = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
f.base = CFormat::OCT;
|
||||
if( f.special )
|
||||
f.showbase = true;
|
||||
break;
|
||||
|
||||
|
||||
case 'E':
|
||||
f.setupper = true;
|
||||
|
||||
case 'e':
|
||||
if( f.special )
|
||||
f.sign = true;
|
||||
f.floating = CFormat::SCIENTIFIC;
|
||||
break;
|
||||
|
||||
case 'F': // not supported
|
||||
case 'f':
|
||||
if( f.special )
|
||||
f.sign = true;
|
||||
f.floating = CFormat::FIXED;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if( f.zero )
|
||||
f.zero = false;
|
||||
break;
|
||||
|
||||
|
||||
// unsupported modifiers
|
||||
|
||||
|
||||
case 'G':
|
||||
case 'g':
|
||||
|
||||
case 'A':
|
||||
case 'a':
|
||||
|
||||
case 'c':
|
||||
|
||||
case 'C':
|
||||
case 'S':
|
||||
case 'P':
|
||||
case 'n': break;
|
||||
|
||||
default: invalid = true;
|
||||
}
|
||||
|
||||
if( !invalid )
|
||||
f.valid = true;
|
||||
}
|
||||
|
||||
if( f.valid )
|
||||
{
|
||||
std::string str;
|
||||
int upar = par;
|
||||
|
||||
if( use_par != par )
|
||||
upar = use_par;
|
||||
|
||||
if( f.base == CFormat::HEX && had_precision && f.special )
|
||||
{
|
||||
CFormat f2;
|
||||
f2.base = f.base;
|
||||
std::string s = use_arg( upar, f2 );
|
||||
f.strlength = s.size();
|
||||
// printf( "str: %s\n", s.c_str() );
|
||||
}
|
||||
|
||||
str = use_arg( upar, f );
|
||||
|
||||
// cut string
|
||||
if( had_precision && args[upar].is_string )
|
||||
str = str.substr( 0, f.precision );
|
||||
|
||||
s += str;
|
||||
|
||||
if( use_par == par )
|
||||
par++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy the invalid format string
|
||||
for( ST i = start; i<= pos; i++ )
|
||||
if( i < len )
|
||||
s += format[i];
|
||||
}
|
||||
|
||||
pos++;
|
||||
|
||||
} // while
|
||||
|
||||
if( pos < len )
|
||||
{
|
||||
while( pos < len )
|
||||
{
|
||||
s += format[pos];
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // ifndef NFORMAT
|
||||
|
||||
/// converts anything to a string
|
||||
template<class T>std::string x2s( T what )
|
||||
{
|
||||
#ifdef HAVE_STL_SSTREAM
|
||||
|
||||
std::stringstream str;
|
||||
|
||||
str << what;
|
||||
std::string s( str.str() );
|
||||
return s;
|
||||
|
||||
#else
|
||||
|
||||
std::strstream str;
|
||||
|
||||
str << what << std::ends;
|
||||
|
||||
std::string s( str.str() );
|
||||
|
||||
str.freeze(0);
|
||||
|
||||
return s;
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace Format
|
||||
{
|
||||
|
||||
template <class T> const char* convert( T t ) { return x2s( t ).c_str(); }
|
||||
|
||||
#define DEF( TYPE ) \
|
||||
inline TYPE convert( TYPE t ) { return t; }
|
||||
|
||||
DEF( unsigned )
|
||||
DEF( int )
|
||||
DEF( char )
|
||||
DEF( char* )
|
||||
DEF( const char* )
|
||||
DEF( short )
|
||||
DEF( double )
|
||||
DEF( float )
|
||||
DEF( long )
|
||||
|
||||
#undef DEF
|
||||
|
||||
|
||||
template<class A, class B, class C, class D, class E, class F>
|
||||
class Format
|
||||
{
|
||||
std::string s;
|
||||
|
||||
public:
|
||||
Format( const std::string &format, A a, B b, C c, D d, E e, F f, unsigned int num_of_args )
|
||||
{
|
||||
#define D( T ) convert( T )
|
||||
unsigned buffer_size = 256;
|
||||
|
||||
bool cont = false;
|
||||
|
||||
do {
|
||||
|
||||
cont = false;
|
||||
|
||||
char *buffer = new char[buffer_size];
|
||||
int n = 0;
|
||||
|
||||
switch( num_of_args )
|
||||
{
|
||||
case 1: n = std::sprintf( buffer, format.c_str(),
|
||||
D( a ) ); break;
|
||||
case 2: n = std::sprintf( buffer, format.c_str(),
|
||||
D( a ), D( b ) ); break;
|
||||
case 3: n = std::sprintf( buffer, format.c_str(),
|
||||
D( a ), D( b ), D( c ) ); break;
|
||||
case 4: n = std::sprintf( buffer, format.c_str(),
|
||||
D( a ), D( b ), D( c ), D( d ) ); break;
|
||||
case 5: n = std::sprintf( buffer, format.c_str(),
|
||||
D( a ), D( b ), D( c ), D( d ), D( e ) ); break;
|
||||
case 6: n = std::sprintf( buffer, format.c_str(),
|
||||
D( a ), D( b ), D( c ), D( d ), D( e ), D( f ) ); break;
|
||||
}
|
||||
|
||||
|
||||
if( (unsigned) n >= buffer_size - 2 )
|
||||
{
|
||||
buffer_size *= 2;
|
||||
cont = true;
|
||||
n = 0;
|
||||
}
|
||||
|
||||
for( int i = 0; i < n; i++ )
|
||||
s += buffer[i];
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
} while( cont );
|
||||
#undef D
|
||||
}
|
||||
|
||||
std::string get_string() const { return s; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <class A, class B, class C, class D, class E, class F>
|
||||
inline std::string format( std::string fs, A a, B b, C c, D d, E e, F f )
|
||||
{
|
||||
return Format::Format<A,B,C,D,E,F>( fs, a, b, c, d, e, f, 6).get_string();
|
||||
}
|
||||
|
||||
template <class A, class B, class C, class D, class E>
|
||||
inline std::string format( std::string fs, A a, B b, C c, D d, E e )
|
||||
{
|
||||
return Format::Format<A,B,C,D,E,char>( fs, a, b, c, d, e, 0, 5).get_string();
|
||||
}
|
||||
|
||||
template <class A, class B, class C, class D>
|
||||
inline std::string format( std::string fs, A a, B b, C c, D d)
|
||||
{
|
||||
return Format::Format<A,B,C,D,char,char>( fs, a, b, c, d, 0, 0, 4).get_string();
|
||||
}
|
||||
|
||||
template <class A, class B, class C>
|
||||
inline std::string format( std::string fs, A a, B b, C c )
|
||||
{
|
||||
return Format::Format<A,B,C,char,char,char>( fs, a, b, c, 0, 0, 0, 3).get_string();
|
||||
}
|
||||
|
||||
template <class A, class B>
|
||||
inline std::string format( std::string fs, A a, B b )
|
||||
{
|
||||
return Format::Format<A,B,char,char,char,char>( fs, a, b, 0, 0, 0, 0, 2).get_string();
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline std::string format( std::string fs, A a)
|
||||
{
|
||||
return Format::Format<A,char,char,char,char,char>( fs, a, 0, 0, 0, 0, 0, 1).get_string();
|
||||
}
|
||||
|
||||
|
||||
namespace Format
|
||||
{
|
||||
template<typename ostream> class PrintF
|
||||
{
|
||||
private:
|
||||
|
||||
int level;
|
||||
int dlevel;
|
||||
|
||||
int dmodule;
|
||||
int module;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
ostream &out;
|
||||
|
||||
public:
|
||||
|
||||
PrintF( ostream &out = std::cout, int module = -1, int debug_level = -1 )
|
||||
: level( debug_level ), dlevel( debug_level ),
|
||||
dmodule( module), module( module), out( out )
|
||||
{}
|
||||
|
||||
void set_debug_level( int dlevel_ ) { dlevel = dlevel_; }
|
||||
void set_module( int module_ ) { dmodule = module_; }
|
||||
|
||||
PrintF operator()( int module_ )
|
||||
{
|
||||
PrintF printf( *this );
|
||||
printf.module = module_;
|
||||
|
||||
return printf;
|
||||
}
|
||||
|
||||
PrintF operator[]( int level_ )
|
||||
{
|
||||
PrintF printf( *this );
|
||||
printf.level = level_;
|
||||
|
||||
return printf;
|
||||
}
|
||||
|
||||
template<typename T> PrintF& operator<<( const T &t )
|
||||
{
|
||||
if( check() )
|
||||
out << t;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// io manipulator overloading
|
||||
PrintF& operator<<(ostream& (*f)(ostream&))
|
||||
{
|
||||
if( check() )
|
||||
out << f;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PrintF& operator()( std::string fs )
|
||||
{
|
||||
if( check() )
|
||||
out << fs;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<typename A> PrintF& operator()( std::string fs, const A &a )
|
||||
{
|
||||
if( check() )
|
||||
out << format( fs, a );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
PrintF& operator()( std::string fs, const A &a, const B &b )
|
||||
{
|
||||
if( check() )
|
||||
out << format( fs, a, b );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C>
|
||||
PrintF& operator()( std::string fs, const A &a, const B &b, const C &c )
|
||||
{
|
||||
if( check() )
|
||||
out << format( fs, a, b, c );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C, typename D>
|
||||
PrintF& operator()( std::string fs, const A &a, const B &b, const C &c, const D &d )
|
||||
{
|
||||
if( check() )
|
||||
out << format( fs, a, b, c, d );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C, typename D, typename E>
|
||||
PrintF& operator()( std::string fs, const A &a, const B &b, const C &c, const D &d, const E &e )
|
||||
{
|
||||
if( check() )
|
||||
out << format( fs, a, b, c, d, e );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F>
|
||||
PrintF& operator()( std::string fs, const A &a, const B &b, const C &c, const D &d, const E &e, const F &f )
|
||||
{
|
||||
if( check() )
|
||||
out << format( fs, a, b, c, d, e, f );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool check( int module, int level ) const
|
||||
{
|
||||
if( module == dmodule || dmodule == -1 )
|
||||
{
|
||||
if( dlevel == -1 )
|
||||
return true;
|
||||
|
||||
if( level <= dlevel )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool check() const { return check( module, level ); }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#undef IS_DIGIT
|
||||
|
||||
#endif
|
2567
engine/Utilities/sigslot.h
Normal file
2567
engine/Utilities/sigslot.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user