Added ChatServer and soePlatform

This commit is contained in:
Anonymous
2014-01-17 03:40:51 -07:00
parent 26b88b4533
commit 4fae2dfe0f
183 changed files with 64549 additions and 0 deletions
@@ -0,0 +1,299 @@
////////////////////////////////////////////////////////////////////////////////
// The author of this code is Justin Randall
//
// I have made modifications to the ByteStream
// and AutoByteStream classes in order to make them suitable
// for use in messaging systems which require objects that
// are copyable and assignable. It is also desirable for
// the ByteStream object to use a flexible allocator system
// that may support multi-threaded programming models.
#include "Archive.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
////////////////////////////////////////////////////////////////////////////////
#if defined(USE_ARCHIVE_MUTEX)
CMutex ByteStreamMutex;
#endif
// Default to Data object reuse
bool ByteStream::ms_reuseData = true;
#if defined (PASCAL_STRING)
#pragma message ("--- Packing pascal style strings ---")
unsigned get(Base::ByteStream::ReadIterator& source, std::string& target)
{
unsigned int size = 0;
if (source.getSize() < sizeof(size))
{
return 0;
}
Base::get (source, size);
const unsigned char *buf = source.getBuffer();
target.assign((const char *)buf, (const char *)(buf + size));
const unsigned int readSize = size * sizeof(char);
source.advance(readSize);
return (readSize + sizeof(size));
}
void put(ByteStream& target, const std::string& source)
{
const unsigned int size = source.size();
put(target, size);
target.put(source.data(), size * sizeof (char));
}
#else
#pragma message ("--- Packing c style strings ---")
unsigned get(ByteStream::ReadIterator & source, std::string & target)
{
target = reinterpret_cast<const char *>(source.getBuffer());
if (target.length() > source.getSize())
return 0;
source.advance(target.length() + 1);
return (target.length() + 1);
}
void put(ByteStream & target, const std::string & source)
{
target.put(source.c_str(), source.size()+1);
}
#endif
ByteStream::ReadIterator::ReadIterator() :
readPtr(0),
stream(0)
{
}
ByteStream::ReadIterator::ReadIterator(const ReadIterator & source) :
readPtr(source.readPtr),
stream(source.stream)
{
}
ByteStream::ReadIterator::ReadIterator(const ByteStream & source) :
readPtr(0),
stream(&source)
{
}
ByteStream::ReadIterator::~ReadIterator()
{
stream = 0;
}
ByteStream::ByteStream() :
allocatedSize(0),
beginReadIterator(),
data(NULL),
size(0),
lastPutSize(0)
{
data = Data::getNewData();
beginReadIterator = ReadIterator(*this);
}
ByteStream::ByteStream(const unsigned char * const newBuffer, const unsigned int bufferSize) :
allocatedSize(bufferSize),
data(0),
size(bufferSize),
lastPutSize(0)
{
data = Data::getNewData();
if(data->size < size)
{
delete[] data->buffer;
data->buffer = new unsigned char[size];
data->size = size;
}
memcpy(data->buffer, newBuffer, size);
beginReadIterator = ReadIterator(*this);
}
ByteStream::ByteStream(const ByteStream & source):
allocatedSize(source.getSize()), // only allocate what is really there, be opportinistic when grow()'ing
data(source.data),
size(source.getSize()),
lastPutSize(source.lastPutSize)
{
source.data->ref();
beginReadIterator = ReadIterator(*this);
}
ByteStream::ByteStream(ReadIterator & source) :
allocatedSize(0),
size(0),
lastPutSize(0)
{
data = Data::getNewData();
put(source.getBuffer(), source.getSize());
source.advance(source.getSize());
beginReadIterator = ReadIterator(*this);
}
ByteStream::~ByteStream()
{
data->deref();
allocatedSize = 0;
data = 0; //lint !e672 (data deref insures the data is deleted if no one references it)
size = 0;
}
ByteStream & ByteStream::operator=(const ByteStream & rhs)
{
if(this != &rhs)
{
data->deref(); // deref local data
rhs.data->ref();
allocatedSize = rhs.allocatedSize;
size = rhs.size;
data = rhs.data; //lint !e672 (data is ref counted)
}
return *this;
}
void ByteStream::get(void * target, ReadIterator & readIterator, const unsigned long int targetSize) const
{
assert(readIterator.getReadPosition() + targetSize <= allocatedSize);
memcpy(target, &data->buffer[readIterator.getReadPosition()], targetSize);
}
void ByteStream::put(const void * const source, const unsigned int sourceSize)
{
if(data->getRef() > 1)
{
const unsigned char * const tmp = data->buffer;
data->deref();
data = Data::getNewData();
if(data->size < sourceSize)
{
delete[] data->buffer;
data->buffer = new unsigned char[size];
data->size = size;
}
memcpy(data->buffer, tmp, size);
allocatedSize = size;
}
growToAtLeast(size + sourceSize);
memcpy(&data->buffer[size], source, sourceSize);
size += sourceSize;
if (sourceSize > 0)
lastPutSize = sourceSize;
}
bool ByteStream::overwriteEnd(const void * const source, const unsigned int sourceSize)
{
if(data->getRef() <= 1 &&
lastPutSize == sourceSize &&
sourceSize <= data->size)
{
memcpy(&data->buffer[size-sourceSize], source, sourceSize);
return true;
}
else
{
return false;
}
}
void ByteStream::reAllocate(const unsigned int newSize)
{
allocatedSize = newSize;
if(data->size < allocatedSize)
{
unsigned char * tmp = new unsigned char[newSize];
if(data->buffer != NULL)
memcpy(tmp, data->buffer, size);
delete[] data->buffer;
data->buffer = tmp;
data->size = newSize;
}
}
////////////////////////////////////////////////////////////////////////////////
AutoByteStream::AutoByteStream() :
members()
{
}
AutoByteStream::~AutoByteStream()
{
}
void AutoByteStream::addVariable(AutoVariableBase & newVariable)
{
members.push_back(&newVariable);
}
const unsigned int AutoByteStream::getItemCount() const
{
return members.size();
}
void AutoByteStream::pack(ByteStream & target) const
{
std::vector<AutoVariableBase *>::const_iterator i;
unsigned short packedSize=static_cast<unsigned short>(members.size());
put(target,packedSize);
for(i = members.begin(); i != members.end(); ++i)
{
(*i)->pack(target);
}
}
void AutoByteStream::unpack(ByteStream::ReadIterator & source)
{
std::vector<AutoVariableBase *>::iterator i;
unsigned short packedSize;
get(source,packedSize);
for(i = members.begin(); i != members.end(); ++i)
{
(*i)->unpack(source);
}
}
////////////////////////////////////////////////////////////////////////////////
AutoVariableBase::AutoVariableBase()
{
}
AutoVariableBase::~AutoVariableBase()
{
}
////////////////////////////////////////////////////////////////////////////////
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,756 @@
////////////////////////////////////////////////////////////////////////////////
// The author of this code is Justin Randall
//
// I have made modifications to the ByteStream
// and AutoByteStream classes in order to make them suitable
// for use in messaging systems which require objects that
// are copyable and assignable. It is also desirable for
// the ByteStream object to use a flexible allocator system
// that may support multi-threaded programming models.
#ifndef BASE_ARCHIVE_H
#define BASE_ARCHIVE_H
#include <assert.h>
#include <string>
#include <vector>
#include "Platform.h"
#include "Mutex.h"
#if defined _MT || defined _REENTRANT
# define USE_ARCHIVE_MUTEX
#endif
#ifdef WIN32
# include "win32/Archive.h"
#elif linux
# include "linux/Archive.h"
#elif sparc
# include "solaris/Archive.h"
#else
#error /Base/Archive.h: Undefine platform type
#endif
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
const unsigned MAX_ARRAY_SIZE = 1024;
////////////////////////////////////////////////////////////////////////////////
#if defined(USE_ARCHIVE_MUTEX)
extern CMutex ByteStreamMutex;
#endif
class ByteStream
{
public:
class ReadIterator
{
public:
ReadIterator();
ReadIterator(const ReadIterator & source);
explicit ReadIterator(const ByteStream & source);
~ReadIterator();
ReadIterator & operator = (const ReadIterator & source);
void advance (const unsigned int distance);
unsigned get (void * target, const unsigned long int readSize);
const unsigned int getSize () const;
const unsigned char * const getBuffer () const;
const unsigned int getReadPosition () const;
private:
unsigned int readPtr;
const ByteStream * stream;
};
private:
class Data
{
friend class ByteStream;
friend class ReadIterator;
public:
~Data();
static Data * getNewData();
const int getRef () const;
void deref ();
void ref ();
protected:
unsigned char * buffer;
unsigned long size;
private:
struct DataFreeList
{
~DataFreeList()
{
std::vector<ByteStream::Data *>::iterator i;
for(i = freeList.begin(); i != freeList.end(); ++i)
{
delete (*i);
}
};
std::vector<Data *> freeList;
};
Data();
//explicit Data(unsigned char * buffer);
static std::vector<Data *> & getDataFreeList();
static void releaseOldData(Data * oldData);
private:
int refCount;
};
friend class ReadIterator;
public:
ByteStream();
ByteStream(const unsigned char * const buffer, const unsigned int bufferSize);
ByteStream(const ByteStream & source);
virtual ~ByteStream();
public:
ByteStream(ReadIterator & source);
ByteStream & operator = (const ByteStream & source);
ByteStream & operator = (ReadIterator & source);
const ReadIterator & begin() const;
void clear();
const unsigned char * const getBuffer() const;
const unsigned int getSize() const;
void put(const void * const source, const unsigned int sourceSize);
bool overwriteEnd(const void * const source, const unsigned int sourceSize);
static bool ms_reuseData;
private:
void get(void * target, ReadIterator & readIterator, const unsigned long int readSize) const;
void growToAtLeast(const unsigned int targetSize);
void reAllocate(const unsigned int newSize);
private:
unsigned int allocatedSize;
ReadIterator beginReadIterator;
Data * data;
unsigned int size;
unsigned int lastPutSize;
};
inline ByteStream::Data::Data() :
buffer(0),
size(0),
refCount(1)
{
}
inline ByteStream::Data::~Data()
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
refCount = 0;
delete[] buffer;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
}
inline void ByteStream::Data::deref()
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
refCount--;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
if(refCount < 1)
releaseOldData(this);
}
inline std::vector<ByteStream::Data *> & ByteStream::Data::getDataFreeList()
{
static DataFreeList freeList;
return freeList.freeList;
}
inline ByteStream::Data * ByteStream::Data::getNewData()
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
Data * result = 0;
if(getDataFreeList().empty())
{
result = new Data;
}
else
{
result = getDataFreeList().back();
getDataFreeList().pop_back();
}
result->refCount = 1;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
return result;
}
inline const int ByteStream::Data::getRef() const
{
return refCount;
}
inline void ByteStream::Data::ref()
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
refCount++;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
}
inline void ByteStream::Data::releaseOldData(ByteStream::Data * oldData)
{
if (ByteStream::ms_reuseData)
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
getDataFreeList().push_back(oldData);
oldData->refCount = 0;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
}
else
{
delete oldData;
}
}
inline ByteStream::ReadIterator & ByteStream::ReadIterator::operator = (const ByteStream::ReadIterator & rhs)
{
if(&rhs != this)
{
readPtr = rhs.readPtr;
stream = rhs.stream;
}
return *this;
}
inline unsigned ByteStream::ReadIterator::get(void * target, const unsigned long int readSize)
{
assert(stream);
stream->get(target, *this, readSize);
readPtr += readSize;
return readSize;
}
inline const unsigned int ByteStream::ReadIterator::getSize() const
{
assert(stream);
return stream->getSize() - readPtr;
}
inline const ByteStream::ReadIterator & ByteStream::begin() const
{
return beginReadIterator;
}
inline void ByteStream::ReadIterator::advance(const unsigned int distance)
{
readPtr += distance;
}
inline const unsigned int ByteStream::ReadIterator::getReadPosition() const
{
return readPtr;
}
inline const unsigned char * const ByteStream::ReadIterator::getBuffer() const
{
if(stream)
return &stream->data->buffer[readPtr];
return 0;
}
inline void ByteStream::clear()
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
size = 0;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
}
inline const unsigned char * const ByteStream::getBuffer() const
{
return data->buffer;
}
inline const unsigned int ByteStream::getSize() const
{
return size;
}
inline void ByteStream::growToAtLeast(const unsigned int targetSize)
{
if(allocatedSize < targetSize)
{
reAllocate(allocatedSize + allocatedSize + targetSize);
}
}
////////////////////////////////////////////////////////////////////////////////
class AutoVariableBase
{
public:
AutoVariableBase();
virtual ~AutoVariableBase();
virtual void pack(ByteStream & target) const = 0;
virtual void unpack(ByteStream::ReadIterator & source) = 0;
};
////////////////////////////////////////////////////////////////////////////////
class AutoByteStream
{
public:
AutoByteStream();
virtual ~AutoByteStream();
void addVariable(AutoVariableBase & newVariable);
virtual const unsigned int getItemCount() const;
virtual void pack(ByteStream & target) const;
virtual void unpack(ByteStream::ReadIterator & source);
protected:
std::vector<AutoVariableBase *> members;
private:
AutoByteStream(const AutoByteStream & source);
};
////////////////////////////////////////////////////////////////////////////////
template<class ValueType>
class AutoVariable : public AutoVariableBase
{
public:
AutoVariable();
explicit AutoVariable(const ValueType & source);
virtual ~AutoVariable();
const ValueType & get() const;
virtual void pack(ByteStream & target) const;
void set(const ValueType & rhs);
virtual void unpack(ByteStream::ReadIterator & source);
private:
ValueType value;
};
template<class ValueType>
AutoVariable<ValueType>::AutoVariable() :
AutoVariableBase(),
value()
{
}
template<class ValueType>
AutoVariable<ValueType>::AutoVariable(const ValueType & source) :
AutoVariableBase(),
value(source)
{
}
template<class ValueType>
AutoVariable<ValueType>::~AutoVariable()
{
}
template<class ValueType>
const ValueType & AutoVariable<ValueType>::get() const
{
return value;
}
template<class ValueType>
void AutoVariable<ValueType>::pack(ByteStream & target) const
{
Base::put(target, value);
}
template<class ValueType>
void AutoVariable<ValueType>::set(const ValueType & rhs)
{
value = rhs;
}
template<class ValueType>
void AutoVariable<ValueType>::unpack(ByteStream::ReadIterator & source)
{
Base::get(source, value);
}
////////////////////////////////////////////////////////////////////////////////
template<class ValueType>
class AutoArray : public AutoVariableBase
{
public:
AutoArray();
AutoArray(const AutoArray & source);
~AutoArray();
const std::vector<ValueType> & get() const;
void set(const std::vector<ValueType> & source);
virtual void pack(ByteStream & target) const;
virtual void unpack(ByteStream::ReadIterator & source);
private:
std::vector<ValueType> array;
};
template<class ValueType>
inline AutoArray<ValueType>::AutoArray()
{
}
template<class ValueType>
inline AutoArray<ValueType>::AutoArray(const AutoArray & source) :
array(source.array)
{
}
template<class ValueType>
inline AutoArray<ValueType>::~AutoArray()
{
}
template<class ValueType>
inline const std::vector<ValueType> & AutoArray<ValueType>::get() const
{
return array;
}
template<class ValueType>
inline void AutoArray<ValueType>::set(const std::vector<ValueType> & source)
{
array = source;
}
template<class ValueType>
inline void AutoArray<ValueType>::pack(ByteStream & target) const
{
unsigned int arraySize = array.size();
Base::put(target, arraySize);
typename std::vector<ValueType>::const_iterator i;
for(i = array.begin(); i != array.end(); ++i)
{
ValueType v = (*i);
Base::put(target, v);
}
}
template<class ValueType>
inline void AutoArray<ValueType>::unpack(ByteStream::ReadIterator & source)
{
unsigned int arraySize;
Base::get(source, arraySize);
ValueType v;
if (arraySize > MAX_ARRAY_SIZE)
arraySize = 0;
for(unsigned int i = 0; i < arraySize; ++i)
{
Base::get(source, v);
array.push_back(v);
}
}
////////////////////////////////////////////////////////////////////////////////
inline void get(ByteStream::ReadIterator & source, ByteStream & target)
{
target.put(source.getBuffer(), source.getSize());
source.advance(source.getSize());
}
inline void get(ByteStream::ReadIterator & source, double & target)
{
source.get(&target, 8);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, float & target)
{
source.get(&target, 4);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, uint64 & target)
{
source.get(&target, 8);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, int64 & target)
{
source.get(&target, 8);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, uint32 & target)
{
source.get(&target, 4);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, int32 & target)
{
source.get(&target, 4);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, uint16 & target)
{
source.get(&target, 2);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, int16 & target)
{
source.get(&target, 2);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, uint8 & target)
{
source.get(&target, 1);
}
inline void get(ByteStream::ReadIterator & source, int8 & target)
{
source.get(&target, 1);
}
inline unsigned get(ByteStream::ReadIterator & source, unsigned char * const target, const unsigned int targetSize)
{
return source.get(target, targetSize);
}
inline void get(ByteStream::ReadIterator & source, bool & target)
{
source.get(&target, 1);
}
////////////////////////////////////////////////////////////////////////////////
inline void put(ByteStream & target, ByteStream::ReadIterator & source)
{
target.put(source.getBuffer(), source.getSize());
source.advance(source.getSize());
}
inline void put(ByteStream & target, const double value)
{
double temp = byteSwap(value);
target.put(&temp, 8);
}
inline void put(ByteStream & target, const float value)
{
float temp = byteSwap(value);
target.put(&temp, 4);
}
inline void put(ByteStream & target, const uint64 value)
{
uint64 temp = byteSwap(value);
target.put(&temp, 8);
}
inline void put(ByteStream & target, const int64 value)
{
int64 temp = byteSwap(value);
target.put(&temp, 8);
}
inline void put(ByteStream & target, const uint32 value)
{
uint32 temp = byteSwap(value);
target.put(&temp, 4);
}
inline void put(ByteStream & target, const int32 value)
{
int32 temp = byteSwap(value);
target.put(&temp, 4);
}
inline void put(ByteStream & target, const uint16 value)
{
uint16 temp = byteSwap(value);
target.put(&temp, 2);
}
inline void put(ByteStream & target, const int16 value)
{
int16 temp = byteSwap(value);
target.put(&temp, 2);
}
inline void put(ByteStream & target, const uint8 value)
{
target.put(&value, 1);
}
inline void put(ByteStream & target, const int8 value)
{
target.put(&value, 1);
}
inline void put(ByteStream & target, const bool & source)
{
target.put(&source, 1);
}
inline void put(ByteStream & target, const unsigned char * const source, const unsigned int sourceSize)
{
target.put(source, sourceSize);
}
inline void put(ByteStream & target, const ByteStream & source)
{
target.put(source.begin().getBuffer(), source.begin().getSize());
}
unsigned get(ByteStream::ReadIterator & source, std::string & target);
void put(ByteStream & target, const std::string & source);
////////////////////////////////////////////////////////////////////////////////
inline bool overwriteEnd(ByteStream & target, const double value)
{
double temp = byteSwap(value);
return target.overwriteEnd(&temp, 8);
}
inline bool overwriteEnd(ByteStream & target, const float value)
{
float temp = byteSwap(value);
return target.overwriteEnd(&temp, 4);
}
inline bool overwriteEnd(ByteStream & target, const uint64 value)
{
uint64 temp = byteSwap(value);
return target.overwriteEnd(&temp, 8);
}
inline bool overwriteEnd(ByteStream & target, const int64 value)
{
int64 temp = byteSwap(value);
return target.overwriteEnd(&temp, 8);
}
inline bool overwriteEnd(ByteStream & target, const uint32 value)
{
uint32 temp = byteSwap(value);
return target.overwriteEnd(&temp, 4);
}
inline bool overwriteEnd(ByteStream & target, const int32 value)
{
int32 temp = byteSwap(value);
return target.overwriteEnd(&temp, 4);
}
inline bool overwriteEnd(ByteStream & target, const uint16 value)
{
uint16 temp = byteSwap(value);
return target.overwriteEnd(&temp, 2);
}
inline bool overwriteEnd(ByteStream & target, const int16 value)
{
int16 temp = byteSwap(value);
return target.overwriteEnd(&temp, 2);
}
inline bool overwriteEnd(ByteStream & target, const uint8 value)
{
return target.overwriteEnd(&value, 1);
}
inline bool overwriteEnd(ByteStream & target, const int8 value)
{
return target.overwriteEnd(&value, 1);
}
inline bool overwriteEnd(ByteStream & target, const bool & source)
{
return target.overwriteEnd(&source, 1);
}
inline bool overwriteEnd(ByteStream & target, const unsigned char * const source, const unsigned int sourceSize)
{
return target.overwriteEnd(source, sourceSize);
}
////////////////////////////////////////////////////////////////////////////////
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,349 @@
#include "AutoLog.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#ifdef WIN32
#include <direct.h> // for NT directory commands
#define SLASHCHAR "\\"
#define WRONGSLASH '/'
#else
#define SLASHCHAR "/"
#define WRONGSLASH '\\'
#endif
// set default values for global masks
CAutoLog::eLogLevel CAutoLog::nLogMask = eLOG_NORMAL; // what is logged in log files
CAutoLog::eLogLevel CAutoLog::nPrintMask = eLOG_ERROR; // what is printed on the screen
CAutoLog::eLogLevel CAutoLog::nFlushMask = eLOG_ERROR; // when is file flushed on every entry?
// class info
//-------------------------------------
bool CAutoLog::Open(const char * filename)
//-------------------------------------
{
if( NULL == filename)
return false;
if (pFilename)
return false;
pFilename = strdup(filename);
// Sanitize slashes
char *ptr;
while ((ptr = strchr(pFilename,WRONGSLASH)) != NULL)
*ptr = SLASHCHAR[0];
char strPath[1024];
strcpy(strPath,pFilename);
ptr = strrchr(strPath, SLASHCHAR[0]);
if (ptr != NULL)
{
*ptr = 0;
#ifdef WIN32
char curdir[128];
// remember current directory
if( getcwd(curdir,sizeof(curdir)) == NULL )
{
fprintf(stderr,"CAutoLog::Archive failed to get current directory!\n");
free(pFilename);
pFilename = NULL;
return false; // error, can't proceed
}
if (chdir(strPath))
{
// failed to find the directory, so we must create it
if (mkdir(strPath))
{
fprintf(stderr,"CAutoLog::Archive failed to make directory: %s\n", strPath);
free(pFilename);
pFilename = NULL;
return false; // error, can't proceed
}
}
else
{
// found the directory, but we don't want to be there, so go back
chdir(curdir);
}
#else
struct stat SS;
// see if directory exists
if (stat(strPath,&SS))
{
// create directory
if (mkdir(strPath,0777))
{
fprintf(stderr,"CAutoLog::Archive failed to make directory: %s\n", strPath);
free(pFilename);
pFilename = NULL;
return false; // error, can't proceed
}
}
#endif
}
pFile = fopen(pFilename,"a+");
if( pFile == NULL || pFile == (FILE *)-1)
{
//fprintf(stderr,"CAutoLog::Open failed to open log file: %s\n",pFilename);
Close();
return false;
}
time_t t;
time(&t);
struct tm *ptm = localtime(&t);
nTodaysDayOfYear = ptm->tm_yday;
//printf("Open log file: %s\n",pFilename);
return true;
}
//-------------------------------------
void CAutoLog::Close(void)
//-------------------------------------
{
if( pFile != (FILE *)-1 && pFile != NULL)
{
fclose(pFile);
}
pFile = (FILE *)-1;
if (pFilename)
{
free(pFilename);
}
pFilename = NULL;
}
//-------------------------------------
void CAutoLog::LogError(char * format, ...)
{
char strInput[1024];
// parse format and input arguments
va_list varg;
va_start(varg, format);
vsprintf(strInput, format, varg);
va_end(varg);
Log(eLOG_ERROR, strInput);
}
//-------------------------------------
void CAutoLog::LogAlert(char * format, ...)
{
char strInput[1024];
// parse format and input arguments
va_list varg;
va_start(varg, format);
vsprintf(strInput, format, varg);
va_end(varg);
Log(eLOG_ALERT, strInput);
}
//-------------------------------------
void CAutoLog::Log(char * format, ...)
{
char strInput[1024];
// parse format and input arguments
va_list varg;
va_start(varg, format);
vsprintf(strInput, format, varg);
va_end(varg);
Log(eLOG_NORMAL, strInput);
}
//-------------------------------------
void CAutoLog::LogDebug(char * format, ...)
{
char strInput[1024];
// parse format and input arguments
va_list varg;
va_start(varg, format);
vsprintf(strInput, format, varg);
va_end(varg);
Log(eLOG_DEBUG, strInput);
}
//-------------------------------------
void CAutoLog::Log(eLogLevel severity, char *fmt, ...)
//-------------------------------------
{
if (pFile == (FILE *)-1 || pFile == NULL)
{
//fprintf(stderr,"CAutoLog::Log called with no file open!\n");
return;
}
if (nLogMask == eLOG_NONE || nLogMask < severity)
{
if (nPrintMask == eLOG_NONE || nPrintMask < severity)
{ // no point in parsing, we're doing nothing.
return;
}
}
char strTime[128];
char strInput[1024];
char strOutput[1024+128];
time_t t;
// parse format and input arguments
va_list varg;
va_start(varg, fmt);
vsprintf(strInput, fmt, varg);
va_end(varg);
// make timestamp
time(&t);
strftime(strTime, sizeof(strTime), "[%m/%d/%Y %H:%M:%S]", localtime(&t) );
// construct output string
sprintf(strOutput, "%s %s\n", strTime, strInput);
// check to see if current file needs to be archived
Archive();
// log to file
if (!(nLogMask == eLOG_NONE || nLogMask < severity))
{
fwrite(strOutput,strlen(strOutput),1,pFile);
}
// print as standard output
if (!(nPrintMask == eLOG_NONE || nPrintMask < severity))
{
printf("%s", strOutput);
}
// flush file buffer if error is high severity
if (severity <= nFlushMask)
fflush(pFile);
}
//-------------------------------------
void CAutoLog::Archive(void)
//-------------------------------------
{
if( pFile == (FILE *)-1 || pFile == NULL)
{
//fprintf(stderr,"CAutoLog::Archive called with no file open!\n");
return;
}
// check to see if it's time to archive
time_t t;
time(&t);
struct tm *ptm = localtime(&t);
if (ptm->tm_yday == nTodaysDayOfYear)
{
return; // nope, not time to archive
}
nTodaysDayOfYear = ptm->tm_yday;
char strPath[1024];
char strCurrent[1024];
char strTime[128];
char * pCurrent;
#ifdef WIN32
char curdir[128];
#else
struct stat SS;
#endif
strftime(strTime, sizeof(strTime), "%m%d%Y", localtime(&t) ); // numerical time e.g. 041698
strcpy(strCurrent,pFilename);
pCurrent = strrchr(strCurrent, SLASHCHAR[0]);
if (pCurrent != NULL)
*pCurrent = 0;
else
sprintf(strCurrent,".");
sprintf(strPath,"%s"SLASHCHAR"%s", strCurrent, strTime); // logs/041698
#ifdef WIN32
// remember current directory
if( getcwd(curdir,sizeof(curdir)) == NULL )
{
fprintf(stderr,"CAutoLog::Archive failed to get current directory!\n");
return; // error, can't proceed
}
if (chdir(strPath))
{
// failed to find the directory, so we must create it
if (mkdir(strPath))
{
fprintf(stderr,"CAutoLog::Archive failed to make directory: %s\n", strPath);
return; // error, can't proceed
}
}
else
{
// found the directory, but we don't want to be there, so go back
chdir(curdir);
}
#else
// see if directory exists
if (stat(strPath,&SS))
{
// create directory
if (mkdir(strPath,0777))
{
fprintf(stderr,"CAutoLog::Archive failed to make directory: %s\n", strPath);
return; // error, can't proceed
}
}
#endif
pCurrent = strrchr(pFilename, SLASHCHAR[0]);
if (pCurrent == NULL)
pCurrent = pFilename;
else
pCurrent++;
sprintf(strCurrent,"%s"SLASHCHAR"%s",strPath,pCurrent);
fflush(pFile);
fclose(pFile);
rename(pFilename,strCurrent);
pFile = fopen(pFilename,"w+");
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,117 @@
#ifndef _AUTOLOG_H
#define _AUTOLOG_H
#pragma warning (disable : 4786)
#include <stdio.h>
#include <time.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
class CAutoLog
{
public:
enum eLogLevel {
eLOG_NONE = 0, // log entries are discarded
eLOG_ERROR = 1, // log errors only
eLOG_ALERT = 2, // log alerts and errors only
eLOG_NORMAL = 3, // log all normal events, no debug
eLOG_DEBUG = 4 // log everything
};
// Global setting for all AutoLog instances for this application. Can be set on the fly. Default is eLOG_NORMAL.
void SetLogLevel(eLogLevel loglevel);
// Global setting for all AutoLog instances for this application. Can be set on the fly. Default is eLOG_ERROR.
void SetPrintLevel(eLogLevel printlevel);
// Global setting for all AutoLog instances for this application. Can be set on the fly. Default is eLOG_ERROR.
void SetFlushLevel(eLogLevel flushlevel);
// constructor, no file loaded
CAutoLog();
// version of constructor that calls Open(file)
CAutoLog(const char * file);
// destructor, will close file if opened
~CAutoLog();
// Open log file. If a file is already open, function will fail.
// returns true if no error
bool Open(const char * file);
// Close log file if opened.
void Close(void);
// Make an entry in the log. Format and variable arguments are identical to printf.
// severity will be compared to master log level to determine if the log entry will be made
// severity will be compared to master print level to determine if the log entry will be printed to stdout
void Log(eLogLevel severity, char * format, ...);
// Equivalent to the above with the approriate severity argument
void LogError(char * format, ...);
void LogAlert(char * format, ...);
void Log(char * format, ...);
void LogDebug(char * format, ...);
private:
FILE * pFile; // current log file opened
char * pFilename; // current log file opened
int nTodaysDayOfYear; // remember the current day to detect change of day
void Archive(void); // archives current log
static eLogLevel nLogMask; // master severity level
static eLogLevel nPrintMask; // master severity level
static eLogLevel nFlushMask; // master severity level
};
//-------------------------------------
inline void CAutoLog::SetLogLevel(eLogLevel loglevel)
{
nLogMask = loglevel;
}
//-------------------------------------
inline void CAutoLog::SetPrintLevel(eLogLevel printlevel)
{
nPrintMask = printlevel;
}
//-------------------------------------
inline void CAutoLog::SetFlushLevel(eLogLevel flushlevel)
{
nFlushMask = flushlevel;
}
//-------------------------------------
inline CAutoLog::CAutoLog()
{
pFilename = NULL;
pFile = (FILE *)-1;
}
//-------------------------------------
inline CAutoLog::CAutoLog(const char * file)
{
pFilename = NULL;
pFile = (FILE *)-1;
Open(file);
}
//-------------------------------------
inline CAutoLog::~CAutoLog()
{
Close();
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1 @@
#include "Base.h"
@@ -0,0 +1,63 @@
////////////////////////////////////////
// Base.h
//
// Purpose:
// 1. Provide a single header file that may be used to include all
// Base library header files.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef _BASEPCH_H
#define _BASEPCH_H
#ifdef WIN32
#include "win32/Platform.h"
#include "win32/Types.h"
#include "win32/Mutex.h"
#include "win32/Event.h"
#include "win32/Thread.h"
#include "Logger.h"
#include "Config.h"
#include "ScopeLock.h"
#include "Statistics.h"
#include "TemplateObjectAllocator.h"
#include "BlockAllocator.h"
#elif linux
#include "linux/Platform.h"
#include "linux/Types.h"
#include "linux/Mutex.h"
#include "linux/Event.h"
#include "linux/Thread.h"
#include "Logger.h"
#include "Config.h"
#include "ScopeLock.h"
#include "Statistics.h"
#include "TemplateObjectAllocator.h"
#include "BlockAllocator.h"
#elif sparc
#include "solaris/Platform.h"
#include "solaris/Types.h"
#include "solaris/Mutex.h"
#include "solaris/Event.h"
#include "solaris/Thread.h"
#include "Logger.h"
#include "Config.h"
#include "ScopeLock.h"
#include "Statistics.h"
#include "TemplateObjectAllocator.h"
#include "BlockAllocator.h"
#else
#error Base.h: Undefine platform type
#endif
#endif // _BASEPCH_H
@@ -0,0 +1,387 @@
#include "Base64.h"
#include <stdio.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
//----------------------------------------------------------------------------
// Constants
//----------------------------------------------------------------------------
#define BASE64_PAD '='
#define BASE64_PAD_INDEX 64
#define BASE64_ERR ((unsigned char)-1)
#define BASE64_PAD_CODE ((unsigned char)100)
#define BASE64_OUTPUT_LINE 76
#define BASE64_ENCODE_BUFFER ((BASE64_OUTPUT_LINE*3)/4)
#define BASE64_DECODE_ERROR ((unsigned)-1)
#define HEX_ERR 16
#define HEX_LOWER_FORMAT "%2.2x"
#define HEX_UPPER_FORMAT "%2.2X";
const char Base64::ms_base64Table[] =
{
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/',
BASE64_PAD
};
//----------------------------------------------------------------------------
// Functions
//----------------------------------------------------------------------------
unsigned char Base64::GetBase64Code(char base64char)
{
if (base64char == BASE64_PAD)
return BASE64_PAD_CODE;
if (base64char >= 'A' && base64char <= 'Z')
return (unsigned char)(base64char - 'A');
if (base64char >= 'a' && base64char <= 'z')
return (unsigned char)(base64char - 'a' + 26);
if (base64char >= '0' && base64char <= '9')
return (unsigned char)(base64char - '0' + 2*26);
if (base64char == '+')
return 2*26+10;
if (base64char == '/')
return 2*26+11;
return BASE64_ERR;
}
unsigned char Base64::GetHexCode(char hexChar)
{
if (hexChar >= '0' && hexChar <= '9')
return (unsigned char)(hexChar - '0');
if (hexChar >= 'A' && hexChar <= 'F')
return (unsigned char)(hexChar - 'A' + 10);
if (hexChar >= 'a' && hexChar <= 'f')
return (unsigned char)(hexChar - 'a' + 10);
return HEX_ERR;
}
unsigned Base64::UUDecodeQuadToTriple(const char *quad, unsigned char *triple)
{
unsigned char b;
unsigned char quadByteCodes[4];
unsigned bytes = 3, i;
for (i = 0; i < 4; i++)
{
b = GetBase64Code(quad[i]);
if (b == BASE64_PAD_CODE)
{
switch(i)
{
case 0: bytes=0; break;
case 1: bytes=0; break;
case 2: bytes=1; break;
case 3: bytes=2; break;
}
break;
}
else if (b == BASE64_ERR)
{
bytes = BASE64_DECODE_ERROR;
}
else
{
quadByteCodes[i] = b;
}
}
triple[0] = (quadByteCodes[0] << 2) | (quadByteCodes[1] >> 4);
triple[1] = (quadByteCodes[1] << 4) | (quadByteCodes[2] >> 2);
triple[2] = (quadByteCodes[2] << 6) | (quadByteCodes[3] >> 0);
return bytes;
}
bool Base64::UUDecode(const char *source, unsigned sourceLen, unsigned char *dest, unsigned *destLen)
{
unsigned char q[3];
unsigned index;
unsigned bytes;
unsigned char *destIn = dest;
bool noErrors = true;
for (index = 0; index < sourceLen; index += 4)
{
bytes = UUDecodeQuadToTriple(source + index, q);
if (bytes != BASE64_DECODE_ERROR) {
*destLen -= bytes;
if (*destLen >= 0) {
memcpy(dest, (char*)&q, bytes);
} else {
noErrors = false;
}
dest += bytes;
} else {
noErrors = false;
}
}
*destLen = (int)(dest - destIn);
return noErrors;
}
bool Base64::UUDecode(const char *source, unsigned sourceLen, std::string &destString)
{
unsigned char q[3];
unsigned index;
unsigned bytes;
bool noErrors = true;
for (index = 0; index < sourceLen; index += 4)
{
bytes = UUDecodeQuadToTriple(source + index, q);
if (bytes != BASE64_DECODE_ERROR) {
destString.append((char*)&q, bytes);
} else {
noErrors = false;
}
}
return noErrors;
}
unsigned Base64::UUEncodeTripleToQuad(const unsigned char *triple, char* quad, unsigned bytes)
{
unsigned char indices[4];
int quadIndex;
memset(indices, BASE64_PAD_INDEX, sizeof(indices));
switch(bytes)
{
case 3:
indices[3] = (triple[2] ) & 0x0000003F;
indices[2] = (triple[2] >> 6) & 0x0000003F;
case 2:
indices[2] = (indices[2] | (triple[1] << 2)) & 0x0000003F;
indices[1] = (triple[1] >> 4) & 0x0000003F;
case 1:
indices[1] = (indices[1] | (triple[0] << 4)) & 0x0000003F;
indices[0] = (triple[0] >> 2) & 0x0000003F;
case 0:
default:
break;
};
for (quadIndex = 0; quadIndex < 4; quadIndex++) {
quad[quadIndex] = ms_base64Table[indices[quadIndex]];
}
return 0;
}
bool Base64::UUEncode(const unsigned char *source, unsigned sourceLen, char *dest, unsigned destLen)
{
char quad[5];
unsigned z;
bool noErrors = true;
quad[4] = 0;
// The normal case
for(z = 0; z < sourceLen;z += 3)
{
UUEncodeTripleToQuad(source + z,quad,(z + 3 < sourceLen) ? 3 : (sourceLen - z));
destLen -= strlen(quad);
if (destLen > 0) {
dest += sprintf(dest,quad);
} else {
noErrors = false;
}
}
return noErrors;
}
bool Base64::UUEncode(const unsigned char *source, unsigned sourceLen, std::string &destString)
{
char quad[5];
unsigned z;
bool noErrors = true;
quad[4] = 0;
// The normal case
for(z = 0; z < sourceLen;z += 3)
{
UUEncodeTripleToQuad(source + z,quad,(z + 3 < sourceLen) ? 3 : (sourceLen - z));
destString.append(quad);
}
return noErrors;
}
bool Base64::HexEncode(const unsigned char *source, unsigned sourceLen, char *dest, unsigned destLen, bool lowercase)
{
const char *format = lowercase ? HEX_LOWER_FORMAT : HEX_UPPER_FORMAT;
bool noErrors = true;
for (; sourceLen > 0; sourceLen--, source++)
{
if (destLen >= 2) {
destLen -= sprintf(dest, format, *source);
} else {
noErrors = false;
}
}
return noErrors;
}
bool Base64::HexEncode(const unsigned char *source, unsigned sourceLen, std::string &destString, bool lowercase)
{
const char *format = lowercase ? HEX_LOWER_FORMAT : HEX_UPPER_FORMAT;
char hexBuffer[3];
bool noErrors = true;
hexBuffer[2] = '\0';
for (; sourceLen > 0; sourceLen--, source++)
{
hexBuffer[0] = '\0';
sprintf(hexBuffer, format, *source);
destString.append(hexBuffer);
}
return noErrors;
}
bool Base64::HexDecode(const char *source, unsigned sourceLen, unsigned char *dest, unsigned *destLen)
{
unsigned char *destIn = dest;
unsigned char digits[2];
bool noErrors = true;
for (; sourceLen > 1; sourceLen -= 2, source += 2)
{
if (*destLen > 0) {
digits[0] = GetHexCode(source[0]);
digits[1] = GetHexCode(source[1]);
if ((digits[0] != HEX_ERR) && (digits[1] != HEX_ERR)) {
*dest = (digits[0] * 16) + digits[1];
dest++;
(*destLen)--;
} else {
noErrors = false;
}
} else {
noErrors = false;
}
}
*destLen = dest - destIn;
if (sourceLen == 1) {
noErrors = false;
}
return noErrors;
}
bool Base64::HexDecode(const char *source, unsigned sourceLen, std::string &destString)
{
unsigned char digits[2];
unsigned char byte;
bool noErrors = true;
for (; sourceLen > 1; sourceLen -= 2, source += 2)
{
digits[0] = GetHexCode(source[0]);
digits[1] = GetHexCode(source[1]);
if ((digits[0] != HEX_ERR) && (digits[1] != HEX_ERR)) {
byte = (digits[0] * 16) + digits[1];
destString.append((char *)&byte, 1);
} else {
noErrors = false;
}
}
if (sourceLen == 1) {
noErrors = false;
}
return noErrors;
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,42 @@
#ifndef BASE64_H
#define BASE64_H
#include <string>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
class Base64
{
public:
static bool UUEncode(const unsigned char *source, unsigned sourceLen, char *dest, unsigned destLen);
static bool UUEncode(const unsigned char *source, unsigned sourceLen, std::string &destString);
static bool UUDecode(const char *source, unsigned sourceLen, unsigned char *dest, unsigned *destLen);
static bool UUDecode(const char *source, unsigned sourceLen, std::string &destString);
// these don't *exactly* belong here, but it's a convenient place for them
static bool HexEncode(const unsigned char *source, unsigned sourceLen, char *dest, unsigned destLen, bool lowercase = false);
static bool HexEncode(const unsigned char *source, unsigned sourceLen, std::string &destString, bool lowercase = false);
static bool HexDecode(const char *source, unsigned sourceLen, unsigned char *dest, unsigned *destLen);
static bool HexDecode(const char *source, unsigned sourceLen, std::string &destString);
private:
static unsigned UUEncodeTripleToQuad(const unsigned char *triple, char *quad, unsigned bytes);
static unsigned UUDecodeQuadToTriple(const char *quad, unsigned char *triple);
static void Init();
static unsigned char GetBase64Code(char base64char);
static unsigned char GetHexCode(char hexChar);
static const char ms_base64Table[];
};
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // BASE64_H
@@ -0,0 +1,30 @@
#if !defined (BLOCKALLOCATOR_H_)
#define BLOCKALLOCATOR_H_
#include <stdio.h>
#include <stdlib.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
class BlockAllocator
{
public:
BlockAllocator();
~BlockAllocator();
void *getBlock(unsigned accum);
void returnBlock(unsigned *handle);
private:
unsigned *m_blocks[31];
};
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,291 @@
/*------------------------------------------------------
CCmdLine
A utility for parsing command lines.
Copyright (C) 1999 Chris Losinger, Smaller Animals Software.
http://www.smalleranimals.com
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.
See SACmds.h for more info.
------------------------------------------------------*/
#pragma warning (disable: 4267)
// if you're using MFC, you'll need to un-comment this line
// #include "stdafx.h"
#include "CmdLine.h"
//#include "crtdbg.h"
#include <ctype.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
/*------------------------------------------------------
int CCmdLine::SplitLine(int argc, char **argv)
parse the command line into switches and arguments
returns number of switches found
------------------------------------------------------*/
int CCmdLine::SplitLine(int argc, char **argv)
{
clear();
StringType curParam; // current argv[x]
// skip the exe name (start with i = 1)
for (int i = 1; i < argc; i++)
{
// if it's a switch, start a new CCmdLine
if (IsSwitch(argv[i]))
{
curParam = argv[i];
StringType arg;
// look at next input string to see if it's a switch or an argument
if (i + 1 < argc)
{
if (!IsSwitch(argv[i + 1]))
{
// it's an argument, not a switch
arg = argv[i + 1];
// skip to next
i++;
}
else
{
arg = "";
}
}
// add it
CCmdParam cmd;
// only add non-empty args
if (arg != "")
{
cmd.m_strings.push_back(arg);
}
// add the CCmdParam to 'this'
std::pair<CCmdLine::iterator, bool> res = insert(CCmdLine::value_type(curParam, cmd));
if (res.second) continue;
}
else
{
// it's not a new switch, so it must be more stuff for the last switch
// ...let's add it
CCmdLine::iterator theIterator;
// get an iterator for the current param
theIterator = find(curParam);
if (theIterator!=end())
{
(*theIterator).second.m_strings.push_back(argv[i]);
}
else
{
// ??
}
}
}
return size();
}
/*------------------------------------------------------
protected member function
test a parameter to see if it's a switch :
switches are of the form : -x
where 'x' is one or more characters.
the first character of a switch must be non-numeric!
------------------------------------------------------*/
bool CCmdLine::IsSwitch(const char *pParam)
{
if (pParam==NULL)
return false;
// switches must non-empty
// must have at least one character after the '-'
int len = strlen(pParam);
if (len <= 1)
{
return false;
}
// switches always start with '-'
if (pParam[0]=='-')
{
// allow negative numbers as arguments.
// ie., don't count them as switches
return (!isdigit(pParam[1]));
}
else
{
return false;
}
}
/*------------------------------------------------------
bool CCmdLine::HasSwitch(const char *pSwitch)
was the switch found on the command line ?
ex. if the command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
call return
---- ------
cmdLine.HasSwitch("-a") true
cmdLine.HasSwitch("-z") false
------------------------------------------------------*/
bool CCmdLine::HasSwitch(const char *pSwitch)
{
CCmdLine::iterator theIterator;
theIterator = find(pSwitch);
return (theIterator!=end());
}
/*------------------------------------------------------
StringType CCmdLine::GetSafeArgument(const char *pSwitch, int iIdx, const char *pDefault)
fetch an argument associated with a switch . if the parameter at
index iIdx is not found, this will return the default that you
provide.
example :
command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
call return
---- ------
cmdLine.GetSafeArgument("-a", 0, "zz") p1
cmdLine.GetSafeArgument("-a", 1, "zz") p2
cmdLine.GetSafeArgument("-b", 0, "zz") p4
cmdLine.GetSafeArgument("-b", 1, "zz") zz
------------------------------------------------------*/
StringType CCmdLine::GetSafeArgument(const char *pSwitch, int iIdx, const char *pDefault)
{
StringType sRet;
if (pDefault!=NULL)
sRet = pDefault;
try
{
sRet = GetArgument(pSwitch, iIdx);
}
catch (...)
{
}
return sRet;
}
/*------------------------------------------------------
StringType CCmdLine::GetArgument(const char *pSwitch, int iIdx)
fetch a argument associated with a switch. throws an exception
of (int)0, if the parameter at index iIdx is not found.
example :
command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
call return
---- ------
cmdLine.GetArgument("-a", 0) p1
cmdLine.GetArgument("-b", 1) throws (int)0, returns an empty string
------------------------------------------------------*/
StringType CCmdLine::GetArgument(const char *pSwitch, int iIdx)
{
if (HasSwitch(pSwitch))
{
CCmdLine::iterator theIterator;
theIterator = find(pSwitch);
if (theIterator!=end())
{
if ((int)(*theIterator).second.m_strings.size() > iIdx)
{
return (*theIterator).second.m_strings[iIdx];
}
}
}
throw (int)0;
return "";
}
/*------------------------------------------------------
int CCmdLine::GetArgumentCount(const char *pSwitch)
returns the number of arguments found for a given switch.
returns -1 if the switch was not found
------------------------------------------------------*/
int CCmdLine::GetArgumentCount(const char *pSwitch)
{
int iArgumentCount = -1;
if (HasSwitch(pSwitch))
{
CCmdLine::iterator theIterator;
theIterator = find(pSwitch);
if (theIterator!=end())
{
iArgumentCount = (*theIterator).second.m_strings.size();
}
}
return iArgumentCount;
}
}; // end namespace Base
#ifdef EXTERNAL_DISTRO
}; // end namespace NAMESPACE
#endif
@@ -0,0 +1,251 @@
/*------------------------------------------------------
CCmdLine
A utility for parsing command lines.
Copyright (C) 1999 Chris Losinger, Smaller Animals Software.
http://www.smalleranimals.com
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.
-------------------------
Example :
Our example application uses a command line that has two
required switches and two optional switches. The app should abort
if the required switches are not present and continue with default
values if the optional switches are not present.
Sample command line :
MyApp.exe -p1 text1 text2 -p2 "this is a big argument" -opt1 -55 -opt2
Switches -p1 and -p2 are required.
p1 has two arguments and p2 has one.
Switches -opt1 and -opt2 are optional.
opt1 requires a numeric argument.
opt2 has no arguments.
Also, assume that the app displays a 'help' screen if the '-h' switch
is present on the command line.
#include "CmdLine.h"
void main(int argc, char **argv)
{
// our cmd line parser object
CCmdLine cmdLine;
// parse argc,argv
if (cmdLine.SplitLine(argc, argv) < 1)
{
// no switches were given on the command line, abort
ASSERT(0);
exit(-1);
}
// test for the 'help' case
if (cmdLine.HasSwitch("-h"))
{
show_help();
exit(0);
}
// get the required arguments
StringType p1_1, p1_2, p2_1;
try
{
// if any of these fail, we'll end up in the catch() block
p1_1 = cmdLine.GetArgument("-p1", 0);
p1_2 = cmdLine.GetArgument("-p1", 1);
p2_1 = cmdLine.GetArgument("-p2", 0);
}
catch (...)
{
// one of the required arguments was missing, abort
ASSERT(0);
exit(-1);
}
// get the optional parameters
// convert to an int, default to '100'
int iOpt1Val = atoi(cmdLine.GetSafeArgument("-opt1", 0, 100));
// since opt2 has no arguments, just test for the presence of
// the '-opt2' switch
bool bOptVal2 = cmdLine.HasSwitch("-opt2");
.... and so on....
}
If this class is used in an MFC application, StringType is CString, else
it uses the STL 'string' type.
If this is an MFC app, you can use the __argc and __argv macros from
you CYourWinApp::InitInstance() function in place of the standard argc
and argv variables.
------------------------------------------------------*/
#ifndef SACMDSH
#define SACMDSH
//#include <iostream> // you may need this
#include <map>
#include <string>
#include <vector>
//using namespace std ;
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#ifdef __AFX_H__
// if we're using MFC, use CStrings
#define StringType CString
#else
// if we're not using MFC, use STL strings
#define StringType std::string
#endif
// tell the compiler to shut up
#pragma warning(disable:4786)
// handy little container for our argument vector
struct CCmdParam
{
std::vector<StringType> m_strings;
};
// this class is actually a map of strings to vectors
typedef std::map<StringType, CCmdParam> _CCmdLine;
// the command line parser class
class CCmdLine : public _CCmdLine
{
public:
/*------------------------------------------------------
int CCmdLine::SplitLine(int argc, char **argv)
parse the command line into switches and arguments.
returns number of switches found
------------------------------------------------------*/
int SplitLine(int argc, char **argv);
/*------------------------------------------------------
bool CCmdLine::HasSwitch(const char *pSwitch)
was the switch found on the command line ?
ex. if the command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
call return
---- ------
cmdLine.HasSwitch("-a") true
cmdLine.HasSwitch("-z") false
------------------------------------------------------*/
bool HasSwitch(const char *pSwitch);
/*------------------------------------------------------
StringType CCmdLine::GetSafeArgument(const char *pSwitch, int iIdx, const char *pDefault)
fetch an argument associated with a switch . if the parameter at
index iIdx is not found, this will return the default that you
provide.
example :
command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
call return
---- ------
cmdLine.GetSafeArgument("-a", 0, "zz") p1
cmdLine.GetSafeArgument("-a", 1, "zz") p2
cmdLine.GetSafeArgument("-b", 0, "zz") p4
cmdLine.GetSafeArgument("-b", 1, "zz") zz
------------------------------------------------------*/
StringType GetSafeArgument(const char *pSwitch, int iIdx, const char *pDefault);
/*------------------------------------------------------
StringType CCmdLine::GetArgument(const char *pSwitch, int iIdx)
fetch a argument associated with a switch. throws an exception
of (int)0, if the parameter at index iIdx is not found.
example :
command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
call return
---- ------
cmdLine.GetArgument("-a", 0) p1
cmdLine.GetArgument("-b", 1) throws (int)0, returns an empty string
------------------------------------------------------*/
StringType GetArgument(const char *pSwitch, int iIdx);
/*------------------------------------------------------
int CCmdLine::GetArgumentCount(const char *pSwitch)
returns the number of arguments found for a given switch.
returns -1 if the switch was not found
------------------------------------------------------*/
int GetArgumentCount(const char *pSwitch);
protected:
/*------------------------------------------------------
protected member function
test a parameter to see if it's a switch :
switches are of the form : -x
where 'x' is one or more characters.
the first character of a switch must be non-numeric!
------------------------------------------------------*/
bool IsSwitch(const char *pParam);
};
}; // end namespace Base
#ifdef EXTERNAL_DISTRO
}; // end namespace NAMESPACE
#endif
#endif
@@ -0,0 +1,179 @@
#include "Config.h"
//#include <stdlib.h>
//#include <stdio.h>
//#include <string.h>
#include <ctype.h>
#include "Platform.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
//-----------------------------------
/// Read the config file into memory
/// Returns true for success
bool CConfig::LoadFile(char * file)
//-----------------------------------
{
char ch;
FILE * fp;
UnloadFile();
// open file
fp = fopen(file, "r");
if (fp == NULL || fp == (FILE *)-1)
{
//fprintf(stderr,"Failed to open config file %s!",file);
return false;
}
// get length of file
fseek(fp,0,SEEK_END);
long length = ftell(fp);
rewind(fp);
// allocate buffer
pConfig = new char[length + 1];
if (pConfig == NULL)
{
fclose(fp);
fprintf(stderr,"Failed to alloc config buffer length %d",(int32)length);
return false;
}
memset(pConfig,0,length);
// read data, stripping comments
int i = 0;
while (i < length)
{
ch = fgetc(fp);
if (feof(fp))
break;
if (ch == '#')
{
while (ch != 10 && !feof (fp))
{
ch = fgetc(fp);
}
}
pConfig[i++] = ch;
}
pConfig[i] = 0; // mark end of file buffer
fclose(fp);
return true;
}
//-----------------------------------
/// remove the config file from memory
void CConfig::UnloadFile(void)
//-----------------------------------
{
if (pConfig)
delete[] pConfig;
pConfig = NULL;
}
//-----------------------------------
/// finds a key of the config in memory
// key argument is case-insensitive, but must be upper case in config file
// Returns true for success (passing NULL is a special case returned as success)
bool CConfig::FindKey(char *key)
//-----------------------------------
{
if (pConfig == NULL)
return false;
// special case...continue with existing key
if (key == NULL)
return true;
// form the search key
strcpy(strBuffer, "[");
strcat(strBuffer, key);
strcat(strBuffer,"]");
strupr(strBuffer); // keywords must be upper case
// find the key heading
pCursor = strstr(pConfig,strBuffer);
if (pCursor==NULL)
return false;
// find the closing bracket of key heading
pCursor = strchr(pCursor,']');
if (pCursor==NULL)
return false;
pCursor++;
return true;
}
//-----------------------------------
/// extract a number from the config string
// pass the key to find the first number in the list, else NULL to find the next number in the list
// returns 0 if no number is found, else returns the number
long CConfig::GetLong(char *key)
//-----------------------------------
{
if (!FindKey(key))
return 0;
// look for start of number or end of key
while (*pCursor && !isdigit(*pCursor) && *pCursor != '[' && *pCursor != '-')
pCursor++;
int c = 0;
while (*pCursor && (isdigit(*pCursor) || *pCursor == '-') && c < (int)sizeof(strBuffer))
strBuffer[c++] = *(pCursor++);
strBuffer[c] = '\0';
return atol(strBuffer);
}
//-----------------------------------
/// extract string (in double-quotes) from the list.
// pass the key to find the first string in the list, else NULL to find the next string in the list
// returns NULL if no string found, else returns a temporary copy of the string (without quotes)
char * CConfig::GetString(char *key)
//-----------------------------------
{
if (!FindKey(key))
return NULL;
// look for start of string or end of key
while (*pCursor && *pCursor != '"' && *pCursor != '[')
pCursor++;
if (*(pCursor++) != '"')
return NULL;
// until closing quote
int c = 0;
while (*pCursor && c < (int)sizeof(strBuffer))
{
strBuffer[c++] = *pCursor; // extract string
if (*pCursor++ == '"')
{
strBuffer[--c] = '\0';
return strBuffer;
}
}
return NULL;
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,111 @@
/*
; Example syntax of a config file.
# This is a comment to end of line.
; This is a comment too....both comments are to end of line
[KEYWORD] ; all keywords must be upper case to be recognized
; single number, with code example
# long number = config.GetLong("PORT");
[PORT] 5999 ; common single-value case
; list of strings, with code example
# config.FindKey("NUMBERS");
# while (number = config.GetLong(NULL))
# YourHandleNumber(number);
[NUMBERS] 100
200, 300 ; formatting is very flexible as long as numbers are delimited by non-numbers
400 500
600 ; This is badly formatted for example purposes only
; single string, with code example
# strcpy(mystring, config.GetString("STRING"));
[STRING] "This is a string"
; list of strings, with code example
# config.FindKey("HOSTS");
# while (string = config.GetString(NULL))
# YourHandleString(string);
[HOSTS]
"206.19.151.173:5999"
"206.19.151.173:5998"
"206.19.151.173:2000"
*/
#ifndef _CONFIG_H
#define _CONFIG_H
#include <stdio.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
class CConfig
{
public:
// constructor, no file loaded
CConfig();
// version of constructor that calls LoadFile(file)
CConfig(char * file);
// destructor, will delete all buffers
~CConfig();
// copy text config file into memory. Required to use extraction methods.
// if called with a different filename, existing file will be discarded.
bool LoadFile(char * file);
// delete memory buffer of file
void UnloadFile();
// set cursor in file based on key name. Alternate way to select first key when extracting lists.
// returns TRUE if key is found.
bool FindKey(char *key);
// extract string from config. If key is NULL, extract next string in list, else extract first string.
// if key was not found, returns NULL
char * GetString(char *key = NULL);
// extract number from config. If key is NULL, extract next number in list, else extract first number.
// if key was not found, returns 0
long GetLong(char *key = NULL); // extract number from config.
// indicate if config file has been loaded
inline bool FileLoaded() { return pConfig == NULL ? false : true; }
private:
char * pConfig; // pointer to file memory
char * pCursor; // current cursor into file memory
char strBuffer[8196]; // buffer for GetString return pointer -- reused
};
inline CConfig::CConfig()
{
pConfig = NULL;
pCursor = NULL;
}
inline CConfig::CConfig(char * file)
{
pConfig = NULL;
pCursor = NULL;
LoadFile(file);
}
inline CConfig::~CConfig()
{
UnloadFile();
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,22 @@
#ifndef BASE_EVENT_H
#define BASE_EVENT_H
#ifdef WIN32
#include "win32/Event.h"
#elif linux
#include "linux/Event.h"
#elif sparc
#include "solaris/Event.h"
#else
#error /Base/Event.h: Undefine platform type
#endif
#endif // BASE_EVENT_H
@@ -0,0 +1,756 @@
#include "Logger.h"
#include "Mutex.h"
#include <sys/stat.h>
using namespace std;
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
const long kDateLenAllowance = 256;
#ifndef _BASE_LOGGER_MAX_BUF_SIZE_
#define _BASE_LOGGER_MAX_BUF_SIZE_ 2048
#endif
#ifdef WIN32
const char file_sep = '\\';
#define LOGGER_GET_CURR_TIME(__tm_struct__, __time_t_var__) \
memcpy(&__tm_struct__, localtime(&__time_t_var__), sizeof(__tm_struct__))
#define LOGGER_MAKE_DIR(__dir_name__, __mode__) mkdir(__dir_name__)
# ifdef _MT
# define LOGGER_LOCK rLock.Lock();
# define LOGGER_UNLOCK rLock.Unlock();
# else // ifndef _MT
# define LOGGER_LOCK
# define LOGGER_UNLOCK
# endif // _MT
#define vsnprintf _vsnprintf
#else // ifndef WIN32
const char file_sep = '/';
const char *syslogLevels[] = {
"EMERG", "ALERT", "CRIT", "ERR", "WARNING", "NOTICE", "INFO", "DEBUG" };
const int numSysLogLevels = sizeof(syslogLevels) / sizeof(char *);
#define LOGGER_GET_CURR_TIME(__tm_struct__, __time_t_var__) \
localtime_r(&__time_t_var__, &__tm_struct__)
#define LOGGER_MAKE_DIR(__dir_name__, __mode__) mkdir(__dir_name__, __mode__)
# ifdef _REENTRANT
# define LOGGER_LOCK rLock.Lock();
# define LOGGER_UNLOCK rLock.Unlock();
# else // ifndef _REENTRANT
# define LOGGER_LOCK
# define LOGGER_UNLOCK
# endif // _REENTRANT
#endif // WIN32
Logger::Logger(const char *prefix,
int level,
unsigned size,
bool rollDate)
: m_defaultLevel(level),
m_defaultSize(size),
m_dirPrefix(prefix),
m_rollDate(rollDate),
m_opennedSyslog(false)
{
ELogType logType = eUseLocalFile;
m_logLevelToTypeMap[LOG_DEBUG] = logType;
m_logLevelToTypeMap[LOG_INFO] = logType;
m_logLevelToTypeMap[LOG_NOTICE] = logType;
m_logLevelToTypeMap[LOG_WARNING] = logType;
m_logLevelToTypeMap[LOG_ERR] = logType;
m_logLevelToTypeMap[LOG_CRIT] = logType;
m_logLevelToTypeMap[LOG_ALERT] = logType;
m_logLevelToTypeMap[LOG_EMERG] = logType;
m_combinedLogType = logType;
LoggerInit("UnNamedServer");
}
Logger::Logger(const char *programName,
const ELogType logType,
const char *prefix,
int level,
unsigned size,
bool rollDate)
: m_defaultLevel(level),
m_defaultSize(size),
m_dirPrefix(prefix),
m_rollDate(rollDate),
m_opennedSyslog(false)
{
m_logLevelToTypeMap[LOG_DEBUG] = logType;
m_logLevelToTypeMap[LOG_INFO] = logType;
m_logLevelToTypeMap[LOG_NOTICE] = logType;
m_logLevelToTypeMap[LOG_WARNING] = logType;
m_logLevelToTypeMap[LOG_ERR] = logType;
m_logLevelToTypeMap[LOG_CRIT] = logType;
m_logLevelToTypeMap[LOG_ALERT] = logType;
m_logLevelToTypeMap[LOG_EMERG] = logType;
m_combinedLogType = logType;
LoggerInit(programName);
}
void Logger::LoggerInit(const char *programName)
{
char buf[1024];
FILE *logDir = NULL;
if (0 != (m_combinedLogType & eUseLocalFile))
{
logDir = fopen(m_dirPrefix.c_str(), "r+");
if(errno == ENOENT)
{
cmkdir(m_dirPrefix.c_str(), 0755);
}
else if(logDir != NULL)
{
fclose(logDir);
}
tm now;
time_t t = time(NULL);
LOGGER_GET_CURR_TIME(now, t);
memcpy(&m_lastDateTime, &now, sizeof(tm));
if(m_rollDate)
{
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
}
else
{
sprintf(buf, "%s", m_dirPrefix.c_str());
}
logDir = fopen(buf, "r+");
if(errno == ENOENT)
{
cmkdir(buf, 0755);
}
else if(logDir != NULL)
{
fclose(logDir);
}
m_logPrefix = buf;
m_logRolloverSize = 0x80000000; // Default: 2 GB upper limit on file size
}
#ifndef WIN32
// Open connection to syslog
if (0 != (m_combinedLogType & eUseSysLog)) {
openlog(programName, LOG_NDELAY | LOG_PID, LOG_LOCAL5);
m_opennedSyslog = true;
}
#endif // !WIN32
}
Logger::~Logger()
{
map<unsigned, LogInfo *>::iterator iter;
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
{
logWithSys((*iter).first, LOG_INFO, LOG_FILEONLY, "---=== Log Stopped ===---");
fflush((*iter).second->file);
fclose((*iter).second->file);
delete((*iter).second);
}
m_logTable.clear();
#ifndef WIN32
// close connection to syslog
if (m_opennedSyslog)
closelog();
#endif // !WIN32
}
ELogType Logger::getLoggingType(unsigned logLevel) const
{
std::map<unsigned, ELogType>::const_iterator levelIter = m_logLevelToTypeMap.find(logLevel);
ELogType logType = eUseNone;
if (levelIter != m_logLevelToTypeMap.end())
{
logType = levelIter->second;
}
return logType;
}
void Logger::setLoggingType(unsigned logLevel, ELogType logType)
{
std::map<unsigned, ELogType>::iterator levelIter = m_logLevelToTypeMap.find(logLevel);
if (levelIter != m_logLevelToTypeMap.end())
{
levelIter->second = logType;
if (logType > m_combinedLogType) {
m_combinedLogType = (ELogType)(m_combinedLogType | logType);
} else {
m_combinedLogType = eUseNone;
for (levelIter = m_logLevelToTypeMap.begin();
levelIter != m_logLevelToTypeMap.end();
levelIter++)
{
m_combinedLogType = (ELogType)(m_combinedLogType | logType);
}
}
}
}
void Logger::flush(unsigned logenum)
{
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter != m_logTable.end())
{
LogInfo *info = (*iter).second;
fflush(info->file);
info->used = 0;
}
}
void Logger::flushAll()
{
if (0 != (m_combinedLogType & eUseLocalFile))
{
map<unsigned, LogInfo *>::iterator iter;
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
{
LogInfo *info = (*iter).second;
fflush(info->file);
info->used = 0;
}
}
}
void Logger::addLog(const char *id, unsigned logenum, int level, unsigned size)
{
if (0 != (m_combinedLogType & eUseLocalFile))
{
LogInfo *newLog = new LogInfo;
newLog->filename = m_logPrefix + file_sep + id + ".log";
newLog->name = id;
newLog->used = 0;
newLog->max = size;
newLog->last = 0;
newLog->level = level;
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
if(strcmp("stdout", id) == 0)
{
newLog->file = stdout;
}
else if(strcmp("stderr", id) == 0)
{
newLog->file = stderr;
}
else
{
newLog->file = fopen(newLog->filename.c_str(), "a+");
if(newLog->file == NULL)
{
printf("Open file %s failed\n", newLog->filename.c_str());
}
}
logWithSys(logenum, LOG_INFO, LOG_FILEONLY, "---=== Log Started ===---");
}
}
void Logger::addLog(const char *id, unsigned logenum)
{
if (0 != (m_combinedLogType & eUseLocalFile))
{
LogInfo *newLog = new LogInfo;
newLog->filename = m_logPrefix + file_sep + id + ".log";
newLog->name = id;
newLog->used = 0;
newLog->max = m_defaultSize;
newLog->last = 0;
newLog->level = m_defaultLevel;
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
if(strcmp("stdout", id) == 0)
{
newLog->file = stdout;
}
else if(strcmp("stderr", id) == 0)
{
newLog->file = stderr;
}
else
{
newLog->file = fopen(newLog->filename.c_str(), "a+");
if(newLog->file == NULL)
{
printf("Open file %s failed\n", newLog->filename.c_str());
}
}
logWithSys(logenum, LOG_INFO, LOG_FILEONLY, "---===Log Started ===---");
}
}
void Logger::updateLog(unsigned logenum, int level, unsigned size)
{
if (0 != (m_combinedLogType & eUseLocalFile))
{
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter != m_logTable.end())
{
(*iter).second->level = level;
(*iter).second->max = size;
}
}
}
void Logger::removeLog(unsigned logenum)
{
if (0 != (m_combinedLogType & eUseLocalFile))
{
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter != m_logTable.end())
{
#ifdef WIN32
logWithSys((*iter).first, LOG_INFO, LOG_FILEONLY, "---=== Log Stopped ===---");
#else // ifndef WIN32
logWithSys((*iter).first, LOG_INFO, LOG_ALWAYS, "---=== Log Stopped ===---");
#endif // WIN32
fflush((*iter).second->file);
fclose((*iter).second->file);
delete((*iter).second);
}
}
}
void Logger::logSimple(unsigned logenum, int level, const char *message)
{
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter == m_logTable.end())
{
return;
}
time_t t = time(NULL);
LogInfo *info = (*iter).second;
if(level >= info->level)
{
return;
}
#ifndef WIN32
if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout)))
{
return;
}
#endif // !WIN32
if(info->last != t)
{
memcpy(&info->ts, localtime(&t), sizeof(tm));
info->last = t;
}
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
{
LOGGER_LOCK
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
{
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
rollDate(t);
}
LOGGER_UNLOCK
}
if(iter != m_logTable.end())
{
if(info->max > 0)
{
info->used += fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
info->used += fputc('\n', info->file);
if(info->used > info->max)
{
fflush(info->file);
info->used = 0;
}
}
else
{
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
fputc('\n', info->file);
fflush(info->file);
}
}
}
void Logger::logSimpleWithSys(unsigned logenum, unsigned priority, int level, const char *message)
{
#ifndef WIN32
if (0 != (m_combinedLogType & eUseSysLog))
syslog(priority, "%s: %s", syslogLevels[priority % numSysLogLevels], message);
#endif // !WIN32
if (0 != (m_combinedLogType & eUseLocalFile))
{
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter == m_logTable.end())
{
return;
}
time_t t = time(NULL);
LogInfo *info = (*iter).second;
if(level >= info->level)
{
return;
}
#ifndef WIN32
if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout)))
{
return;
}
#endif // !WIN32
if(info->last != t)
{
memcpy(&info->ts, localtime(&t), sizeof(tm));
info->last = t;
}
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
{
LOGGER_LOCK
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
{
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
rollDate(t);
}
LOGGER_UNLOCK
}
if(iter != m_logTable.end())
{
if (m_logRolloverSize> 0)
checkLogRoll(info, ::strlen(message) + kDateLenAllowance);
if(info->max > 0)
{
info->used += fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
info->used += fputc('\n', info->file);
if(info->used > info->max)
{
fflush(info->file);
info->used = 0;
}
}
else
{
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
fputc('\n', info->file);
fflush(info->file);
}
}
}
}
void Logger::log(unsigned logenum, int level, const char *message, ...)
{
char buf[_BASE_LOGGER_MAX_BUF_SIZE_];
va_list varg;
va_start(varg, message);
vsnprintf(buf, _BASE_LOGGER_MAX_BUF_SIZE_, message, varg);
buf[_BASE_LOGGER_MAX_BUF_SIZE_ - 1] = 0;
va_end(varg);
// ensure that the buf does not contain any '%' characters.
// prevent crash problem
char *rv;
while((rv = strchr(buf, '%')) != NULL)
{
*rv = ' '; // replace with space
}
logWithSys(logenum, LOG_NOTICE, level, buf);
}
void Logger::logWithSys(unsigned logenum, unsigned priority, int level, const char *message, ...)
{
ELogType logType = getLoggingType(priority);
char buf[_BASE_LOGGER_MAX_BUF_SIZE_];
va_list varg;
va_start(varg, message);
vsnprintf(buf, _BASE_LOGGER_MAX_BUF_SIZE_, message, varg);
buf[_BASE_LOGGER_MAX_BUF_SIZE_ - 1] = 0;
va_end(varg);
#ifndef WIN32
if (0 != (logType & eUseSysLog))
syslog(priority, "%s: %s", syslogLevels[priority % numSysLogLevels], buf);
#endif // !WIN32
if (0 != (logType & eUseLocalFile))
{
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter == m_logTable.end())
{
return;
}
time_t t = time(NULL);
LogInfo *info = (*iter).second;
if(level >= info->level)
{
return;
}
if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout)))
{
return;
}
if(info->last != t)
{
LOGGER_GET_CURR_TIME(info->ts, t);
info->last = t;
}
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
{
LOGGER_LOCK
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
{
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
rollDate(t);
}
LOGGER_UNLOCK
}
if(iter != m_logTable.end())
{
if (m_logRolloverSize> 0)
checkLogRoll(info, ::strlen(buf) + kDateLenAllowance);
if(info->max > 0)
{
info->used += fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, buf);
info->used += fputc('\n', info->file);
if(info->used > info->max)
{
fflush(info->file);
info->used = 0;
}
}
else
{
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, buf);
fputc('\n', info->file);
fflush(info->file);
}
}
}
}
void Logger::rollDate(time_t t)
{
char buf[80];
FILE *logDir = NULL;
logDir = fopen(m_dirPrefix.c_str(), "r+");
if(errno == ENOENT)
{
cmkdir(m_dirPrefix.c_str(), 0755);
}
else if(logDir != NULL)
{
fclose(logDir);
}
tm now;
LOGGER_GET_CURR_TIME(now, t);
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
logDir = fopen(buf, "r+");
if(errno == ENOENT)
{
cmkdir(buf, 0755);
}
else if(logDir != NULL)
{
fclose(logDir);
}
m_logPrefix = buf;
map<unsigned, LogInfo *>::iterator iter;
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
{
(*iter).second->filename = m_logPrefix + file_sep + (*iter).second->name.c_str() + ".log";
fflush((*iter).second->file);
fclose((*iter).second->file);
(*iter).second->file = fopen((*iter).second->filename.c_str(), "a+");
if ((*iter).second->file == 0)
abort();
memcpy(&((*iter).second->ts), &now, sizeof(tm));
}
}
// mkdir function that creates intermediate directories
void Logger::cmkdir(const char *dir, int mode)
{
char dirbuf[128];
strncpy(dirbuf, dir, 127);
dirbuf[127] = 0;
char *j = dirbuf, *i = dirbuf;
int handle;
while(*i)
{
if(*i == file_sep)
{
(*i) = 0;
#ifdef WIN32
handle = open(j, O_EXCL);
if((handle > 0) || (errno != EISDIR && errno != ENOENT && errno != EACCES))
{
perror("Logger::cmkdir():");
abort();
}
#else // ifndef WIN32
// handle = open(j, O_EXCL); // Ben's original code
// if((handle > 0) || (errno != EISDIR && errno != ENOENT))
// {
// perror("Logger::cmkdir():");
// abort();
// }
// This doesnt work under Linux, it returns a valid handle
// Instead: see if file exists. If it doesnt, create directory ok
// If it exists, do stat to see if it is a dir.
// If it is a dir, then ok, create the directory.
// If it is a file, error
// ging 9-16-2002
handle = open(j, O_RDONLY);
if (handle > 0)
{
struct stat stat_buffer;
int ret = fstat(handle,&stat_buffer);
if ((ret == -1) || ((stat_buffer.st_mode | S_IFDIR) == 0))
{
perror("Logger::cmkdir():");
abort();
}
}
#endif // WIN32
LOGGER_MAKE_DIR(j, mode);
close(handle);
(*i) = file_sep;
}
else if(*(i + 1) == 0)
{
LOGGER_MAKE_DIR(j, mode);
}
i++;
}
}
void Logger::rollLog(LogInfo *logInfo)
{
std::string newLogName;
char timeStampBuffer[256];
time_t t = time(NULL);
tm now;
int r;
int nTries = 10;
fflush(logInfo->file);
fclose(logInfo->file);
do
{
LOGGER_GET_CURR_TIME(now, t);
sprintf(timeStampBuffer, "-%4.4d-%2.2d-%2.2d-%2.2d-%2.2d-%2.2d.log",
(now.tm_year + 1900), (now.tm_mon + 1), now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec);
newLogName = logInfo->filename.substr(0, logInfo->filename.length() - 4) + timeStampBuffer;
r = rename(logInfo->filename.c_str(), newLogName.c_str());
nTries--;
t++;
}
while ((r != 0) && (nTries > 0));
logInfo->file = fopen(logInfo->filename.c_str(), "a+");
memcpy(&(logInfo->ts), &now, sizeof(tm));
}
void Logger::checkLogRoll(LogInfo *logInfo, unsigned long lenToAdd)
{
unsigned long logSize = ftell(logInfo->file);
if ((logSize + lenToAdd) > m_logRolloverSize)
{
LOGGER_LOCK
rollLog(logInfo);
LOGGER_UNLOCK
}
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,165 @@
#ifndef __LOGGER_H__
#define __LOGGER_H__
// make the compiler shut up
#pragma warning (disable : 4786)
#include "Platform.h"
#include <string>
#include <map>
#include "Mutex.h"
#ifndef WIN32
#include <syslog.h>
#endif
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#define LOG_ALWAYS -1
#define LOG_FILEONLY -2
struct LogInfo
{
FILE *file;
unsigned used;
tm ts;
time_t last;
unsigned max;
int level;
std::string filename;
std::string name;
};
/* Use these flags defined in syslog.h for the priority level
LOG_EMERG,
LOG_ALERT,
LOG_CRIT,
LOG_ERR,
LOG_WARNING,
LOG_NOTICE,
LOG_INFO,
LOG_DEBUG
*/
//-----------------------------------------------
// Windows doesn't have syslog (?) so we define the
// syslog warning levels here to satisfy the compiler
// but then ignore them in log() and logSimple()
//-----------------------------------------------
// PLEASE USE THE FOLLOWING ENUMERATIONS FOR LOGGING INSTEAD OF THE SYSLOG ONES.
enum LogLevel
{
#ifndef WIN32
BASE_LOG_EMERG = LOG_EMERG,
BASE_LOG_ALERT = LOG_ALERT,
BASE_LOG_CRIT = LOG_CRIT,
BASE_LOG_ERR = LOG_ERR,
BASE_LOG_WARNING = LOG_WARNING,
BASE_LOG_NOTICE = LOG_NOTICE,
BASE_LOG_INFO = LOG_INFO,
BASE_LOG_DEBUG = LOG_DEBUG
#else
BASE_LOG_EMERG = 0,
BASE_LOG_ALERT,
BASE_LOG_CRIT,
BASE_LOG_ERR,
BASE_LOG_WARNING,
BASE_LOG_NOTICE,
BASE_LOG_INFO,
BASE_LOG_DEBUG
#endif
};
// The _WIN32_LOG_LEVELS_ remain for backwards compatability.
#ifdef WIN32
enum _WIN32_LOG_LEVELS_
{
LOG_EMERG = 0,
LOG_ALERT,
LOG_CRIT,
LOG_ERR,
LOG_WARNING,
LOG_NOTICE,
LOG_INFO,
LOG_DEBUG
};
#endif
enum ELogType
{
eUseNone = 0,
eUseLocalFile = 1,
eUseSysLog = 2,
eUseBoth = 3
};
class Logger
{
public:
Logger(const char *programName,
const ELogType logType = eUseLocalFile,
const char *prefix = "logs",
int level = 10,
unsigned size = 0,
bool rollDate = true);
Logger(const char *prefix,
int level,
unsigned size,
bool rollDate = true); // Backwards compatibility
void LoggerInit(const char *programName);
~Logger();
void addLog(const char *id, unsigned logenum, int level, unsigned size);
void addLog(const char *id, unsigned logenum);
void removeLog(unsigned logenum);
void updateLog(unsigned logenum, int level, unsigned size);
void logSimple(unsigned logenum, int level, const char *message);
void logSimpleWithSys(unsigned logenum, unsigned priority, int level, const char *message);
void logWithSys(unsigned logenum, unsigned priority, int level, const char *message, ...);
void log(unsigned logenum, int level, const char *message, ...);
void flushAll();
void flush(unsigned logenum);
unsigned long getLogRolloverSize() { return m_logRolloverSize; }
void setLogRolloverSize(unsigned long maxLogSize) { m_logRolloverSize = maxLogSize; }
ELogType getLoggingType(unsigned logLevel) const;
void setLoggingType(unsigned logLevel, ELogType logType);
private:
void rollDate(time_t now);
void cmkdir(const char *dir, int mode);
void rollLog(LogInfo *logInfo);
void checkLogRoll(LogInfo *logInfo, unsigned long lenToAdd);
unsigned m_defaultLevel;
unsigned m_defaultSize;
std::string m_lastDateText;
tm m_lastDateTime;
std::map<unsigned, LogInfo *> m_logTable;
std::string m_logPrefix;
std::string m_dirPrefix;
#if defined (_REENTRANT) || defined (_MT)
Base::CMutex rLock;
#endif
bool m_rollDate;
unsigned long m_logRolloverSize;
std::map<unsigned, ELogType> m_logLevelToTypeMap;
ELogType m_combinedLogType;
bool m_opennedSyslog;
};
extern const char file_sep;
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,325 @@
// MD5.cpp: implementation of the MD5 class.
//
//////////////////////////////////////////////////////////////////////
#include "MD5.h"
#include "Types.h"
using namespace std;
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
MD5::State::State() :
state(4,0),
count(2,0),
buffer(64,0)
{
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
}
static char const init[64] =
{
-128, 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
};
vector<char> MD5::padding(init,init+sizeof(init)/sizeof(init[0]));
MD5::MD5()
{
Init();
}
MD5::MD5(const string & input)
{
Init();
Update(input);
}
vector<int> MD5::Decode(vector<char> achar0, int i, int j)
{
vector<int> ai(16,0);
int l;
int k = l = 0;
for(; l < i; l += 4)
{
ai[k] = achar0[l + j] & 0xff | (achar0[l + 1 + j] & 0xff) << 8 | (achar0[l + 2 + j] & 0xff) << 16 | (achar0[l + 3 + j] & 0xff) << 24;
k++;
}
return ai;
}
vector<char> MD5::Encode(vector<int> ai, int i)
{
vector<char> achar0(i,0);
int k;
int j = k = 0;
for(; k < i; k += 4){
achar0[k] = (char)(ai[j] & 0xff);
achar0[k + 1] = (char)(ai[j] >> 8 & 0xff);
achar0[k + 2] = (char)(ai[j] >> 16 & 0xff);
achar0[k + 3] = (char)(ai[j] >> 24 & 0xff);
j++;
}
return achar0;
}
int MD5::FF(int i, int j, int k, int l, int i1, int j1, int k1)
{
i = uadd(i, j & k | ~j & l, i1, k1);
return uadd(rotate_left(i, j1), j);
}
vector<char> MD5::Final()
{
if (finalsNull)
{
State &state1 = state;
vector<char> achar0 = Encode(state1.count, 8);
int i = state1.count[0] >> 3 & 0x3f;
int j = i >= 56 ? 120 - i : 56 - i;
Update(state1, padding, 0, j);
Update(state1, achar0, 0, 8);
finals = state1;
finalsNull = false;
}
return Encode(finals.state, 16);
}
int MD5::GG(int i, int j, int k, int l, int i1, int j1, int k1)
{
i = uadd(i, j & l | k & ~l, i1, k1);
return uadd(rotate_left(i, j1), j);
}
int MD5::HH(int i, int j, int k, int l, int i1, int j1, int k1)
{
i = uadd(i, j ^ k ^ l, i1, k1);
return uadd(rotate_left(i, j1), j);
}
int MD5::II(int i, int j, int k, int l, int i1, int j1, int k1)
{
i = uadd(i, k ^ (j | ~l), i1, k1);
return uadd(rotate_left(i, j1), j);
}
void MD5::Init()
{
if (padding.size() == 0)
{
padding.resize(64,0);
padding[0] = -128;
}
finalsNull = true;
}
void MD5::Transform(State & state1, vector<char> achar0, int i)
{
int j = state1.state[0];
int k = state1.state[1];
int l = state1.state[2];
int i1 = state1.state[3];
vector<int> ai = Decode(achar0, 64, i);
j = FF(j, k, l, i1, ai[0], 7, 0xd76aa478);
i1 = FF(i1, j, k, l, ai[1], 12, 0xe8c7b756);
l = FF(l, i1, j, k, ai[2], 17, 0x242070db);
k = FF(k, l, i1, j, ai[3], 22, 0xc1bdceee);
j = FF(j, k, l, i1, ai[4], 7, 0xf57c0faf);
i1 = FF(i1, j, k, l, ai[5], 12, 0x4787c62a);
l = FF(l, i1, j, k, ai[6], 17, 0xa8304613);
k = FF(k, l, i1, j, ai[7], 22, 0xfd469501);
j = FF(j, k, l, i1, ai[8], 7, 0x698098d8);
i1 = FF(i1, j, k, l, ai[9], 12, 0x8b44f7af);
l = FF(l, i1, j, k, ai[10], 17, -42063);
k = FF(k, l, i1, j, ai[11], 22, 0x895cd7be);
j = FF(j, k, l, i1, ai[12], 7, 0x6b901122);
i1 = FF(i1, j, k, l, ai[13], 12, 0xfd987193);
l = FF(l, i1, j, k, ai[14], 17, 0xa679438e);
k = FF(k, l, i1, j, ai[15], 22, 0x49b40821);
j = GG(j, k, l, i1, ai[1], 5, 0xf61e2562);
i1 = GG(i1, j, k, l, ai[6], 9, 0xc040b340);
l = GG(l, i1, j, k, ai[11], 14, 0x265e5a51);
k = GG(k, l, i1, j, ai[0], 20, 0xe9b6c7aa);
j = GG(j, k, l, i1, ai[5], 5, 0xd62f105d);
i1 = GG(i1, j, k, l, ai[10], 9, 0x2441453);
l = GG(l, i1, j, k, ai[15], 14, 0xd8a1e681);
k = GG(k, l, i1, j, ai[4], 20, 0xe7d3fbc8);
j = GG(j, k, l, i1, ai[9], 5, 0x21e1cde6);
i1 = GG(i1, j, k, l, ai[14], 9, 0xc33707d6);
l = GG(l, i1, j, k, ai[3], 14, 0xf4d50d87);
k = GG(k, l, i1, j, ai[8], 20, 0x455a14ed);
j = GG(j, k, l, i1, ai[13], 5, 0xa9e3e905);
i1 = GG(i1, j, k, l, ai[2], 9, 0xfcefa3f8);
l = GG(l, i1, j, k, ai[7], 14, 0x676f02d9);
k = GG(k, l, i1, j, ai[12], 20, 0x8d2a4c8a);
j = HH(j, k, l, i1, ai[5], 4, 0xfffa3942);
i1 = HH(i1, j, k, l, ai[8], 11, 0x8771f681);
l = HH(l, i1, j, k, ai[11], 16, 0x6d9d6122);
k = HH(k, l, i1, j, ai[14], 23, 0xfde5380c);
j = HH(j, k, l, i1, ai[1], 4, 0xa4beea44);
i1 = HH(i1, j, k, l, ai[4], 11, 0x4bdecfa9);
l = HH(l, i1, j, k, ai[7], 16, 0xf6bb4b60);
k = HH(k, l, i1, j, ai[10], 23, 0xbebfbc70);
j = HH(j, k, l, i1, ai[13], 4, 0x289b7ec6);
i1 = HH(i1, j, k, l, ai[0], 11, 0xeaa127fa);
l = HH(l, i1, j, k, ai[3], 16, 0xd4ef3085);
k = HH(k, l, i1, j, ai[6], 23, 0x4881d05);
j = HH(j, k, l, i1, ai[9], 4, 0xd9d4d039);
i1 = HH(i1, j, k, l, ai[12], 11, 0xe6db99e5);
l = HH(l, i1, j, k, ai[15], 16, 0x1fa27cf8);
k = HH(k, l, i1, j, ai[2], 23, 0xc4ac5665);
j = II(j, k, l, i1, ai[0], 6, 0xf4292244);
i1 = II(i1, j, k, l, ai[7], 10, 0x432aff97);
l = II(l, i1, j, k, ai[14], 15, 0xab9423a7);
k = II(k, l, i1, j, ai[5], 21, 0xfc93a039);
j = II(j, k, l, i1, ai[12], 6, 0x655b59c3);
i1 = II(i1, j, k, l, ai[3], 10, 0x8f0ccc92);
l = II(l, i1, j, k, ai[10], 15, 0xffeff47d);
k = II(k, l, i1, j, ai[1], 21, 0x85845dd1);
j = II(j, k, l, i1, ai[8], 6, 0x6fa87e4f);
i1 = II(i1, j, k, l, ai[15], 10, 0xfe2ce6e0);
l = II(l, i1, j, k, ai[6], 15, 0xa3014314);
k = II(k, l, i1, j, ai[13], 21, 0x4e0811a1);
j = II(j, k, l, i1, ai[4], 6, 0xf7537e82);
i1 = II(i1, j, k, l, ai[11], 10, 0xbd3af235);
l = II(l, i1, j, k, ai[2], 15, 0x2ad7d2bb);
k = II(k, l, i1, j, ai[9], 21, 0xeb86d391);
state1.state[0] += j;
state1.state[1] += k;
state1.state[2] += l;
state1.state[3] += i1;
}
void MD5::Update(char char0)
{
vector<char> achar0(1,0);
achar0[0] = char0;
Update(achar0, 1);
}
void MD5::Update(State & state1, vector<char> achar0, int i, int j)
{
finalsNull = true;
if (j - i > (int)achar0.size())
j = achar0.size() - i;
int k = state1.count[0] >> 3 & 0x3f;
if ((state1.count[0] += j << 3) < j << 3)
state1.count[1]++;
state1.count[1] += j >> 29;
int l = 64 - k;
int j1;
if(j >= l)
{
for(int i1 = 0; i1 < l; i1++)
state1.buffer[i1 + k] = achar0[i1 + i];
Transform(state1, state1.buffer, 0);
for(j1 = l; j1 + 63 < j; j1 += 64)
Transform(state1, achar0, j1);
k = 0;
}
else
{
j1 = 0;
}
if (j1 < j)
{
int k1 = j1;
for(; j1 < j; j1++)
state1.buffer[(k + j1) - k1] = achar0[j1 + i];
}
}
void MD5::Update(string s)
{
vector<char> achar(s.size(),0);
for (int i=0; i<(int)s.size(); i++)
achar[i] = s[i];
Update( achar, achar.size() );
}
void MD5::Update(vector<char> achar0)
{
Update(achar0, 0, achar0.size());
}
void MD5::Update(vector<char> achar0, int i)
{
Update(state, achar0, 0, i);
}
void MD5::Update(vector<char> achar0, int i, int j)
{
Update(state, achar0, i, j);
}
string MD5::asHex()
{
return asHex(Final());
}
string MD5::asHex(vector<char> achar0)
{
const string hex = "0123456789abcdef";
string stringbuffer;
for (int i = 0; i < (int)achar0.size(); i++)
{
stringbuffer += hex.substr((achar0[i] >> 4) & 0x0f,1);
stringbuffer += hex.substr(achar0[i] & 0x0f,1);
}
return stringbuffer;
}
int MD5::rotate_left(int i, int j)
{
unsigned i1 = i;
unsigned j1 = j;
return i1 << j1 | i1 >> (32 - j1);
}
int MD5::uadd(int i, int j)
{
int64 l = (int64)i & 0x0ffffffffL;
int64 l1 = (int64)j & 0x0ffffffffL;
l += l1;
return (int)(l & 0x0ffffffffL);
}
int MD5::uadd(int i, int j, int k)
{
return uadd(uadd(i, j), k);
}
int MD5::uadd(int i, int j, int k, int l)
{
return uadd(uadd(i, j, k), l);
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,75 @@
// MD5.h: interface for the MD5 class.
//
//////////////////////////////////////////////////////////////////////
#ifndef MD5_H
#define MD5_H
#include <string>
#include <vector>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
class MD5
{
struct State
{
State();
std::vector<int> state;
std::vector<int> count;
std::vector<char> buffer;
};
public:
MD5::MD5();
MD5(const std::string &input);
void Init();
std::vector<char> Final();
void Update(char char0);
void Update(State & state1, std::vector<char> achar0, int i, int j);
void Update(std::string s);
void Update(std::vector<char> achar0);
void Update(std::vector<char> achar0, int i);
void Update(std::vector<char> achar0, int i, int j);
std::string asHex();
static std::string asHex(std::vector<char> achar0);
private:
std::vector<int> Decode(std::vector<char> achar0, int i, int j);
std::vector<char> Encode(std::vector<int> ai, int i);
int FF(int i, int j, int k, int l, int i1, int j1, int k1);
int GG(int i, int j, int k, int l, int i1, int j1, int k1);
int HH(int i, int j, int k, int l, int i1, int j1, int k1);
int II(int i, int j, int k, int l, int i1, int j1, int k1);
void Transform(State & state1, std::vector<char> achar0, int i);
int rotate_left(int i, int j);
int uadd(int i, int j);
int uadd(int i, int j, int k);
int uadd(int i, int j, int k, int l);
private:
State state;
State finals;
bool finalsNull;
static std::vector<char> padding;
};
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // MD5_H
@@ -0,0 +1,23 @@
#ifndef BASE_MUTEX_H
#define BASE_MUTEX_H
#ifdef WIN32
#include "win32/Mutex.h"
#elif linux
#include "linux/Mutex.h"
#elif sparc
#include "solaris/Mutex.h"
#else
#error /Base/Mutex.h: Undefine platform type
#endif
#endif // BASE_MUTEX_H
@@ -0,0 +1,105 @@
#ifndef BASE_PLATFORM_H
#define BASE_PLATFORM_H
#include <assert.h>
#ifdef WIN32
#include "win32/Platform.h"
#elif linux
#include "linux/Platform.h"
#elif sparc
#include "solaris/Platform.h"
#else
#error /Base/Platform.h: Undefine platform type
#endif
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
template <class T> inline T rotlFixed(T x, unsigned int y)
{
assert(y < sizeof(T)*8);
return (T)((x<<y) | (x>>(sizeof(T)*8-y)));
}
template <class T> inline T rotrFixed(T x, unsigned int y)
{
assert(y < sizeof(T)*8);
return (x>>y) | (x<<(sizeof(T)*8-y));
}
template <class T> inline T rotlMod(T x, unsigned int y)
{
y %= sizeof(T)*8;
return (x<<y) | (x>>(sizeof(T)*8-y));
}
template <class T> inline T rotrMod(T x, unsigned int y)
{
y %= sizeof(T)*8;
return (x>>y) | (x<<(sizeof(T)*8-y));
}
inline uint16 byteReverse16(void * data)
{
uint16 value = *static_cast<uint16 *>(data);
return *static_cast<uint16 *>(data) = rotlFixed(value, 8U);
// return rotlFixed(value, 8U);
}
inline uint32 byteReverse32(void * data)
{
uint32 value = *static_cast<uint32 *>(data);
return *static_cast<uint32 *>(data) = (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
// return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
}
inline uint64 byteReverse64(void * data)
{
uint64 value = *static_cast<uint64 *>(data);
return *static_cast<uint64 *>(data) = (
uint64((rotrFixed(uint32(value), 8U) & 0xff00ff00) | (rotlFixed(uint32(value), 8U) & 0x00ff00ff)) << 32) |
(rotrFixed(uint32(value>>32), 8U) & 0xff00ff00) | (rotlFixed(uint32(value>>32), 8U) & 0x00ff00ff);
// return (uint64(byteReverse(uint32(value))) << 32) | byteReverse(uint32(value>>32));
}
inline uint32 strlen(const unsigned short * string)
{
if (string == 0)
return 0;
uint32 length=0;
while (*(string+length++) != 0);
return length-1;
}
inline double getTimerLatency(Base::uint64 startTime, Base::uint64 finishTime=0)
{
Base::int64 requestAge;
Base::int64 freq = Base::getTimerFrequency();
Base::uint64 finish = (finishTime ? finishTime : Base::getTimer());
if (finish < startTime)
requestAge = (0 - 1) - startTime - finish;
else
requestAge = finish - startTime;
return (double)requestAge/freq;
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // BASE_PLATFORM_H
@@ -0,0 +1,34 @@
#include "ScopeLock.h"
#ifdef INCLUDE_SCOPELOCK
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
CScopeLock::CScopeLock(CMutex& mutex) :
mMutex(&mutex)
{
mMutex->Lock();
}
CScopeLock::CScopeLock(CScopeLock& lock) :
mMutex(lock.mMutex)
{
mMutex->Lock();
}
CScopeLock::~CScopeLock()
{
mMutex->Unlock();
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // INCLUDE_SCOPELOCK
@@ -0,0 +1,40 @@
// ScopeLock.h: interface for the CScopeLock class.
//
//////////////////////////////////////////////////////////////////////
#ifndef SCOPELOCK_H
#define SCOPELOCK_H
#if defined _MT || defined _REENTRANT
# define INCLUDE_SCOPELOCK
#endif
#ifdef INCLUDE_SCOPELOCK
#include "Mutex.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
class CScopeLock
{
public:
CScopeLock(CMutex& mutex);
CScopeLock(CScopeLock& lock);
virtual ~CScopeLock();
private:
CMutex *mMutex;
};
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // INCLUDE_SCOPELOCK
#endif // SCOPELOCK_H
@@ -0,0 +1,45 @@
#include "Statistics.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
CStatisticTimer::CStatisticTimer(bool running) :
mTotal(0),
mStart(getTimer()),
mRunning(running)
{
}
double CStatisticTimer::GetTime()
{
uint64 total = mTotal;
if (mRunning)
total += getTimer()-mStart;
return (double)((int64)(total/getTimerFrequency()));
}
uint64 CStatisticTimer::GetFraction(uint32 fraction)
{
uint64 total = mTotal;
if (mRunning)
total += getTimer()-mStart;
if (fraction == 0)
return total;
else
return total/(getTimerFrequency()/fraction);
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,140 @@
#ifndef STATISTICS_H
#define STATISTICS_H
#include <time.h>
#include "Platform.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
template <class TYPE, uint32 COUNT>
class CStatistic
{
public:
CStatistic(uint32 freq=0) :
mSampleFrequency(freq),
mLastSampleTime(0),
mSample(0),
mSampleTotal(0),
mAggregateTotal(0),
mAggregateMaximum(0),
mAggregateMinimum(0),
mAverageTotal(0),
mAverageIndex(0),
mAverageCount(0)
{
}
bool Sample(TYPE value)
{
bool commit = false;
if (!mLastSampleTime)
mLastSampleTime = time(NULL);
if (!mSampleFrequency || mLastSampleTime + mSampleFrequency < (unsigned)time(NULL))
{
mSampleTotal++;
mAggregateTotal += value;
if (value > mAggregateMaximum)
mAggregateMaximum = value;
if (value < mAggregateMinimum)
mAggregateMinimum = value;
if (mAverageIndex == COUNT)
mAverageIndex = 0;
if (mAverageCount > COUNT)
mAverageTotal -= mAverageData[mAverageIndex];
mAverageData[mAverageIndex++] = value;
mAverageTotal += value;
if (mAverageCount < COUNT)
mAverageCount++;
commit = true;
mSample = 0;
}
mSample += value;
return commit;
}
TYPE GetSample(uint32 age = 0)
{
if (age > mAverageCount)
return 0;
uint32 index = mAverageIndex;
if (age > index)
index = COUNT - (age - index);
else
index -= age;
return mAverageData[index];
}
double GetAverage()
{
return (double)mAverageTotal/mAverageCount;
}
double GetAggregateAverage()
{
return (double)mAggregateTotal/mSampleTotal;
}
TYPE GetMaximum()
{
return mAggregateMaximum;
}
TYPE GetMinimum()
{
return mAggregateMinimum;
}
private:
uint32 mSampleFrequency;
time_t mLastSampleTime;
TYPE mSample;
uint32 mSampleTotal;
TYPE mAggregateTotal;
TYPE mAggregateMaximum;
TYPE mAggregateMinimum;
TYPE mAverageData[COUNT];
TYPE mAverageTotal;
uint32 mAverageIndex;
uint32 mAverageCount;
};
class CStatisticTimer
{
public:
CStatisticTimer(bool running = true);
void Start() { if (mRunning) return; mStart = getTimer(); mRunning = true; }
void Stop() { if (!mRunning) return; mTotal += getTimer()-mStart; mRunning = false; }
void Reset() { mTotal = 0; mStart = getTimer(); }
double GetTime();
uint64 GetFraction(uint32 fraction=1000);
private:
uint64 mTotal;
uint64 mStart;
bool mRunning;
};
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // STATISTICS_H
@@ -0,0 +1,238 @@
#ifndef BLOCK_ALLOCATOR_H
#define BLOCK_ALLOCATOR_H
#if defined _MT || defined _REENTRANT
# define USE_ALLOCATOR_MUTEX
#endif
#include <new>
#include "Mutex.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
template<int BLOCK_SIZE>
class CBlockAllocator
{
private:
class Node
{
public:
Node * mNext;
unsigned mBuffer[(BLOCK_SIZE-1)/sizeof(unsigned)+1];
};
public:
CBlockAllocator() :
mMemoryBlockCount(0),
mNodesAllocated(0),
mNodesUsed(0),
mUnusedList(0)
{
for (int block=0; block<MAX_BLOCK_COUNT; block++)
mMemoryBlock[block] = 0;
Allocate();
}
~CBlockAllocator()
{
for (int block=0; block<MAX_BLOCK_COUNT; block++)
delete[] mMemoryBlock[block];
}
void * Allocate()
{
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Lock();
#endif
void * data;
Node * node = mUnusedList;
mUnusedList = node->mNext;
node->mNext = (Node *)1;
data = node->mBuffer;
mNodesUsed++;
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Unlock();
#endif
return data;
}
void Deallocate(void * data)
{
if (!data)
return;
char * memoryPtr = reinterpret_cast<char *>(data) - sizeof(Node *);
Node * node = reinterpret_cast<Node *>(memoryPtr);
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Lock();
#endif
node->mNext = mUnusedList;
mUnusedList = node;
mNodesUsed--;
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Unlock();
#endif
}
template<class T> T * Construct(const T & object)
{
T * objectPtr;
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Lock();
#endif
if (sizeof(T) > BLOCK_SIZE || (!mUnusedList && !Allocate()))
{
char * memoryPtr = reinterpret_cast<char *>(new unsigned[(sizeof(Node *)+sizeof(T)-1)/sizeof(unsigned)+1]);
objectPtr = reinterpret_cast<T *>(memoryPtr+sizeof(Node *));
*reinterpret_cast<unsigned *>(memoryPtr) = 0;
}
else
{
Node * node = mUnusedList;
mUnusedList = node->mNext;
node->mNext = (Node *)1;
objectPtr = reinterpret_cast<T *>(node->mBuffer);
mNodesUsed++;
}
new (objectPtr) T(object);
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Unlock();
#endif
return objectPtr;
}
template<class T> void Destroy(T * object)
{
if (!object)
return;
char * memoryPtr = reinterpret_cast<char *>(object) - sizeof(Node *);
Node * node = reinterpret_cast<Node *>(memoryPtr);
object->~T();
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Lock();
#endif
if (node->mNext == 0)
delete []memoryPtr;
else
{
node->mNext = mUnusedList;
mUnusedList = node;
mNodesUsed--;
}
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Unlock();
#endif
}
template<class T> T * FastConstruct(const T & object)
{
T * objectPtr;
if (sizeof(T) > BLOCK_SIZE || (!mUnusedList && !Allocate()))
{
char * memoryPtr = reinterpret_cast<char *>(new unsigned[(sizeof(Node *)+sizeof(T)-1)/sizeof(unsigned)+1]);
objectPtr = reinterpret_cast<T *>(memoryPtr+sizeof(Node *));
*reinterpret_cast<unsigned *>(memoryPtr) = 0;
}
else
{
Node * node = mUnusedList;
mUnusedList = node->mNext;
node->mNext = (Node *)1;
objectPtr = reinterpret_cast<T *>(node->mBuffer);
mNodesUsed++;
}
new (objectPtr) T(object);
return objectPtr;
}
template<class T> void FastDestroy(T * object)
{
if (!object)
return;
char * memoryPtr = reinterpret_cast<char *>(object) - sizeof(Node *);
Node * node = reinterpret_cast<Node *>(memoryPtr);
object->~T();
if (node->mNext == 0)
delete []memoryPtr;
else
{
node->mNext = mUnusedList;
mUnusedList = node;
mNodesUsed--;
}
}
bool Allocate()
{
if (mMemoryBlockCount == MAX_BLOCK_COUNT)
return false;
unsigned count = (mNodesAllocated ? mNodesAllocated : 32);
Node* newMemoryBlock = new Node[count];
for (unsigned i=0; i<count-1; i++)
newMemoryBlock[i].mNext = &newMemoryBlock[i+1];
newMemoryBlock[count-1].mNext = mUnusedList;
mUnusedList = newMemoryBlock;
mMemoryBlock[mMemoryBlockCount++] = newMemoryBlock;
mNodesAllocated += count;
return true;
};
private:
enum { MAX_BLOCK_COUNT = 32 };
void * mMemoryBlock[MAX_BLOCK_COUNT];
unsigned mMemoryBlockCount;
unsigned mNodesAllocated;
unsigned mNodesUsed;
Node * mUnusedList;
#ifdef USE_ALLOCATOR_MUTEX
Base::CMutex mMutex;
#endif
};
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // BLOCK_ALLOCATOR_H
@@ -0,0 +1,200 @@
// TemplateCBlockAlloc.h: interface for the CBlockAlloc class.
//
//////////////////////////////////////////////////////////////////////
#ifndef _TEMPLATE_COBJECTALLOCATOR_H
#define _TEMPLATE_COBJECTALLOCATOR_H
#if defined _MT || defined _REENTRANT
# define USE_ALLOCATOR_MUTEX
#endif
#include <new>
#include "Types.h"
#include "Mutex.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
const uint32 MAX_BLOCK_COUNT = 32;
template <class TYPE>
class CObjectAllocator
{
public:
CObjectAllocator(uint32 size=32)
{
if (size < 32)
size = 32;
for (uint32 index=0; index<MAX_BLOCK_COUNT; index++)
mMemoryBlock[index] = 0;
mMemoryBlockCount = 0;
mObjectsAllocated = 0;
mObjectCount = 0;
mUnusedList = 0;
mBytesAllocated = 0;
Allocate(size);
}
~CObjectAllocator()
{
for (uint32 index=0; index<MAX_BLOCK_COUNT; index++)
delete[] mMemoryBlock[index];
}
TYPE *Construct()
{
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Lock();
#endif
if (!mUnusedList)
Allocate(mObjectCount);
Node *node = mUnusedList;
mUnusedList = mUnusedList->next;
new (node) TYPE;
mObjectCount++;
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Unlock();
#endif
return (TYPE *)node;
}
TYPE *Construct(const TYPE& object)
{
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Lock();
#endif
if (!mUnusedList)
Allocate(mObjectCount);
Node *node = mUnusedList;
mUnusedList = mUnusedList->next;
new (node) TYPE(object);
mObjectCount++;
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Unlock();
#endif
return (TYPE *)node;
}
void Destroy(TYPE *object)
{
if (object == NULL)
return;
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Lock();
#endif
object->~TYPE();
Node *node = reinterpret_cast<Node *>(object);
node->next = mUnusedList;
mUnusedList = node;
mObjectCount--;
#ifdef USE_ALLOCATOR_MUTEX
mMutex.Unlock();
#endif
}
TYPE *FastConstruct()
{
if (!mUnusedList)
Allocate(mObjectCount);
Node *node = mUnusedList;
mUnusedList = mUnusedList->next;
new (node) TYPE;
mObjectCount++;
return (TYPE *)node;
}
TYPE *FastConstruct(const TYPE& object)
{
if (!mUnusedList)
Allocate(mObjectCount);
Node *node = mUnusedList;
mUnusedList = mUnusedList->next;
new (node) TYPE(object);
mObjectCount++;
return (TYPE *)node;
}
void FastDestroy(TYPE *object)
{
if (object == NULL)
return;
object->~TYPE();
Node *node = reinterpret_cast<Node *>(object);
node->next = mUnusedList;
mUnusedList = node;
mObjectCount--;
}
private:
struct Node
{
char buffer[sizeof(TYPE)];
Node* next;
};
bool Allocate(uint32 size)
{
if (mMemoryBlockCount == MAX_BLOCK_COUNT)
return false;
Node* newMemoryBlock = new Node[size];
mBytesAllocated += size * sizeof(Node);
for (uint32 i=0; i<size-1; i++)
newMemoryBlock[i].next = &newMemoryBlock[i+1];
newMemoryBlock[size-1].next = mUnusedList;
mUnusedList = newMemoryBlock;
mMemoryBlock[mMemoryBlockCount++] = newMemoryBlock;
mObjectsAllocated += size;
return true;
};
Node* mMemoryBlock[MAX_BLOCK_COUNT];
uint32 mMemoryBlockCount;
uint32 mObjectsAllocated;
uint32 mObjectCount;
Node* mUnusedList;
#ifdef USE_ALLOCATOR_MUTEX
CMutex mMutex;
#endif
uint64 mBytesAllocated;
};
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // _TEMPLATE_CBLOCKALLOC_H
@@ -0,0 +1,22 @@
#ifndef BASE_THREAD_H
#define BASE_THREAD_H
#ifdef WIN32
#include "win32/Thread.h"
#elif linux
#include "linux/Thread.h"
#elif sparc
#include "solaris/Thread.h"
#else
#error /Base/Thread.h: Undefine platform type
#endif
#endif // BASE_THREAD_H
@@ -0,0 +1,29 @@
#ifndef BASE_TYPES_H
#define BASE_TYPES_H
#ifdef WIN32
# define FILENAME (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#else
# define FILENAME __FILE__
#endif
#ifdef WIN32
#include "win32/Types.h"
#elif linux
#include "linux/Types.h"
#elif sparc
#include "solaris/Types.h"
#else
#error /Base/Types.h: Undefine platform type
#endif
#endif
@@ -0,0 +1,664 @@
#ifndef BASE__UCS2_H
#define BASE__UCS2_H
#include <algorithm>
#include <string>
#include <vector>
#include "Base/Archive.h"
namespace ucs2
{
class string
{
public:
typedef unsigned short char_type;
typedef unsigned size_type;
public:
string();
string(const string & copy);
string(const char * copy);
string(const char_type * copy);
explicit string(const std::string & copy);
~string();
string & operator=(const char * rhs);
string & operator=(const std::string & rhs);
string & operator=(const char_type * rhs);
string & operator=(const string & rhs);
string & operator+=(const char * rhs);
string & operator+=(const std::string & rhs);
string & operator+=(const char_type * rhs);
string & operator+=(const string & rhs);
const char_type & at(size_type index) const;
char_type & at(size_type index);
const char_type & operator[](size_type index) const;
char_type & operator[](size_type index);
bool operator==(const string & rhs) const;
bool operator!=(const string & rhs) const;
bool operator<(const string & rhs) const;
bool operator<=(const string & rhs) const;
bool operator>(const string & rhs) const;
bool operator>=(const string & rhs) const;
string & assign(const char_type * rhs);
string & assign(const char_type * rhs, size_type count);
string & assign(const string & rhs, size_type position, size_type count);
string & assign(const string & rhs);
string & assign(size_type count, char_type c);
string & assign(const char_type * first, const char_type * last);
string & append(const char_type * rhs);
string & append(const char_type * rhs, size_type count);
string & append(const string & rhs, size_type position, size_type count);
string & append(const string & rhs);
string & append(size_type count, char_type c);
string & append(const char_type * first, const char_type * last);
std::string narrow() const;
const char_type * c_str() const;
const char_type * data() const;
size_type length() const;
size_type size() const;
size_type max_size() const;
void resize(size_type n, char_type c = 0x0032);
size_type capacity() const;
void reserve(size_type n = 0);
bool empty() const;
private:
size_type mLength;
std::vector<char_type> mData;
static char_type mOutOfRangeCharacter;
};
inline char WideToNarrow(string::char_type c) { return (char)c; }
inline string::char_type NarrowToWide(char c) { return (string::char_type)c; }
string::char_type string::mOutOfRangeCharacter(0);
////////////////////////////////////////
// default constructor allocates 8 characters and sets length to zero
inline string::string() :
mLength(0),
mData(8,0)
{
}
////////////////////////////////////////
// target string is a null-terminated C string
inline string::string(const char * copy) :
mLength(0),
mData(8,0)
{
// (1) protect from null pointer
if (!copy)
{
return;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (*copy)
{
reserve(mLength+1);
mData[mLength++] = *copy++;
}
// (3) ensure null termination
mData[mLength]=0;
}
////////////////////////////////////////
// target string is a C string that may or may not include null characters
inline string::string(const std::string & copy) :
mLength(copy.length()),
mData(8,0)
{
// (1) ensure we have the storage for the entire string
reserve(mLength);
// (2) perform transform to copy the narrow string to our
// wide string
std::transform(copy.begin(), copy.end(), mData.begin(), NarrowToWide);
// (3) ensure null termination
mData[mLength] = 0;
}
////////////////////////////////////////
// target string is a wide null-terminated C string
inline string::string(const char_type * copy) :
mLength(0),
mData(8,0)
{
// (1) protect from null pointer
if (!copy)
{
return;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (*copy)
{
reserve(mLength+1);
mData[mLength++] = *copy++;
}
// (3) ensure null termination
mData[mLength]=0;
}
////////////////////////////////////////
// copy constructor
inline string::string(const string & copy) :
mLength(copy.mLength),
mData(8,0)
{
reserve(mLength);
mData.assign(copy.mData.begin(), copy.mData.begin()+copy.mLength+1);
}
inline string::~string()
{
}
inline string & string::operator=(const char * rhs)
{
mLength = 0;
// (1) protect from null pointer
if (!rhs)
{
mData[0] = 0;
return *this;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (*rhs)
{
reserve(mLength+1);
mData[mLength++] = *rhs++;
}
// (3) ensure null termination
mData[mLength]=0;
return *this;
}
inline string & string::operator=(const std::string & rhs)
{
mLength = rhs.length();
// (1) ensure we have the storage for the entire string
reserve(mLength);
// (2) perform transform to copy the narrow string to our
// wide string
std::transform(rhs.begin(), rhs.end(), mData.begin(), NarrowToWide);
// (3) ensure null termination
mData[mLength] = 0;
return *this;
}
inline string & string::operator=(const char_type * rhs)
{
mLength = 0;
// (1) protect from null pointer
if (!rhs)
{
mData[0] = 0;
return *this;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (*rhs)
{
reserve(mLength+1);
mData[mLength++] = *rhs++;
}
// (3) ensure null termination
mData[mLength]=0;
return *this;
}
inline string & string::operator=(const string & rhs)
{
// (1) protect from assigning to self
if (&rhs != this)
{
mLength = rhs.mLength;
reserve(mLength);
mData.assign(rhs.mData.begin(), rhs.mData.begin()+rhs.mLength+1);
}
return *this;
}
inline string & string::operator+=(const char * rhs)
{
// (1) protect from null pointer
if (!rhs)
{
return *this;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (*rhs)
{
reserve(mLength+1);
mData[mLength++] = *rhs++;
}
// (3) ensure null termination
mData[mLength]=0;
return *this;
}
inline string & string::operator+=(const std::string & rhs)
{
// (1) ensure we have the storage for the entire string
reserve(mLength+rhs.length());
// (2) perform transform to copy the narrow string to our
// wide string
std::transform(rhs.begin(), rhs.end(), mData.begin()+mLength, NarrowToWide);
// (3) ensure null termination
mLength += rhs.length();
mData[mLength] = 0;
return *this;
}
inline string & string::operator+=(const char_type * rhs)
{
// (1) protect from null pointer
if (!rhs)
{
return *this;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (*rhs)
{
reserve(mLength+1);
mData[mLength++] = *rhs++;
}
// (3) ensure null termination
mData[mLength]=0;
return *this;
}
inline string & string::operator+=(const string & rhs)
{
reserve(mLength+rhs.mLength);
std::copy(rhs.mData.begin(), rhs.mData.begin()+rhs.mLength+1, mData.begin()+mLength);
mLength += rhs.mLength;
return *this;
}
inline const string::char_type & string::at(string::size_type index) const
{
return (index > mLength) ? mOutOfRangeCharacter : mData[index];
}
inline string::char_type & string::at(string::size_type index)
{
return (index > mLength) ? mOutOfRangeCharacter : mData[index];
}
inline const string::char_type & string::operator[](string::size_type index) const
{
return (index > mLength) ? mOutOfRangeCharacter : mData[index];
}
inline string::char_type & string::operator[](string::size_type index)
{
return (index > mLength) ? mOutOfRangeCharacter : mData[index];
}
inline bool string::operator==(const string & rhs) const
{
if (mLength != rhs.mLength)
{
return false;
}
else
{
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) == 0);
}
}
inline bool string::operator!=(const string & rhs) const
{
if (mLength != rhs.mLength)
{
return true;
}
else
{
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) != 0);
}
}
inline bool string::operator<(const string & rhs) const
{
if (mLength <= rhs.mLength)
{
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) < 0);
}
else
{
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*rhs.mLength) < 0);
}
}
inline bool string::operator<=(const string & rhs) const
{
if (mLength <= rhs.mLength)
{
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) <= 0);
}
else
{
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*rhs.mLength) <= 0);
}
}
inline bool string::operator>(const string & rhs) const
{
if (mLength <= rhs.mLength)
{
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) > 0);
}
else
{
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*rhs.mLength) > 0);
}
}
inline bool string::operator>=(const string & rhs) const
{
if (mLength <= rhs.mLength)
{
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*mLength) >= 0);
}
else
{
return (memcmp(&mData[0], &rhs.mData[0], sizeof(size_type)*rhs.mLength) >= 0);
}
}
inline string & string::assign(const char_type * rhs)
{
mLength = 0;
// (1) protect from null pointer
if (!rhs)
{
mData[0] = 0;
return *this;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (*rhs)
{
reserve(mLength+1);
mData[mLength++] = *rhs++;
}
// (3) ensure null termination
mData[mLength]=0;
return *this;
}
inline string & string::assign(const char_type * rhs, size_type count)
{
mLength = 0;
// (1) protect from null pointer
if (!rhs)
{
mData[0] = 0;
return *this;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (count--)
{
reserve(mLength+1);
mData[mLength++] = *rhs++;
}
// (3) ensure null termination
mData[mLength]=0;
return *this;
}
inline string & string::assign(const string & rhs, size_type position, size_type count)
{
// (1) protect from assigning to self
if (&rhs != this)
{
mLength = count;
reserve(mLength);
mData.assign(rhs.mData.begin()+position, rhs.mData.begin()+position+count+1);
}
return *this;
}
inline string & string::assign(const string & rhs)
{
// (1) protect from assigning to self
if (&rhs != this)
{
mLength = rhs.mLength;
reserve(mLength);
mData.assign(rhs.mData.begin(), rhs.mData.begin()+rhs.mLength+1);
}
return *this;
}
inline string & string::assign(size_type count, char_type c)
{
mLength = count;
reserve(mLength);
std::fill(mData.begin(), mData.end(), c);
mData[mLength]=0;
return *this;
}
inline string & string::assign(const char_type * first, const char_type * last)
{
mLength = 0;
// (1) protect from null pointer
if (!first || !last)
{
mData[0] = 0;
return *this;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (first != last)
{
reserve(mLength+1);
mData[mLength++] = *first++;
}
// (3) ensure null termination
mData[mLength]=0;
return *this;
}
inline string & string::append(const char_type * rhs)
{
// (1) protect from null pointer
if (!rhs)
{
return *this;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (*rhs)
{
reserve(mLength+1);
mData[mLength++] = *rhs++;
}
// (3) ensure null termination
mData[mLength]=0;
return *this;
}
inline string & string::append(const char_type * rhs, size_type count)
{
// (1) protect from null pointer
if (!rhs)
{
return *this;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (count--)
{
reserve(mLength+1);
mData[mLength++] = *rhs++;
}
// (3) ensure null termination
mData[mLength]=0;
return *this;
}
inline string & string::append(const string & rhs, size_type position, size_type count)
{
// (1) protect from invalid position value
if (rhs.mLength <= position)
{
return *this;
}
// (2) make sure we copy count charatcers, or to the end of the string
if (rhs.mLength < position+count)
{
count = rhs.mLength-position;
}
// (3) perform copy
reserve(mLength+count);
std::copy(rhs.mData.begin()+position, rhs.mData.begin()+position+count+1, mData.begin()+mLength);
mLength += count;
return *this;
}
inline string & string::append(const string & rhs)
{
// (1) perform copy
reserve(mLength+rhs.mLength);
std::copy(rhs.mData.begin(), rhs.mData.begin()+rhs.mLength+1, mData.begin()+mLength);
mLength += rhs.mLength;
return *this;
}
inline string & string::append(size_type count, char_type c)
{
reserve(mLength+count);
std::fill(mData.begin()+mLength, mData.begin()+mLength+count, c);
mLength += count;
mData[mLength]=0;
return *this;
}
inline string & string::append(const char_type * first, const char_type * last)
{
// (1) protect from null pointer
if (!first || !last)
{
return *this;
}
// (2) linear copy the string, must reserve before each character
// because the string length is unknown
while (first != last)
{
reserve(mLength+1);
mData[mLength++] = *first++;
}
// (3) ensure null termination
mData[mLength]=0;
return *this;
}
inline std::string string::narrow() const
{
std::string narrow;
narrow.resize(mLength);
std::transform(mData.begin(), mData.begin()+mLength+1, narrow.begin(), WideToNarrow);
return narrow;
}
inline const string::char_type * string::c_str() const
{
return &mData[0];
}
inline const string::char_type * string::data() const
{
return &mData[0];
}
inline string::size_type string::length() const
{
return mLength;
}
inline string::size_type string::size() const
{
return mLength;
}
inline void string::resize(string::size_type n, string::char_type c)
{
reserve(n);
while (mLength<n)
{
mData[mLength++] = c;
}
}
inline string::size_type string::capacity() const
{
return mData.size()-1;
}
inline void string::reserve(string::size_type n)
{
while (n > capacity())
mData.resize((capacity()+1)*2,0x0000);
}
inline bool string::empty() const
{
return mLength == 0;
}
}
namespace Base
{
inline void get(ByteStream::ReadIterator & source, ucs2::string & target)
{
unsigned int size = 0;
get(source, size);
const unsigned char * const buf = source.getBuffer();
const ucs2::string::char_type * const ubuf = reinterpret_cast<const ucs2::string::char_type *>(buf);
target.assign(ubuf, ubuf + size);
const unsigned int readSize = size * sizeof(ucs2::string::char_type);
source.advance(readSize);
}
inline void put(ByteStream & target, const ucs2::string & source)
{
const unsigned int size = source.size();
put(target, size);
put(target, (const unsigned char *)source.data(), size*sizeof(ucs2::string::char_type));
}
}
#endif
@@ -0,0 +1,165 @@
#include "ccspanutil.h"
#include <stdlib.h>
#include <string.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
char * CSpanUtil::getDescriptionFromCardNum(const char *cardNum)
{
// if the card number is less than this we wont be able to determine it, and we dont want to crash so . . .
if(strlen(cardNum) < 8 )
return "Credit Card";
switch(cardNum[0])
{
case '3':
if(cardNum[1] == '4')
return "AMEX";
if(cardNum[1] == '7')
{
// RG 5/9 changed to fix rrc=233. We do not support OP anyway.
// Card prefix check is unclear.
//
// if(cardNum[3] == '7')
// return "OP";
// else
return "AMEX";
}
if((cardNum[1] == '0') || (cardNum[1] == '6'))
return "DINERS";
if(cardNum[1] == '8')
{
if((cardNum[2] >= '1') && (cardNum[2] <= '8'))
return "DINERS";
}
if(cardNum[1] == '5')
{
char temp[3];
memcpy(temp, &cardNum[2], 2);
temp[2] = 0;
int value = atoi(temp);
if((value >= 28) && (value <= 89))
return "JCB";
}
break;
case '4':
// RG 5/6 changed to fix rrc=233. We do not support SW anyway.
// Card prefix check is unclear.
//
// if(cardNum[1] == '9')
// return "SW";
// else
return "VISA";
break;
case '5':
if(cardNum[1] == '6')
return "Switch/solo";
if((cardNum[1] >= '1') && (cardNum[1] <= '5'))
return "MC";
if(memcmp(cardNum, "504990", 6) == 0)
return "Bill me Later";
break;
case '6':
{
char temp[8];
memcpy(temp, cardNum, 7);
temp[7] = 0;
int value7 = atoi(temp);
temp[6] = 0;
int value6 = atoi(temp);
temp[5] = 0;
int value5 = atoi(temp);
// september 29 2005 added new card IIN ranges for Discover per email from
// paymentTech email effective Oct 1, 2005
if((value5 == 60110) ||
(value5 == 60112) ||
(value5 == 60113) ||
(value5 == 60114) ||
(value5 == 60115) ||
(value5 == 60116) ||
(value6 == 601174) ||
(value6 >= 601177 && value6 <= 601179) ||
(value6 >=601186 && value6 <= 600189) ||
(value5 == 60119) ||
(value6 >= 650000 && value6 <=650999))
return "DISCOVER";
if(value6 == 603571)
return "Saved Value";
return "Switch/Solo";
}
break;
case '7':
return "Switch/Solo";
break;
case '9':
//if((cardNum[1] == '4') && (cardNum[1] == '5'))
return "Carte Blanche";
break;
}
return "Credit Card";
}
// generates a credit card span for an account number string up to a length of any size.
std::string CSpanUtil::generateCCSpan(std::string cardNumber)
{
// according to the PCI standard on visa's web site, the max number of displayable digits for a cc are the first 6 and last 4
// we will however require that at least the middle half of the card is not shown
std::string ccSpan;
const std::string asteriks = "*";
// if the length of the card is an odd number we will display the larger portion of the card on the front viewable amount.
// for Amex this will look like 1234********123
// on a 16 digit card, the most digits will be displayed being 1234********1234
// a 12 digit card would look like 123******123
// as per qa request and devtrack bug 2440 masking is first 4 and las 4 visible
unsigned displayableBeginningDigits = 4;
unsigned displayableEndingDigits = 4;
if(cardNumber.length() <= 8)
return cardNumber;
ccSpan = cardNumber.substr(0, displayableBeginningDigits);
unsigned totalMasked = cardNumber.length() - displayableBeginningDigits - displayableEndingDigits;
// now add in characters to mask the middle numbers
for(unsigned maskedDigits = 0; maskedDigits < totalMasked; maskedDigits++)
ccSpan += asteriks;
ccSpan += cardNumber.substr((totalMasked+displayableBeginningDigits));
return ccSpan;
}
std::string CSpanUtil::generateCCDescription(std::string cardNumber)
{
std::string ccDescription;
// get the card type
ccDescription = std::string(getDescriptionFromCardNum(cardNumber.c_str())) + std::string("(") + generateCCSpan(cardNumber) + std::string(")");
return ccDescription;
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,40 @@
#ifndef _CCSPANUTIL_H
#define _CCSPANUTIL_H
#pragma warning (disable : 4786)
#include <stdio.h>
#include <string>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
class CSpanUtil
{
public:
//determine the type of credit card according to credit number
static char *getDescriptionFromCardNum(const char *cardNum);
// generates a credit card span for an account number string up to a length of any size.
static std::string generateCCSpan(std::string cardNumber);
// generartes credit card description consist of card type + a credit card span
static std::string generateCCDescription(std::string cardNumber);
// constructor
CSpanUtil();
// destructor
~CSpanUtil();
};
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,44 @@
#ifndef BASE_LINUX_ARCHIVE_H
#define BASE_LINUX_ARCHIVE_H
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#ifdef PACK_BIG_ENDIAN
inline double byteSwap(double value) { byteReverse(&value); return value; }
inline float byteSwap(float value) { byteReverse(&value); return value; }
inline uint64 byteSwap(uint64 value) { byteReverse(&value); return value; }
inline int64 byteSwap(int64 value) { byteReverse(&value); return value; }
inline uint32 byteSwap(uint32 value) { byteReverse(&value); return value; }
inline int32 byteSwap(int32 value) { byteReverse(&value); return value; }
inline uint16 byteSwap(uint16 value) { byteReverse(&value); return value; }
inline int16 byteSwap(int16 value) { byteReverse(&value); return value; }
#else
inline double byteSwap(double value) { return value; }
inline float byteSwap(float value) { return value; }
inline uint64 byteSwap(uint64 value) { return value; }
inline int64 byteSwap(int64 value) { return value; }
inline uint32 byteSwap(uint32 value) { return value; }
inline int32 byteSwap(int32 value) { return value; }
inline uint16 byteSwap(uint16 value) { return value; }
inline int16 byteSwap(int16 value) { return value; }
#endif
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,110 @@
#include "../BlockAllocator.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
BlockAllocator::BlockAllocator()
{
for(unsigned i = 0; i < 31; i++)
{
m_blocks[i] = NULL;
}
}
BlockAllocator::~BlockAllocator()
{
// free all allocated memory blocks
for(unsigned i = 0; i < 31; i++)
{
while(m_blocks[i] != NULL)
{
unsigned *tmp = m_blocks[i];
m_blocks[i] = (unsigned *)*m_blocks[i];
free(tmp);
}
}
}
// Allocate a block that is the next power of two greater than the # of bytes passed.
// 33 bytes yields a 64 byte block of memory and so forth.
void *BlockAllocator::getBlock(unsigned bytes)
{
unsigned accum = 16, bits = 16;
unsigned *handle = NULL;
// Perform a binary search looking for the highest bit.
while(bits != 0)
{
// If bytes is less than the bit we're testing for, subtract half
// from the bit value and repeat
if(bytes < (unsigned)(1 << accum))
{
bits /= 2;
accum -= bits;
}
// If bytes is greater than the bit we're testing for, add half
// from the but value and repeat
else if(bytes > (unsigned)(1 << accum))
{
bits /= 2;
accum += bits;
}
// Got lucky and hit the value dead on
else
{
break;
}
}
// At this point accum contains the most significant bit index, increment
accum++;
if(accum < 2)
{
accum = 2;
}
// Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front
// The first integer is the address of the next block of memory when the block is in the allocator
// The second integer is the bit length of the block
// Memory is allocated on 4 byte boundaries to sidestep byte alignment problems
// Check if the allocator already has a block of that size
if(m_blocks[accum] == 0)
{
// remove the pre allocated block from the linked list
handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned));
handle[1] = accum;
handle[0] = 0;
}
else
{
// Allocate a new block
handle = m_blocks[accum];
m_blocks[accum] = (unsigned *)handle[0];
handle[0] = 0;
}
// return a pointer that skips over the header used for the allocator's purposes
return(handle + 2);
}
void BlockAllocator::returnBlock(unsigned *handle)
{
// C++ allows for safe deletion of a NULL pointer
if(handle)
{
// Update the allocator linked list, insert this entry at the head
*(handle - 2) = (unsigned)m_blocks[*(handle - 1)];
// Add this entry to the proper linked list node
m_blocks[*(handle - 1)] = (handle - 2);
}
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,103 @@
////////////////////////////////////////
// Event.cpp
//
// Purpose:
// 1. Implementation of the CEvent class.
//
// Revisions:
// 07/10/2001 Created
//
#if defined(_REENTRANT)
#include "Event.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
CEvent::CEvent() :
mMutex(),
mCond(),
mThreadCount(0)
{
pthread_mutex_init(&mMutex, NULL);
pthread_cond_init(&mCond, NULL);
}
CEvent::~CEvent()
{
pthread_cond_destroy(&mCond);
pthread_mutex_destroy(&mMutex);
}
bool CEvent::Signal()
{
pthread_mutex_lock(&mMutex);
if (mThreadCount == 0)
mThreadCount = SIGNALED;
pthread_cond_signal(&mCond);
pthread_mutex_unlock(&mMutex);
return true;
}
int32 CEvent::Wait(uint32 timeout)
{
int result;
pthread_mutex_lock(&mMutex);
if (mThreadCount == SIGNALED)
{
mThreadCount = 0;
pthread_mutex_unlock(&mMutex);
return eWAIT_SIGNAL;
}
if (!timeout)
{
mThreadCount++;
result = pthread_cond_wait(&mCond, &mMutex);
mThreadCount--;
pthread_mutex_unlock(&mMutex);
}
else
{
struct timeval now;
struct timespec abs_timeout;
gettimeofday(&now, NULL);
abs_timeout.tv_sec = now.tv_sec + timeout/1000;
abs_timeout.tv_nsec = now.tv_usec * 1000 + (timeout%1000)*1000000;
abs_timeout.tv_sec += abs_timeout.tv_nsec / 1000000000;
abs_timeout.tv_nsec %= 1000000000;
mThreadCount++;
result = pthread_cond_timedwait(&mCond, &mMutex, &abs_timeout);
mThreadCount--;
pthread_mutex_unlock(&mMutex);
}
if (result == 0 || result == EINTR)
return eWAIT_SIGNAL;
else if (result == ETIMEDOUT)
return eWAIT_TIMEOUT;
else
return eWAIT_ERROR;
}
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_REENTRANT)
@@ -0,0 +1,74 @@
////////////////////////////////////////
// Event.h
//
// Purpose:
// 1. Declair the CEvent class that encapsulates the functionality of a
// single-locking semaphore.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_LINUX_EVENT_H
#define BASE_LINUX_EVENT_H
#if !defined(_REENTRANT)
# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_REENTRANT)" )
#else
#include <pthread.h>
#include "Platform.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
////////////////////////////////////////
// Class:
// CEvent
//
// Purpose:
// Encapsulates the functionality of a singal-locking semaphore.
// This class is valuable for thread syncronization when a thead's
// execution needs to be dependent upon another thread.
//
// Public Methods:
// Signal() : Signals a thread that has called Wait() so that it can
// continue execution. This function returns true if the waiting
// thread was signalled successfully, otherwise false is returned.
// Wait() : Halts the calling thread's execution indefinately until
// a Singal() call is made by an external thread. If the thread is
// successfully signalled, the function returns eWAIT_SIGNAL. If
// timeout period expires without a signal, eWAIT_TIMEOUT is returned.
// If the function fails, eWAIT_ERROR is returned.
//
class CEvent
{
public:
CEvent();
virtual ~CEvent();
bool Signal();
int32 Wait(uint32 timeout = 0);
public:
enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT };
enum { SIGNALED = -1 };
private:
pthread_mutex_t mMutex;
pthread_cond_t mCond;
int mThreadCount;
};
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_MT)
#endif // BASE_LINUX_EVENT_H
@@ -0,0 +1,40 @@
////////////////////////////////////////
// Mutex.cpp
//
// Purpose:
// 1. Implementation of the CMutex class.
//
// Revisions:
// 07/10/2001 Created
//
#if defined(_REENTRANT)
#include "Mutex.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
CMutex::CMutex()
{
mInitialized = (pthread_mutex_init(&mMutex, 0) == 0);
}
CMutex::~CMutex()
{
if (mInitialized)
pthread_mutex_destroy(&mMutex);
}
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_REENTRANT)
@@ -0,0 +1,79 @@
////////////////////////////////////////
// Mutex.h
//
// Purpose:
// 1. Declair the CMutex class that encapsulates the functionality of a
// mutually-exclusive device.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_LINUX_MUTEX_H
#define BASE_LINUX_MUTEX_H
#if !defined(_REENTRANT)
# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_REENTRANT)" )
#else
#include "Platform.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
////////////////////////////////////////
// Class:
// CMutex
//
// Purpose:
// Encapsulates the functionality of a mutually-exclusive device.
// This class is valuable for protecting against race conditions
// within threaded applications. The CMutex class can be used to
// only allow a single thread to run within a specified code
// segment at a time.
//
// Public Methods:
// Lock() : Locks the mutex. If the mutex is already locked, the
// operating system will block the calling thread until another
// thread has unlocked the mutex.
// Unlock() : Unlocks the mutex.
//
class CMutex
{
public:
CMutex();
~CMutex();
void Lock();
void Unlock();
private:
pthread_mutex_t mMutex;
bool mInitialized;
};
inline void CMutex::Lock(void)
{
if (mInitialized)
pthread_mutex_lock(&mMutex);
}
inline void CMutex::Unlock(void)
{
if (mInitialized)
pthread_mutex_unlock(&mMutex);
}
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_MT)
#endif // BASE_LINUX_MUTEX_H
@@ -0,0 +1,55 @@
////////////////////////////////////////
// Platform.cpp
//
// Purpose:
// 1. Implementation of the global functionality declaired in Platform.h.
//
// Revisions:
// 07/10/2001 Created
//
#include <ctype.h>
#include "Platform.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
// Implementation of microsoft strlwr extension
// This non-ANSI function is not supported under UNIX
void strlwr(char * s)
{
while (*s)
{
*s = tolower(*s);
s++;
}
}
// Implementation of microsoft strlwr extension
// This non-ANSI function is not supported under UNIX
void strupr(char * s)
{
while (*s)
{
*s = toupper(*s);
s++;
}
}
CTimer::CTimer() :
mTimer(0)
{
}
}
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,112 @@
////////////////////////////////////////
// Platform.h
//
// Purpose:
// 1. Include relevent system headers that are platform specific.
// 2. Declair global platform specific functionality.
// 3. Include primative type definitions
//
// Global Functions:
// getTimer() : Return the current high resolution clock count.
// getTimerFrequency() : Return the frequency of the high resolution clock.
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
// specified number of milliseconds.
// strlwr() : Alters the contents of a string, making it all lower-case.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_LINUX_PLATFORM_H
#define BASE_LINUX_PLATFORM_H
#include <errno.h>
#include <assert.h>
#include <sys/errno.h>
#include <pthread.h>
#include <resolv.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include "Types.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
uint64 getTimer(void);
uint64 getTimerFrequency(void);
void sleep(uint32 ms);
inline uint64 getTimer(void)
{
uint64 t;
struct timeval tv;
gettimeofday(&tv, 0);
t = tv.tv_sec;
t = t * 1000000;
t += tv.tv_usec;
return t;
}
inline uint64 getTimerFrequency(void)
{
uint64 f = 1000000;
return f;
}
inline void sleep(uint32 ms)
{
usleep(static_cast<unsigned long>(ms * 1000));
}
void strlwr(char * s);
void strupr(char * s);
class CTimer
{
public:
CTimer();
void Set(uint32 seconds);
void Signal();
bool Expired();
private:
uint32 mTimer;
};
inline void CTimer::Set(uint32 interval)
{
mTimer = (uint32)time(0) + interval;
}
inline void CTimer::Signal()
{
mTimer = 0;
}
inline bool CTimer::Expired()
{
return (mTimer <= (uint32)time(0));
}
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // BASE_LINUX_PLATFORM_H
@@ -0,0 +1,299 @@
////////////////////////////////////////
// Thread.cpp
//
// Purpose:
// 1. Implementation of the CThread class.
//
// Revisions:
// 07/10/2001 Created
//
#if defined(_REENTRANT)
#include <pthread.h>
#include <time.h>
#include "Thread.h"
using namespace std;
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
void *threadProc(void *threadPtr)
{
CThread &thread = *((CThread*)threadPtr);
thread.mThreadActive = true;
thread.ThreadProc();
thread.mThreadActive = false;
return 0;
}
CThread::CThread()
{
mThreadID = 0;
mThreadActive = false;
mThreadContinue = false;
}
CThread::~CThread()
{
StopThread();
}
void CThread::StartThread()
{
mThreadContinue = true;
if (pthread_create(&mThreadID,0,threadProc,this) == 0)
pthread_detach(mThreadID);
while (!IsThreadActive())
Base::sleep(1);
}
int32 CThread::StopThread(int timeout)
{
timeout += time(0);
mThreadContinue = false;
while (mThreadActive && time(0)<timeout)
sleep(1);
if (mThreadActive)
{
mThreadActive = false;
return eSTOP_TIMEOUT;
}
return eSTOP_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////
CThreadPool::CMember::CMember(CThreadPool * parent) :
mParent(parent),
mFunction(NULL),
mArgument(NULL),
mSemaphore()
{
StartThread();
}
CThreadPool::CMember::~CMember()
{
}
void CThreadPool::CMember::Destroy()
{
mThreadContinue = false;
mSemaphore.Signal();
}
bool CThreadPool::CMember::Execute(void( *function )( void * ), void * arg)
{
if (mFunction)
return false;
mArgument = arg;
mFunction = function;
mSemaphore.Signal();
return true;
}
void CThreadPool::CMember::ThreadProc()
{
mParent->OnStartup(this);
while (mThreadContinue)
{
mParent->OnIdle(this);
mSemaphore.Wait(mParent->GetTimeOut()*1000);
if (mFunction)
{
mFunction(mArgument);
mArgument = NULL;
mFunction = NULL;
}
else if (mParent->OnDestory(this))
mThreadContinue = false;
}
}
////////////////////////////////////////////////////////////////////////////////
CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) :
mMutex(),
mIdleMember(),
mBusyMember(),
mNullMember(),
mThreadCount(0),
mMaxThreads(maxThreads),
mMinThreads(minThreads),
mTimeOut(timeout)
{
if (mMaxThreads == 0) mMaxThreads = 1;
if (mMinThreads == 0) mMinThreads = 1;
if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads;
for (uint32 i=0; i<mMinThreads; i++)
new CMember(this);
}
CThreadPool::~CThreadPool()
{
set<CMember *>::iterator setIterator;
////////////////////////////////////////
// (1) Destory all busy member threads
mMutex.Lock();
setIterator = mBusyMember.begin();
while (setIterator != mBusyMember.end())
(*setIterator++)->Destroy();
mMutex.Unlock();
////////////////////////////////////////
// (2) Destory all idle member threads
while (mThreadCount)
{
mMutex.Lock();
setIterator = mIdleMember.begin();
while (setIterator != mIdleMember.end())
(*setIterator++)->Destroy();
mMutex.Unlock();
sleep(1);
}
////////////////////////////////////////
// (3) Delete the null member threads
mMutex.Lock();
while (!mNullMember.empty())
{
delete mNullMember.front();
mNullMember.pop_front();
}
mMutex.Unlock();
}
bool CThreadPool::Execute(void( *function )( void * ), void * arg, uint32 poolGrowthSize )
{
mMutex.Lock();
////////////////////////////////////////
// (1) If no idle members, return false to indicate that no threads
// were available. If the thread count is below the max, create
// a new thread.
if (mIdleMember.empty())
{
if (mThreadCount < mMaxThreads)
{
if (!poolGrowthSize)
poolGrowthSize = mMinThreads;
if ((mThreadCount + poolGrowthSize) > mMaxThreads)
poolGrowthSize = mMaxThreads - mThreadCount;
for (uint32 i(0); i < poolGrowthSize; i++)
new CMember(this);
mMutex.Unlock();
time_t idleTimeout = time(0) + 5;
while(mIdleMember.empty())
{
if (time(0) >= idleTimeout)
{
return false;
}
Base::sleep(10);
}
mMutex.Lock();
}
else
{
mMutex.Unlock();
return false;
}
}
////////////////////////////////////////
// (2) Delete any null member threads.
while (!mNullMember.empty())
{
delete mNullMember.front();
mNullMember.pop_front();
}
////////////////////////////////////////
// (3) Move the first idle thread to the busy set and signal the
// thread to execute the specified function.
CMember * member = *(mIdleMember.begin());
mIdleMember.erase(member);
mBusyMember.insert(member);
member->Execute(function,arg);
mMutex.Unlock();
return true;
}
uint32 CThreadPool::GetTimeOut()
{
return mTimeOut;
}
void CThreadPool::OnStartup(CMember * member)
{
mMutex.Lock();
mThreadCount++;
mIdleMember.insert(member);
mMutex.Unlock();
}
void CThreadPool::OnIdle(CMember * member)
{
mMutex.Lock();
mBusyMember.erase(member);
mIdleMember.insert(member);
mMutex.Unlock();
}
bool CThreadPool::OnDestory(CMember * member)
{
set<CMember *>::iterator setIterator;
mMutex.Lock();
bool result = (setIterator = mIdleMember.find(member)) != mIdleMember.end();
if (result)
{
mNullMember.push_back(member);
mIdleMember.erase(setIterator);
mThreadCount--;
}
mMutex.Unlock();
return result;
}
////////////////////////////////////////////////////////////////////////////////
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_REENTRANT)
@@ -0,0 +1,146 @@
////////////////////////////////////////
// Thread.h
//
// Purpose:
// 1. Declair the CThread class that encapsulates threading functionality.
// This abstract base class in intended to be used to encapsulate
// individual tasks that require threading in derived classes.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_LINUX_THREAD_H
#define BASE_LINUX_THREAD_H
#if !defined(_REENTRANT)
# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_REENTRANT)" )
#else
#pragma warning( disable : 4786)
#include <list>
#include <set>
#include "Platform.h"
#include "Mutex.h"
#include "Event.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
////////////////////////////////////////
// Class:
// CThread
//
// Purpose:
// Encapsulates threading functionality. Creating classes derived
// from CThread provides an easy way to encapsulate tasks that require
// their own thread.
//
// Public Methods:
// StartThread() : Creates the low-level thread handle and begins executing
// the CThread::ThreadProc() function within the new thread.
// StopThread() : Signals the ThreadProc() function to stop executing using
// the mThreadContinue member variable, and waits for the ThreadProc()
// function to exit. By default, the function will block for a maximum
// of 5 seconds before exiting without the thread halting.
// IsThreadActive() : Returns true if the physical thread is still executing
// within the ThreadProc() function, otherwise it returns false.
// ThreadProc() : Pure-virtual function that will be executed when the StartThread()
// function is called. Derived classes must implement this function. The
// mThreadContinue member variable should be used internal the the ThreadProc()
// function to indicate whether it should continue executing or exit.
// Protected Attributes:
// mThreadContinue : Boolean value indicating to the ThreadProc() function
// whether to continue executing or to exit. If mThreadContinue is true,
// ThreadProc() should continue, otherwise ThreadProc() should exit. It
// left up to the derived class to implement a ThreadProc() function that
// uses the mThreadContinue member.
//
//
class CThread
{
friend void * threadProc(void *);
public:
enum { eSTOP_SUCCESS, eSTOP_TIMEOUT };
public:
CThread();
virtual ~CThread();
void StartThread();
int32 StopThread(int timeout=5);
bool IsThreadActive() { return mThreadActive; }
protected:
virtual void ThreadProc() {}
protected:
bool mThreadContinue;
private:
pthread_t mThreadID;
bool mThreadActive;
};
class CThreadPool
{
private:
class CMember : public CThread
{
public:
CMember(CThreadPool * parent);
virtual ~CMember();
bool Execute(void( *function )( void * ), void * arg);
void Destroy();
protected:
virtual void ThreadProc();
private:
CThreadPool * mParent;
void( * mFunction )( void * );
void * mArgument;
CEvent mSemaphore;
};
friend class CMember;
public:
CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60);
virtual ~CThreadPool();
virtual bool Execute(void( *function )( void * ), void * arg, uint32 poolGrowthSize = 0);
private:
uint32 GetTimeOut();
void OnStartup(CMember * member);
void OnIdle(CMember * member);
bool OnDestory(CMember * member);
private:
CMutex mMutex;
std::set<CMember *> mIdleMember;
std::set<CMember *> mBusyMember;
std::list<CMember *> mNullMember;
uint32 mThreadCount;
uint32 mMaxThreads;
uint32 mMinThreads;
uint32 mTimeOut;
};
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_REENTRANT)
#endif // BASE_LINUX_THREAD_H
@@ -0,0 +1,42 @@
////////////////////////////////////////
// Types.h
//
// Purpose:
// 1. Define integer types that are unambiguous with respect to size
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_LINUX_TYPES_H
#define BASE_LINUX_TYPES_H
#include <sys/bitypes.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#define INT32_MAX 0x7FFFFFFF
#define INT32_MIN 0x80000000
#define UINT32_MAX 0xFFFFFFFF
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // BASE_LINUX_TYPES_H
@@ -0,0 +1,585 @@
#ifndef SOE__SERIALIZE_H
#define SOE__SERIALIZE_H
#include <assert.h>
#include <string>
#include <vector>
#include "Types.h"
#if (defined(WIN32) || defined(linux)) && !defined(NETWORK_BIG_ENDIAN)
#define BYTE1 0
#define BYTE2 1
#define BYTE3 2
#define BYTE4 3
#define BYTE5 4
#define BYTE6 5
#define BYTE7 6
#define BYTE8 7
#elif defined(sparc) || defined(NETWORK_BIG_ENDIAN)
#define BYTE1 7
#define BYTE2 6
#define BYTE3 5
#define BYTE4 4
#define BYTE5 3
#define BYTE6 2
#define BYTE7 1
#define BYTE8 0
#endif
////////////////////////////////////////////////////////////////////////////////
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace soe
{
using namespace Base;//for types
////////////////////////////////////////////////////////////////////////////////
// 388 ns (50 bytes)
inline unsigned Write(unsigned char * stream, unsigned size, const unsigned char * data, unsigned dataLen)
{
if (size < dataLen)
return 0;
memcpy(stream, data, dataLen);
return dataLen;
}
// 353 ns
inline unsigned Write(unsigned char * stream, unsigned size, bool data)
{
if (size < sizeof(uint8))
return 0;
stream[BYTE1] = data;
return sizeof(uint8);
}
// 362 ns
inline unsigned Write(unsigned char * stream, unsigned size, int8 data)
{
if (size < sizeof(int8))
return 0;
stream[BYTE1] = data;
return sizeof(int8);
}
// 362 ns
inline unsigned Write(unsigned char * stream, unsigned size, uint8 data)
{
if (size < sizeof(uint8))
return 0;
stream[BYTE1] = data;
return sizeof(uint8);
}
// 355 ns
inline unsigned Write(unsigned char * stream, unsigned size, int16 data)
{
if (size < sizeof(int16))
return 0;
stream[BYTE1] = data&0xff;
stream[BYTE2] = (data>>8)&0xff;
return sizeof(int16);
}
// 360 ns
inline unsigned Write(unsigned char * stream, unsigned size, uint16 data)
{
if (size < sizeof(uint16))
return 0;
stream[BYTE1] = data&0xff;
stream[BYTE2] = (data>>8)&0xff;
return sizeof(uint16);
}
// 360 ns
inline unsigned Write(unsigned char * stream, unsigned size, int32 data)
{
if (size < sizeof(int32))
return 0;
stream[BYTE1] = data&0xff;
stream[BYTE2] = (data>>8)&0xff;
stream[BYTE3] = (data>>16)&0xff;
stream[BYTE4] = (data>>24)&0xff;
return sizeof(int32);
}
// 360 ns
inline unsigned Write(unsigned char * stream, unsigned size, uint32 data)
{
if (size < sizeof(uint32))
return 0;
stream[BYTE1] = data&0xff;
stream[BYTE2] = (data>>8)&0xff;
stream[BYTE3] = (data>>16)&0xff;
stream[BYTE4] = (data>>24)&0xff;
return sizeof(uint32);
}
// 370 ns
inline unsigned Write(unsigned char * stream, unsigned size, int64 data)
{
if (size < sizeof(int64))
return 0;
#if (defined(WIN32) || defined(linux))
uint32 low = *(uint32 *)(&data);
uint32 high = *((uint32 *)&data+1);
#elif defined(sparc)
uint32 low = *((uint32 *)&data+1);
uint32 high = *(uint32 *)(&data);
#endif
stream[BYTE1] = (unsigned char)low&0xff;
stream[BYTE2] = (unsigned char)(low>>8)&0xff;
stream[BYTE3] = (unsigned char)(low>>16)&0xff;
stream[BYTE4] = (unsigned char)(low>>24)&0xff;
stream[BYTE5] = (unsigned char)high&0xff;
stream[BYTE6] = (unsigned char)(high>>8)&0xff;
stream[BYTE7] = (unsigned char)(high>>16)&0xff;
stream[BYTE8] = (unsigned char)(high>>24)&0xff;
return sizeof(int64);
}
// 370 ns
inline unsigned Write(unsigned char * stream, unsigned size, uint64 data)
{
if (size < sizeof(uint64))
return 0;
#if (defined(WIN32) || defined(linux))
uint32 low = *(uint32 *)(&data);
uint32 high = *((uint32 *)&data+1);
#elif defined(sparc)
uint32 low = *((uint32 *)&data+1);
uint32 high = *(uint32 *)(&data);
#endif
stream[BYTE1] = (unsigned char)low&0xff;
stream[BYTE2] = (unsigned char)(low>>8)&0xff;
stream[BYTE3] = (unsigned char)(low>>16)&0xff;
stream[BYTE4] = (unsigned char)(low>>24)&0xff;
stream[BYTE5] = (unsigned char)high&0xff;
stream[BYTE6] = (unsigned char)(high>>8)&0xff;
stream[BYTE7] = (unsigned char)(high>>16)&0xff;
stream[BYTE8] = (unsigned char)(high>>24)&0xff;
return sizeof(uint64);
}
// 360 ns
inline unsigned Write(unsigned char * stream, unsigned size, float data)
{
uint32 & dataRef = *(uint32 *)(&data);
if (size < sizeof(float))
return 0;
stream[BYTE1] = dataRef&0xff;
stream[BYTE2] = (dataRef>>8)&0xff;
stream[BYTE3] = (dataRef>>16)&0xff;
stream[BYTE4] = (dataRef>>24)&0xff;
return sizeof(float);
}
// 370 ns
inline unsigned Write(unsigned char * stream, unsigned size, double data)
{
if (size < sizeof(double))
return 0;
#if (defined(WIN32) || defined(linux))
uint32 low = *(uint32 *)(&data);
uint32 high = *((uint32 *)&data+1);
#elif defined(sparc)
uint32 low = *((uint32 *)&data+1);
uint32 high = *(uint32 *)(&data);
#endif
stream[BYTE1] = (unsigned char)low&0xff;
stream[BYTE2] = (unsigned char)(low>>8)&0xff;
stream[BYTE3] = (unsigned char)(low>>16)&0xff;
stream[BYTE4] = (unsigned char)(low>>24)&0xff;
stream[BYTE5] = (unsigned char)high&0xff;
stream[BYTE6] = (unsigned char)(high>>8)&0xff;
stream[BYTE7] = (unsigned char)(high>>16)&0xff;
stream[BYTE8] = (unsigned char)(high>>24)&0xff;
return sizeof(double);
}
// 361 ns
inline unsigned WriteEncoded(unsigned char * stream, unsigned size, uint32 data)
{
unsigned encoded = ((data & 0xffffffc0) << 2) | (data & 0x3f);
if (data > 0x3fffffff)
{
return 0;
}
else if (data > 0x3fffff && size >= 4)
{
encoded |= 0xc0;
stream[BYTE1] = encoded & 0xff;
stream[BYTE2] = (encoded>>8) & 0xff;
stream[BYTE3] = (encoded>>16) & 0xff;
stream[BYTE4] = (encoded>>24) & 0xff;
return 4;
}
else if (data > 0x3fff)
{
encoded |= 0x80;
stream[BYTE1] = encoded & 0xff;
stream[BYTE2] = (encoded>>8) & 0xff;
stream[BYTE3] = (encoded>>16) & 0xff;
return 3;
}
else if (data > 0x3f)
{
encoded |= 0x40;
stream[BYTE1] = encoded & 0xff;
stream[BYTE2] = (encoded>>8) & 0xff;
return 2;
}
else if (size >= 1)
{
stream[BYTE1] = encoded & 0xff;
return 1;
}
return 0;
}
// 630 ns
inline unsigned Write(unsigned char * stream, unsigned size, const std::string & data, bool isPascal=true)
{
if (isPascal)
{
unsigned fieldLen = 0;
unsigned bytes = 0;
fieldLen = Write(stream, size, static_cast<unsigned>(data.length()));
if (!fieldLen)
return 0;
bytes += fieldLen;
if (data.length())
{
fieldLen = Write(stream+bytes, size-bytes, reinterpret_cast<const unsigned char *>(data.data()), data.length());
if (!fieldLen)
return 0;
bytes += fieldLen;
}
return bytes;
}
else
{
unsigned bytes = Write(stream, size, reinterpret_cast<const unsigned char *>(data.c_str()), data.size()+1);
if (!bytes)
return 0;
return bytes;
}
}
template<class T>
inline unsigned Write(unsigned char * stream, unsigned size, const std::vector<T> & data)
{
unsigned bytes = 0;
unsigned elementBytes = 0;
bytes += Write(stream, size, static_cast<unsigned>(data.size()));
if (!bytes)
return 0;
for (typename std::vector<T>::const_iterator iter = data.begin(); iter != data.end(); iter++)
{
elementBytes = Write(stream+bytes, size-bytes, *iter);
if (!elementBytes)
return 0;
bytes += elementBytes;
}
return bytes;
}
inline unsigned Read(const unsigned char * stream, unsigned size, unsigned char * data, unsigned dataLen)
{
if (size < dataLen)
return 0;
memcpy(data, stream, dataLen);
return dataLen;
}
// 355 ns
inline unsigned Read(const unsigned char * stream, unsigned size, bool & data, unsigned = 1/*unused*/)
{
if (size < sizeof(uint8))
return 0;
data = stream[BYTE1] != 0;
return sizeof(uint8);
}
// 355 ns
inline unsigned Read(const unsigned char * stream, unsigned size, int8 & data, unsigned = 1/*unused*/)
{
if (size < sizeof(int8))
return 0;
data = stream[BYTE1];
return sizeof(int8);
}
// 355 ns
inline unsigned Read(const unsigned char * stream, unsigned size, uint8 & data, unsigned = 1/*unused*/)
{
if (size < sizeof(uint8))
return 0;
data = stream[BYTE1];
return sizeof(uint8);
}
// 355 ns
inline unsigned Read(const unsigned char * stream, unsigned size, int16 & data, unsigned = 1/*unused*/)
{
if (size < sizeof(int16))
return 0;
data = stream[BYTE1];
data |= stream[BYTE2]<<8;
return sizeof(int16);
}
// 355 ns
inline unsigned Read(const unsigned char * stream, unsigned size, uint16 & data, unsigned = 1/*unused*/)
{
if (size < sizeof(uint16))
return 0;
data = stream[BYTE1];
data |= stream[BYTE2]<<8;
return sizeof(uint16);
}
// 360 ns
inline unsigned Read(const unsigned char * stream, unsigned size, int32 & data, unsigned = 1/*unused*/)
{
if (size < sizeof(int32))
return 0;
data = stream[BYTE1];
data |= stream[BYTE2]<<8;
data |= stream[BYTE3]<<16;
data |= stream[BYTE4]<<24;
return sizeof(int32);
}
// 360 ns
inline unsigned Read(const unsigned char * stream, unsigned size, uint32 & data, unsigned = 1/*unused*/)
{
if (size < sizeof(uint32))
return 0;
data = stream[BYTE1];
data |= stream[BYTE2]<<8;
data |= stream[BYTE3]<<16;
data |= stream[BYTE4]<<24;
return sizeof(uint32);
}
// 380 ns
inline unsigned Read(const unsigned char * stream, unsigned size, int64 & data, unsigned = 1/*unused*/)
{
if (size < sizeof(int64))
return 0;
#if (defined(WIN32) || defined(linux))
uint32 & low = *(uint32 *)(&data);
uint32 & high = *((uint32 *)&data+1);
#elif defined(sparc)
uint32 & low = *(uint32 *)(&data+1);
uint32 & high = *(uint32 *)(&data);
#endif
low = stream[BYTE1];
low |= stream[BYTE2]<<8;
low |= stream[BYTE3]<<16;
low |= stream[BYTE4]<<24;
high = stream[BYTE5];
high |= stream[BYTE6]<<8;
high |= stream[BYTE7]<<16;
high |= stream[BYTE8]<<24;
return sizeof(int64);
}
// 380 ns
inline unsigned Read(const unsigned char * stream, unsigned size, uint64 & data, unsigned = 1/*unused*/)
{
if (size < sizeof(uint64))
return 0;
#if (defined(WIN32) || defined(linux))
uint32 & low = *(uint32 *)(&data);
uint32 & high = *((uint32 *)&data+1);
#elif defined(sparc)
uint32 & low = *(uint32 *)(&data+1);
uint32 & high = *(uint32 *)(&data);
#endif
low = stream[BYTE1];
low |= stream[BYTE2]<<8;
low |= stream[BYTE3]<<16;
low |= stream[BYTE4]<<24;
high = stream[BYTE5];
high |= stream[BYTE6]<<8;
high |= stream[BYTE7]<<16;
high |= stream[BYTE8]<<24;
return sizeof(uint64);
}
// 370 ns
inline unsigned Read(const unsigned char * stream, unsigned size, float & data, unsigned = 1/*unused*/)
{
assert(sizeof(float) == 4);
uint32 & dataRef = *(uint32 *)(&data);
if (size < sizeof(float))
return 0;
dataRef = stream[BYTE1];
dataRef |= stream[BYTE2]<<8;
dataRef |= stream[BYTE3]<<16;
dataRef |= stream[BYTE4]<<24;
return sizeof(float);
}
// 380 ns
inline unsigned Read(const unsigned char * stream, unsigned size, double & data, unsigned = 1/*unused*/)
{
assert(sizeof(double) == 8);
if (size < sizeof(double))
return 0;
#if (defined(WIN32) || defined(linux))
uint32 & low = *(uint32 *)(&data);
uint32 & high = *((uint32 *)&data+1);
#elif defined(sparc)
uint32 & low = *(uint32 *)(&data+1);
uint32 & high = *(uint32 *)(&data);
#endif
low = stream[BYTE1];
low |= stream[BYTE2]<<8;
low |= stream[BYTE3]<<16;
low |= stream[BYTE4]<<24;
high = stream[BYTE5];
high |= stream[BYTE6]<<8;
high |= stream[BYTE7]<<16;
high |= stream[BYTE8]<<24;
return sizeof(double);
}
// 360 ns
inline unsigned ReadEncoded(const unsigned char * stream, unsigned size, uint32 & data)
{
if (size < 1)
return 0;
unsigned encoded = stream[BYTE1];
unsigned mask = encoded & 0xc0;
if (mask == 0)
{
data = encoded & 0x3f;
return 1;
}
else if (mask == 0x40 && size >=2)
{
data = (stream[BYTE2]<<6) | (encoded & 0x3f);
return 2;
}
else if (mask == 0x80 && size >=3)
{
data = (stream[BYTE3]<<14) | (stream[BYTE2]<<6) | (encoded & 0x3f);
return 3;
}
else if (mask == 0xc0 && size >=4)
{
data = (stream[BYTE4]<<22) | (stream[BYTE3]<<14) | (stream[BYTE2]<<6) | (encoded & 0x3f);
return 4;
}
return 0;
}
inline unsigned Read(const unsigned char * stream, unsigned size, std::string & data, unsigned maxLen, bool isPascal=true)
{
if (isPascal)
{
unsigned bytes = 0;
unsigned length = 0;
bytes += Read(stream, size, length);
if (!bytes || size < bytes+length || length > maxLen)
return 0;
data.assign((const char *)stream+bytes, (const char *)stream+bytes+length); // assign would be dangerous if unicode, single-byte characters are ok
return bytes + length;
}
else
{
//find null terminator, if don't find it before maxLen, then err
const unsigned char *strEnd = NULL;
unsigned strLen = 0;
for (;strLen<maxLen && strLen < size;strLen++)
{
if (stream[strLen] == 0)
{
//found it
strEnd = (stream+strLen);
break;
}
}
if (strEnd == NULL)
return 0;
data.assign((const char *)stream, (const char *)strEnd);
return strLen+1;
}
}
template<class T>
inline unsigned Read(const unsigned char * stream, unsigned size, std::vector<T> & data, unsigned maxVecLen, unsigned maxFieldLen = 1)
{
T element;
unsigned bytes = 0;
unsigned elementBytes = 0;
unsigned length = 0;
data.clear();
bytes += Read(stream, size, length);
if (!bytes || length > maxVecLen)
return 0;
for (unsigned i=0; i<length; i++)
{
elementBytes = Read(stream+bytes, size-bytes, element, maxFieldLen);
if (!elementBytes)
return 0;
data.push_back(element);
bytes += elementBytes;
}
return bytes;
}
////////////////////////////////////////////////////////////////////////////////
class AutoVariableBase
{
public:
AutoVariableBase() {}
virtual ~AutoVariableBase() {}
virtual unsigned Write(unsigned char * stream, unsigned size) const = 0;
virtual unsigned Read(const unsigned char * stream, unsigned size, unsigned maxLen=1) = 0;
};
template<class ValueType>
class AutoVariable : public AutoVariableBase
{
public:
AutoVariable() : AutoVariableBase(), mValue() {}
explicit AutoVariable(const ValueType & source) : AutoVariableBase(), mValue(source) {}
AutoVariable(const AutoVariable & copy) : AutoVariableBase(), mValue(copy.mValue) {}
virtual ~AutoVariable() {}
const ValueType & Get() const { return mValue; }
void Set(const ValueType & rhs) { mValue = rhs; }
virtual unsigned Write(unsigned char * stream, unsigned size) const { return soe::Write(stream, size, mValue); }
virtual unsigned Read(const unsigned char * stream, unsigned size, unsigned maxLen) { return soe::Read(stream, size, mValue, maxLen); }
private:
ValueType mValue;
};
////////////////////////////////////////////////////////////////////////////////
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,36 @@
#ifndef BASE_SOLARIS_ARCHIVE_H
#define BASE_SOLARIS_ARCHIVE_H
namespace Base
{
#ifdef PACK_BIG_ENDIAN
inline double byteSwap(double value) { return value; }
inline float byteSwap(float value) { return value; }
inline uint64 byteSwap(uint64 value) { return value; }
inline int64 byteSwap(int64 value) { return value; }
inline uint32 byteSwap(uint32 value) { return value; }
inline int32 byteSwap(int32 value) { return value; }
inline uint16 byteSwap(uint16 value) { return value; }
inline int16 byteSwap(int16 value) { return value; }
#else
inline double byteSwap(double value) { byteReverse64(&value); return value; }
inline float byteSwap(float value) { byteReverse32(&value); return value; }
inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; }
inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; }
inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; }
inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; }
inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; }
inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; }
#endif
}
#endif
@@ -0,0 +1,102 @@
#include "../BlockAllocator.h"
namespace Base
{
BlockAllocator::BlockAllocator()
{
for(unsigned i = 0; i < 31; i++)
{
m_blocks[i] = NULL;
}
}
BlockAllocator::~BlockAllocator()
{
// free all allocated memory blocks
for(unsigned i = 0; i < 31; i++)
{
while(m_blocks[i] != NULL)
{
unsigned *tmp = m_blocks[i];
m_blocks[i] = (unsigned *)*m_blocks[i];
free(tmp);
}
}
}
// Allocate a block that is the next power of two greater than the # of bytes passed.
// 33 bytes yields a 64 byte block of memory and so forth.
void *BlockAllocator::getBlock(unsigned bytes)
{
unsigned accum = 16, bits = 16;
unsigned *handle = NULL;
// Perform a binary search looking for the highest bit.
while(bits != 0)
{
// If bytes is less than the bit we're testing for, subtract half
// from the bit value and repeat
if(bytes < (unsigned)(1 << accum))
{
bits /= 2;
accum -= bits;
}
// If bytes is greater than the bit we're testing for, add half
// from the but value and repeat
else if(bytes > (unsigned)(1 << accum))
{
bits /= 2;
accum += bits;
}
// Got lucky and hit the value dead on
else
{
break;
}
}
// At this point accum contains the most significant bit index, increment
accum++;
if(accum < 2)
{
accum = 2;
}
// Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front
// The first integer is the address of the next block of memory when the block is in the allocator
// The second integer is the bit length of the block
// Memory is allocated on 4 byte boundaries to sidestep byte alignment problems
// Check if the allocator already has a block of that size
if(m_blocks[accum] == 0)
{
// remove the pre allocated block from the linked list
handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned));
handle[1] = accum;
handle[0] = 0;
}
else
{
// Allocate a new block
handle = m_blocks[accum];
m_blocks[accum] = (unsigned *)handle[0];
handle[0] = 0;
}
// return a pointer that skips over the header used for the allocator's purposes
return(handle + 2);
}
void BlockAllocator::returnBlock(unsigned *handle)
{
// C++ allows for safe deletion of a NULL pointer
if(handle)
{
// Update the allocator linked list, insert this entry at the head
*(handle - 2) = (unsigned)m_blocks[*(handle - 1)];
// Add this entry to the proper linked list node
m_blocks[*(handle - 1)] = (handle - 2);
}
}
};
@@ -0,0 +1,93 @@
////////////////////////////////////////
// Event.cpp
//
// Purpose:
// 1. Implementation of the CEvent class.
//
// Revisions:
// 07/10/2001 Created
//
#if defined(_REENTRANT)
#include "Event.h"
namespace Base
{
CEvent::CEvent()
{
mWaiting = 0;
mSignaled = false;
mInitialized = false;
if (pthread_cond_init( &mCond, NULL ) != 0)
{
return;
}
if (pthread_mutex_init( &mMutex, NULL ) != 0)
{
pthread_cond_destroy( &mCond );
return;
}
mInitialized = true;
}
CEvent::~CEvent()
{
if (mInitialized)
{
pthread_cond_destroy(&mCond);
pthread_mutex_destroy(&mMutex);
}
}
int32 CEvent::Wait(uint32 timeout)
{
if (!mInitialized)
return CEvent::eWAIT_ERROR;
int result;
pthread_mutex_lock(&mMutex);
if (mSignaled)
{
mSignaled = false;
}
else if (!timeout)
{
mWaiting++;
result = pthread_cond_wait(&mCond, &mMutex);
mWaiting--;
}
else
{
struct timespec wake_time;
clock_gettime( CLOCK_REALTIME, &wake_time );
wake_time.tv_sec += timeout/1000;
wake_time.tv_nsec += (timeout%1000)*1000000;
// normalize new time
wake_time.tv_sec += wake_time.tv_nsec / 1000000000;
wake_time.tv_nsec %= 1000000000;
mWaiting++;
result = pthread_cond_timedwait( &mCond, &mMutex, &wake_time );
mWaiting--;
}
pthread_mutex_unlock(&mMutex);
if (result == 0)
return CEvent::eWAIT_SIGNAL;
else if (result == ETIMEDOUT)
return CEvent::eWAIT_TIMEOUT;
else
return CEvent::eWAIT_ERROR;
}
}
#endif // #if defined(_REENTRANT)
@@ -0,0 +1,83 @@
////////////////////////////////////////
// Event.h
//
// Purpose:
// 1. Declair the CEvent class that encapsulates the functionality of a
// single-locking semaphore.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_SOLARIS_EVENT_H
#define BASE_SOLARIS_EVENT_H
#if !defined(_REENTRANT)
# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_REENTRANT)" )
#else
#include "Platform.h"
namespace Base
{
////////////////////////////////////////
// Class:
// CEvent
//
// Purpose:
// Encapsulates the functionality of a singal-locking semaphore.
// This class is valuable for thread syncronization when a thead's
// execution needs to be dependent upon another thread.
//
// Public Methods:
// Signal() : Signals a thread that has called Wait() so that it can
// continue execution. This function returns true if the waiting
// thread was signalled successfully, otherwise false is returned.
// Wait() : Halts the calling thread's execution indefinately until
// a Singal() call is made by an external thread. If the thread is
// successfully signalled, the function returns eWAIT_SIGNAL. If
// timeout period expires without a signal, eWAIT_TIMEOUT is returned.
// If the function fails, eWAIT_ERROR is returned.
//
class CEvent
{
public:
CEvent();
virtual ~CEvent();
bool Signal();
int32 Wait(uint32 timeout = 0);
public:
enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT };
private:
pthread_mutex_t mMutex;
pthread_cond_t mCond;
bool mInitialized;
bool mSignaled;
int32 mWaiting;
};
inline bool CEvent::Signal()
{
if (!mInitialized)
return false;
pthread_mutex_lock(&mMutex);
if(mWaiting > 0)
{
pthread_cond_signal(&mCond);
}
else
{
mWaiting = true;
}
pthread_mutex_unlock(&mMutex);
return true;
}
}
#endif // #if defined(_MT)
#endif // BASE_SOLARIS_EVENT_H
@@ -0,0 +1,387 @@
#include "../Logger.h"
#include "Mutex.h"
#include <sys/stat.h>
using namespace std;
namespace Base
{
const char file_sep = '/';
Logger::Logger(const char *prefix, int level, unsigned size, bool rollDate)
: m_defaultLevel(level), m_defaultSize(size), m_dirPrefix(prefix), m_rollDate(rollDate)
{
char buf[1024];
FILE *logDir = NULL;
logDir = fopen(m_dirPrefix.c_str(), "r+");
if(errno == ENOENT)
{
cmkdir(m_dirPrefix.c_str(), 0755);
}
else if(logDir != NULL)
{
fclose(logDir);
}
tm now;
time_t t = time(NULL);
#ifdef REENTRANT
localtime_r(&t, &now);
#else
now = *(localtime(&t));
#endif
memcpy(&m_lastDateTime, &now, sizeof(tm));
if(m_rollDate)
{
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
}
else
{
sprintf(buf, "%s", m_dirPrefix.c_str());
}
logDir = fopen(buf, "r+");
if(errno == ENOENT)
{
cmkdir(buf, 0755);
}
else if(logDir != NULL)
{
fclose(logDir);
}
m_logPrefix = buf;
}
Logger::~Logger()
{
map<unsigned, LogInfo *>::iterator iter;
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
{
log((*iter).first, LOG_FILEONLY, "---=== Log Stopped ===---");
fflush((*iter).second->file);
fclose((*iter).second->file);
delete((*iter).second);
}
m_logTable.clear();
}
void Logger::flush(unsigned logenum)
{
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter != m_logTable.end())
{
LogInfo *info = (*iter).second;
fflush(info->file);
info->used = 0;
}
}
void Logger::flushAll()
{
map<unsigned, LogInfo *>::iterator iter;
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
{
LogInfo *info = (*iter).second;
fflush(info->file);
info->used = 0;
}
}
void Logger::addLog(const char *id, unsigned logenum, int level, unsigned size)
{
LogInfo *newLog = new LogInfo;
newLog->filename = m_logPrefix + file_sep + id + ".log";
newLog->name = id;
newLog->used = 0;
newLog->max = size;
newLog->last = 0;
newLog->level = level;
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
if(strcmp("stdout", id) == 0)
{
newLog->file = stdout;
}
else if(strcmp("stderr", id) == 0)
{
newLog->file = stderr;
}
else
{
newLog->file = fopen(newLog->filename.c_str(), "a+");
}
log(logenum, LOG_FILEONLY, "---=== Log Started ===---");
}
void Logger::addLog(const char *id, unsigned logenum)
{
LogInfo *newLog = new LogInfo;
newLog->filename = m_logPrefix + file_sep + id + ".log";
newLog->name = id;
newLog->used = 0;
newLog->max = m_defaultSize;
newLog->last = 0;
newLog->level = m_defaultLevel;
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
if(strcmp("stdout", id) == 0)
{
newLog->file = stdout;
}
else if(strcmp("stderr", id) == 0)
{
newLog->file = stderr;
}
else
{
newLog->file = fopen(newLog->filename.c_str(), "a+");
}
log(logenum, LOG_FILEONLY, "---===Log Started ===---");
}
void Logger::updateLog(unsigned logenum, int level, unsigned size)
{
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter != m_logTable.end())
{
(*iter).second->level = level;
(*iter).second->max = size;
}
}
void Logger::removeLog(unsigned logenum)
{
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter != m_logTable.end())
{
log((*iter).first, LOG_ALWAYS, "---=== Log Stopped ===---");
fflush((*iter).second->file);
fclose((*iter).second->file);
delete((*iter).second);
}
}
void Logger::logSimple(unsigned logenum, int level, const char *message)
{
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter == m_logTable.end())
{
return;
}
time_t t = time(NULL);
LogInfo *info = (*iter).second;
if(level >= info->level)
{
return;
}
if(info->last != t)
{
memcpy(&info->ts, localtime(&t), sizeof(tm));
info->last = t;
}
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
{
#if defined(_REENTRANT)
rLock.Lock();
#endif
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
{
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
rollDate(t);
}
#if defined(_REENTRANT)
rLock.Unlock();
#endif
}
if(iter != m_logTable.end())
{
if(info->max > 0)
{
int tmp = fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
info->used += tmp;
if(info->used > info->max)
{
fflush(info->file);
info->used = 0;
}
}
else
{
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
fflush(info->file);
}
}
}
void Logger::log(unsigned logenum, int level, const char *message, ...)
{
char buf[2048];
va_list varg;
va_start(varg, message);
vsnprintf(buf, 2047, message, varg);
buf[2047] = 0;
va_end(varg);
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
if(iter == m_logTable.end())
{
return;
}
time_t t = time(NULL);
LogInfo *info = (*iter).second;
if(level >= info->level)
{
return;
}
if(info->last != t)
{
#ifdef REENTRANT
localtime_r(&t, &info->ts);
#else
info->ts = *(localtime(&t));
#endif
info->last = t;
}
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
{
#if defined(_REENTRANT)
rLock.Lock();
#endif
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
{
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
rollDate(t);
}
#if defined(_REENTRANT)
rLock.Unlock();
#endif
}
if(iter != m_logTable.end())
{
if(info->max > 0)
{
int tmp = fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, buf);
info->used += tmp;
if(info->used > info->max)
{
fflush(info->file);
info->used = 0;
}
}
else
{
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, buf);
fflush(info->file);
}
}
}
void Logger::rollDate(time_t t)
{
char buf[80];
FILE *logDir = NULL;
logDir = fopen(m_dirPrefix.c_str(), "r+");
if(errno == ENOENT)
{
cmkdir(m_dirPrefix.c_str(), 0755);
}
else if(logDir != NULL)
{
fclose(logDir);
}
tm now;
#ifdef REENTRANT
localtime_r(&t, &now);
#else
now = *(localtime(&t));
#endif
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
logDir = fopen(buf, "r+");
if(errno == ENOENT)
{
cmkdir(buf, 0755);
}
else if(logDir != NULL)
{
fclose(logDir);
}
m_logPrefix = buf;
map<unsigned, LogInfo *>::iterator iter;
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
{
(*iter).second->filename = m_logPrefix + file_sep + (*iter).second->name.c_str() + ".log";
fflush((*iter).second->file);
fclose((*iter).second->file);
(*iter).second->file = fopen((*iter).second->filename.c_str(), "a+");
memcpy(&((*iter).second->ts), &now, sizeof(tm));
}
}
// mkdir function that creates intermediate directories
void Logger::cmkdir(const char *dir, int mode)
{
char dirbuf[128];
strncpy(dirbuf, dir, 127);
dirbuf[127] = 0;
char *j = dirbuf, *i = dirbuf;
int handle;
while(*i)
{
if(*i == file_sep)
{
(*i) = 0;
// handle = open(j, O_EXCL); // Ben's original code
// if((handle > 0) || (errno != EISDIR && errno != ENOENT))
// {
// perror("Logger::cmkdir():");
// abort();
// }
// This doesnt work under Linux, it returns a valid handle
// Instead: see if file exists. If it doesnt, create directory ok
// If it exists, do stat to see if it is a dir.
// If it is a dir, then ok, create the directory.
// If it is a file, error
// ging 9-16-2002
handle = open(j, O_RDONLY);
if (handle > 0)
{
struct stat stat_buffer;
int ret = fstat(handle,&stat_buffer);
if ((ret == -1) || ((stat_buffer.st_mode | S_IFDIR) == 0))
{
perror("Logger::cmkdir():");
abort();
}
}
mkdir(j, mode);
close(handle);
(*i) = file_sep;
}
else if(*(i + 1) == 0)
{
mkdir(j, mode);
}
i++;
}
}
};
@@ -0,0 +1,32 @@
////////////////////////////////////////
// Mutex.cpp
//
// Purpose:
// 1. Implementation of the CMutex class.
//
// Revisions:
// 07/10/2001 Created
//
#if defined(_REENTRANT)
#include "Mutex.h"
namespace Base
{
CMutex::CMutex()
{
mInitialized = (pthread_mutex_init(&mMutex, 0) == 0);
}
CMutex::~CMutex()
{
if (mInitialized)
pthread_mutex_destroy(&mMutex);
}
}
#endif // #if defined(_REENTRANT)
@@ -0,0 +1,71 @@
////////////////////////////////////////
// Mutex.h
//
// Purpose:
// 1. Declair the CMutex class that encapsulates the functionality of a
// mutually-exclusive device.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_SOLARIS_MUTEX_H
#define BASE_SOLARIS_MUTEX_H
#if !defined(_REENTRANT)
# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_REENTRANT)" )
#else
#include "Platform.h"
namespace Base
{
////////////////////////////////////////
// Class:
// CMutex
//
// Purpose:
// Encapsulates the functionality of a mutually-exclusive device.
// This class is valuable for protecting against race conditions
// within threaded applications. The CMutex class can be used to
// only allow a single thread to run within a specified code
// segment at a time.
//
// Public Methods:
// Lock() : Locks the mutex. If the mutex is already locked, the
// operating system will block the calling thread until another
// thread has unlocked the mutex.
// Unlock() : Unlocks the mutex.
//
class CMutex
{
public:
CMutex();
~CMutex();
void Lock();
void Unlock();
private:
pthread_mutex_t mMutex;
bool mInitialized;
};
inline void CMutex::Lock(void)
{
if (mInitialized)
pthread_mutex_lock(&mMutex);
}
inline void CMutex::Unlock(void)
{
if (mInitialized)
pthread_mutex_unlock(&mMutex);
}
}
#endif // #if defined(_MT)
#endif // BASE_SOLARIS_MUTEX_H
@@ -0,0 +1,46 @@
////////////////////////////////////////
// Platform.cpp
//
// Purpose:
// 1. Implementation of the global functionality declaired in Platform.h.
//
// Revisions:
// 07/10/2001 Created
//
#include <ctype.h>
#include "Platform.h"
namespace Base
{
// Implementation of microsoft strlwr extension
// This non-ANSI function is not supported under UNIX
void strlwr(char * s)
{
while (*s)
{
*s = tolower(*s);
s++;
}
}
// Implementation of microsoft strupr extension
// This non-ANSI function is not supported under UNIX
void strupr(char * s)
{
while (*s)
{
*s = toupper(*s);
s++;
}
}
CTimer::CTimer() :
mTimer(0)
{
}
}
@@ -0,0 +1,107 @@
////////////////////////////////////////
// Platform.h
//
// Purpose:
// 1. Include relevent system headers that are platform specific.
// 2. Declair global platform specific functionality.
// 3. Include primative type definitions
//
// Global Functions:
// getTimer() : Return the current high resolution clock count.
// getTimerFrequency() : Return the frequency of the high resolution clock.
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
// specified number of milliseconds.
// strlwr() : Alters the contents of a string, making it all lower-case.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_SOLARIS_PLATFORM_H
#define BASE_SOLARIS_PLATFORM_H
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "Types.h"
namespace Base
{
uint64 getTimer(void);
uint64 getTimerFrequency(void);
void Sleep(uint32 ms);
inline uint64 getTimer(void)
{
uint64 t;
struct timeval tv;
gettimeofday(&tv, 0);
t = tv.tv_sec;
t = t * 1000000;
t += tv.tv_usec;
return t;
}
inline uint64 getTimerFrequency(void)
{
uint64 f = 1000000;
return f;
}
inline void sleep(uint32 ms)
{
//usleep(static_cast<unsigned long>(ms * 1000));
struct timeval sleep_tv;
sleep_tv.tv_sec = ms / 1000;
sleep_tv.tv_usec = (ms % 1000) * 1000;
select(1, NULL, NULL, NULL, &sleep_tv);
}
void strlwr(char * s);
void strupr(char * s);
class CTimer
{
public:
CTimer();
void Set(uint32 seconds);
void Signal();
bool Expired();
private:
uint32 mTimer;
};
inline void CTimer::Set(uint32 interval)
{
mTimer = (uint32)time(0) + interval;
}
inline void CTimer::Signal()
{
mTimer = 0;
}
inline bool CTimer::Expired()
{
return (mTimer <= (uint32)time(0));
}
}
#endif BASE_SOLARIS_PLATFORM_H
@@ -0,0 +1,282 @@
////////////////////////////////////////
// Thread.cpp
//
// Purpose:
// 1. Implementation of the CThread class.
//
// Revisions:
// 07/10/2001 Created
//
#if defined(_REENTRANT)
#include <pthread.h>
#include <time.h>
#include "Thread.h"
using namespace std;
namespace Base
{
void *threadProc(void *threadPtr)
{
CThread &thread = *((CThread*)threadPtr);
thread.mThreadActive = true;
thread.ThreadProc();
thread.mThreadActive = false;
return 0;
}
CThread::CThread()
{
mThreadID = 0;
mThreadActive = false;
mThreadContinue = false;
}
CThread::~CThread()
{
StopThread();
}
void CThread::StartThread()
{
mThreadContinue = true;
pthread_create(&mThreadID,0,threadProc,this);
while (!IsThreadActive())
Base::sleep(1);
}
int32 CThread::StopThread(int timeout)
{
timeout += time(0);
mThreadContinue = false;
while (mThreadActive && time(0)<timeout)
sleep(1);
if (mThreadActive)
{
mThreadActive = false;
return eSTOP_TIMEOUT;
}
return eSTOP_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////
CThreadPool::CMember::CMember(CThreadPool * parent) :
mParent(parent),
mFunction(NULL),
mArgument(NULL),
mSemaphore()
{
StartThread();
}
CThreadPool::CMember::~CMember()
{
}
void CThreadPool::CMember::Destroy()
{
mThreadContinue = false;
mSemaphore.Signal();
}
bool CThreadPool::CMember::Execute(void( *function )( void * ), void * arg)
{
if (mFunction)
return false;
mArgument = arg;
mFunction = function;
mSemaphore.Signal();
return true;
}
void CThreadPool::CMember::ThreadProc()
{
while (mThreadContinue)
{
mParent->OnIdle(this);
mSemaphore.Wait(mParent->GetTimeOut()*1000);
mParent->OnBusy(this);
if (mFunction)
{
mFunction(mArgument);
mArgument = NULL;
mFunction = NULL;
}
else
mThreadContinue = false;
}
mParent->OnDestory(this);
}
////////////////////////////////////////////////////////////////////////////////
CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) :
mMutex(),
mIdleMember(),
mBusyMember(),
mNullMember(),
mThreadCount(0),
mMaxThreads(maxThreads),
mMinThreads(minThreads),
mTimeOut(timeout)
{
if (mMaxThreads == 0) mMaxThreads = 1;
if (mMinThreads == 0) mMinThreads = 1;
if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads;
if (mTimeOut < 60)
mTimeOut = 60;
for (uint32 i=0; i<mMinThreads; i++)
new CMember(this);
}
CThreadPool::~CThreadPool()
{
set<CMember *>::iterator setIterator;
mMutex.Lock();
setIterator = mBusyMember.begin();
while (setIterator != mBusyMember.end())
(*setIterator++)->Destroy();
mMutex.Unlock();
while (mThreadCount)
{
mMutex.Lock();
setIterator = mIdleMember.begin();
while (setIterator != mIdleMember.end())
(*setIterator++)->Destroy();
mMutex.Unlock();
sleep(1);
}
mMutex.Lock();
while (!mNullMember.empty())
{
delete mNullMember.front();
mNullMember.pop_front();
}
mMutex.Unlock();
}
bool CThreadPool::Execute(void( *function )( void * ), void * arg, uint32 poolGrowthSize )
{
mMutex.Lock();
if (mIdleMember.empty())
{
if (mThreadCount < mMaxThreads)
{
if (!poolGrowthSize)
poolGrowthSize = mMinThreads;
if ((mThreadCount + poolGrowthSize) > mMaxThreads)
poolGrowthSize = mMaxThreads - mThreadCount;
for (uint32 i(0); i < poolGrowthSize; i++)
new CMember(this);
mMutex.Unlock();
time_t idleTimeout = time(0) + 5;
while(mIdleMember.empty())
{
if (time(0) >= idleTimeout)
{
return false;
}
Base::sleep(10);
}
mMutex.Lock();
}
else
{
mMutex.Unlock();
return false;
}
}
while (!mNullMember.empty())
{
delete mNullMember.front();
mNullMember.pop_front();
}
CMember * member = *(mIdleMember.begin());
mIdleMember.erase(member);
member->Execute(function,arg);
mMutex.Unlock();
return true;
}
uint32 CThreadPool::GetTimeOut()
{
return mTimeOut;
}
void CThreadPool::OnIdle(CMember * member)
{
mMutex.Lock();
set<CMember *>::iterator setIterator = mBusyMember.find(member);
if (setIterator != mBusyMember.end())
mBusyMember.erase(member);
else
mThreadCount++;
mIdleMember.insert(member);
mMutex.Unlock();
}
void CThreadPool::OnBusy(CMember * member)
{
mMutex.Lock();
mBusyMember.insert(member);
mMutex.Unlock();
}
void CThreadPool::OnDestory(CMember * member)
{
set<CMember *>::iterator setIterator;
mMutex.Lock();
setIterator = mBusyMember.find(member);
if (setIterator != mBusyMember.end())
{
mNullMember.push_back(member);
mBusyMember.erase(member);
mThreadCount--;
}
mMutex.Unlock();
}
////////////////////////////////////////////////////////////////////////////////
}
#endif // #if defined(_REENTRANT)
@@ -0,0 +1,139 @@
////////////////////////////////////////
// Thread.h
//
// Purpose:
// 1. Declair the CThread class that encapsulates threading functionality.
// This abstract base class in intended to be used to encapsulate
// individual tasks that require threading in derived classes.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_SOLARIS_THREAD_H
#define BASE_SOLARIS_THREAD_H
#if !defined(_REENTRANT)
# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_REENTRANT)" )
#else
#pragma warning( disable : 4786)
#include <list>
#include <set>
#include "Platform.h"
#include "Mutex.h"
#include "Event.h"
namespace Base
{
////////////////////////////////////////
// Class:
// CThread
//
// Purpose:
// Encapsulates threading functionality. Creating classes derived
// from CThread provides an easy way to encapsulate tasks that require
// their own thread.
//
// Public Methods:
// StartThread() : Creates the low-level thread handle and begins executing
// the CThread::ThreadProc() function within the new thread.
// StopThread() : Signals the ThreadProc() function to stop executing using
// the mThreadContinue member variable, and waits for the ThreadProc()
// function to exit. By default, the function will block for a maximum
// of 5 seconds before exiting without the thread halting.
// IsThreadActive() : Returns true if the physical thread is still executing
// within the ThreadProc() function, otherwise it returns false.
// ThreadProc() : Pure-virtual function that will be executed when the StartThread()
// function is called. Derived classes must implement this function. The
// mThreadContinue member variable should be used internal the the ThreadProc()
// function to indicate whether it should continue executing or exit.
// Protected Attributes:
// mThreadContinue : Boolean value indicating to the ThreadProc() function
// whether to continue executing or to exit. If mThreadContinue is true,
// ThreadProc() should continue, otherwise ThreadProc() should exit. It
// left up to the derived class to implement a ThreadProc() function that
// uses the mThreadContinue member.
//
//
class CThread
{
friend void * threadProc(void *);
public:
enum { eSTOP_SUCCESS, eSTOP_TIMEOUT };
public:
CThread();
virtual ~CThread();
void StartThread();
int32 StopThread(int timeout=5);
bool IsThreadActive() { return mThreadActive; }
protected:
virtual void ThreadProc() = 0;
protected:
bool mThreadContinue;
private:
bool mThreadActive;
pthread_t mThreadID;
};
class CThreadPool
{
private:
class CMember : public CThread
{
public:
CMember(CThreadPool * parent);
virtual ~CMember();
bool Execute(void( *function )( void * ), void * arg);
void Destroy();
protected:
virtual void ThreadProc();
private:
CThreadPool * mParent;
void( * mFunction )( void * );
void * mArgument;
CEvent mSemaphore;
};
friend class CMember;
public:
CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60);
virtual ~CThreadPool();
virtual bool Execute(void( *function )( void * ), void * arg, uint32 poolGrowthSize = 0);
private:
uint32 GetTimeOut();
void OnIdle(CMember * member);
void OnBusy(CMember * member);
void OnDestory(CMember * member);
private:
CMutex mMutex;
std::set<CMember *> mIdleMember;
std::set<CMember *> mBusyMember;
std::list<CMember *> mNullMember;
uint32 mThreadCount;
uint32 mMaxThreads;
uint32 mMinThreads;
uint32 mTimeOut;
};
}
#endif // #if defined(_MT)
#endif // BASE_SOLARIS_THREAD_H
@@ -0,0 +1,28 @@
////////////////////////////////////////
// Types.h
//
// Purpose:
// 1. Define integer types that are unambiguous with respect to size
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_SOLARIS_TYPES_H
#define BASE_SOLARIS_TYPES_H
namespace Base
{
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef signed int int32;
typedef unsigned int uint32;
typedef signed long long int64;
typedef unsigned long long uint64;
}
#endif // BASE_SOLARIS_TYPES_H
@@ -0,0 +1,42 @@
#ifndef BASE_WIN32_ARCHIVE_H
#define BASE_WIN32_ARCHIVE_H
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#ifdef PACK_BIG_ENDIAN
inline double byteSwap(double value) { byteReverse64(&value); return value; }
inline float byteSwap(float value) { byteReverse32(&value); return value; }
inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; }
inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; }
inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; }
inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; }
inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; }
inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; }
#else
inline double byteSwap(double value) { return value; }
inline float byteSwap(float value) { return value; }
inline uint64 byteSwap(uint64 value) { return value; }
inline int64 byteSwap(int64 value) { return value; }
inline uint32 byteSwap(uint32 value) { return value; }
inline int32 byteSwap(int32 value) { return value; }
inline uint16 byteSwap(uint16 value) { return value; }
inline int16 byteSwap(int16 value) { return value; }
#endif
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,112 @@
#include "../BlockAllocator.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
BlockAllocator::BlockAllocator()
{
for(unsigned i = 0; i < 31; i++)
{
m_blocks[i] = NULL;
}
}
BlockAllocator::~BlockAllocator()
{
// free all allocated memory blocks
for(unsigned i = 0; i < 31; i++)
{
while(m_blocks[i] != NULL)
{
unsigned *tmp = m_blocks[i];
m_blocks[i] = (unsigned *)*m_blocks[i];
free(tmp);
}
}
}
// Allocate a block that is the next power of two greater than the # of bytes passed.
// 33 bytes yields a 64 byte block of memory and so forth.
void *BlockAllocator::getBlock(unsigned bytes)
{
unsigned accum = 16, bits = 16;
unsigned *handle = NULL;
// Perform a binary search looking for the highest bit.
while(bits != 0)
{
// If bytes is less than the bit we're testing for, subtract half
// from the bit value and repeat
if(bytes < (unsigned)(1 << accum))
{
bits /= 2;
accum -= bits;
}
// If bytes is greater than the bit we're testing for, add half
// from the but value and repeat
else if(bytes > (unsigned)(1 << accum))
{
bits /= 2;
accum += bits;
}
// Got lucky and hit the value dead on
else
{
break;
}
}
// At this point accum contains the most significant bit index, increment
accum++;
if(accum < 2)
{
accum = 2;
}
// Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front
// The first integer is the address of the next block of memory when the block is in the allocator
// The second integer is the bit length of the block
// Memory is allocated on 4 byte boundaries to sidestep byte alignment problems
// Check if the allocator already has a block of that size
if(m_blocks[accum] == 0)
{
// remove the pre allocated block from the linked list
handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned));
handle[1] = accum;
handle[0] = 0;
}
else
{
// Allocate a new block
handle = m_blocks[accum];
m_blocks[accum] = (unsigned *)handle[0];
handle[0] = 0;
}
// return a pointer that skips over the header used for the allocator's purposes
return(handle + 2);
}
void BlockAllocator::returnBlock(unsigned *handle)
{
// C++ allows for safe deletion of a NULL pointer
if(handle)
{
// Update the allocator linked list, insert this entry at the head
*(handle - 2) = (unsigned)m_blocks[*(handle - 1)];
// Add this entry to the proper linked list node
m_blocks[*(handle - 1)] = (handle - 2);
}
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,44 @@
////////////////////////////////////////
// Event.cpp
//
// Purpose:
// 1. Implementation of the CEvent class.
//
// Revisions:
// 07/10/2001 Created
//
#if !defined(_MT)
# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_MT)" )
#else
#include "Event.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
CEvent::CEvent()
{
mEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
}
CEvent::~CEvent()
{
if (mEvent)
CloseHandle(mEvent);
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_MT)
@@ -0,0 +1,92 @@
////////////////////////////////////////
// Event.h
//
// Purpose:
// 1. Declair the CEvent class that encapsulates the functionality of a
// single-locking semaphore.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_WIN32_EVENT_H
#define BASE_WIN32_EVENT_H
#if defined(_MT)
#include "Platform.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
////////////////////////////////////////
// Class:
// CEvent
//
// Purpose:
// Encapsulates the functionality of a singal-locking semaphore.
// This class is valuable for thread syncronization when a thead's
// execution needs to be dependent upon another thread.
//
// Public Methods:
// Signal() : Signals a thread that has called Wait() so that it can
// continue execution. This function returns true if the waiting
// thread was signalled successfully, otherwise false is returned.
// Wait() : Halts the calling thread's execution indefinately until
// a Singal() call is made by an external thread. If the thread is
// successfully signalled, the function returns eWAIT_SIGNAL. If
// timeout period expires without a signal, eWAIT_TIMEOUT is returned.
// If the function fails, eWAIT_ERROR is returned.
//
class CEvent
{
public:
CEvent();
virtual ~CEvent();
bool Signal();
int32 Wait(uint32 timeout = 0);
public:
enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT };
private:
HANDLE mEvent;
};
inline bool CEvent::Signal()
{
if (mEvent)
return SetEvent(mEvent)!=0;
return false;
}
inline int32 CEvent::Wait(uint32 timeout)
{
if (!mEvent)
return CEvent::eWAIT_ERROR;
DWORD result = WaitForSingleObjectEx(mEvent, timeout ? timeout : INFINITE, FALSE);
if (result == WAIT_OBJECT_0)
return CEvent::eWAIT_SIGNAL;
else if (result == WAIT_TIMEOUT)
return CEvent::eWAIT_TIMEOUT;
else
return CEvent::eWAIT_ERROR;
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_MT)
#endif // BASE_WIN32_EVENT_H
@@ -0,0 +1,22 @@
// File.cpp: implementation of the CFile class.
//
//////////////////////////////////////////////////////////////////////
#include "File.h"
namespace Base
{
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CFile::CFile(const char *)
{
}
CFile::~CFile()
{
}
}
@@ -0,0 +1,26 @@
// File.h: interface for the CFile class.
//
//////////////////////////////////////////////////////////////////////
#ifndef BASE_FILE_H
#define BASE_FILE_H
#include <stdio.h>
namespace Base
{
class CFile
{
public:
CFile(const char *);
virtual ~CFile();
bool IsOpen();
private:
FILE* mFileHandle;
};
}
#endif // BASE_FILE_H
@@ -0,0 +1,40 @@
////////////////////////////////////////
// Mutex.cpp
//
// Purpose:
// 1. Implementation of the CMutex class.
//
// Revisions:
// 07/10/2001 Created
//
#if !defined(_MT)
# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_MT)" )
#else
#include "Mutex.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
CMutex::CMutex()
{
InitializeCriticalSection(&mCriticalSection);
}
CMutex::~CMutex()
{
DeleteCriticalSection(&mCriticalSection);
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_MT)
@@ -0,0 +1,73 @@
////////////////////////////////////////
// Mutex.h
//
// Purpose:
// 1. Declair the CMutex class that encapsulates the functionality of a
// mutually-exclusive device.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_WIN32_MUTEX_H
#define BASE_WIN32_MUTEX_H
#if defined (_MT)
#include "Platform.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
////////////////////////////////////////
// Class:
// CMutex
//
// Purpose:
// Encapsulates the functionality of a mutually-exclusive device.
// This class is valuable for protecting against race conditions
// within threaded applications. The CMutex class can be used to
// only allow a single thread to run within a specified code
// segment at a time.
//
// Public Methods:
// Lock() : Locks the mutex. If the mutex is already locked, the
// operating system will block the calling thread until another
// thread has unlocked the mutex.
// Unlock() : Unlocks the mutex.
//
class CMutex
{
public:
CMutex();
~CMutex();
void Lock();
void Unlock();
private:
CRITICAL_SECTION mCriticalSection;
};
inline void CMutex::Lock()
{
EnterCriticalSection(&mCriticalSection);
}
inline void CMutex::Unlock()
{
LeaveCriticalSection(&mCriticalSection);
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_MT)
#endif // BASE_WIN32_MUTEX_H
@@ -0,0 +1,31 @@
////////////////////////////////////////
// Platform.cpp
//
// Purpose:
// 1. Implementation of the global functionality declaired in Platform.h.
//
// Revisions:
// 07/10/2001 Created
//
#include "Platform.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
CTimer::CTimer() :
mTimer(0)
{
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,98 @@
////////////////////////////////////////
// Platform.h
//
// Purpose:
// 1. Include relevent system headers that are platform specific.
// 2. Declair global platform specific functionality.
// 3. Include primative type definitions
//
// Global Functions:
// getTimer() : Return the current high resolution clock count.
// getTimerFrequency() : Return the frequency of the high resolution clock.
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
// specified number of milliseconds.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_WIN32_PLATFORM_H
#define BASE_WIN32_PLATFORM_H
#include <memory.h>
#include <winsock2.h>
#include <time.h>
#include <io.h>
#include <fcntl.h>
#include <direct.h>
#include <stdio.h>
#include <errno.h>
#include "Types.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
uint64 getTimer(void);
uint64 getTimerFrequency(void);
inline uint64 getTimer(void)
{
uint64 result;
if (!QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&result)))
result = 0;
return result;
}
inline uint64 getTimerFrequency(void)
{
uint64 result;
if (!QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&result)))
result = 0;
return result;
}
inline void sleep(uint32 ms)
{
Sleep(ms);
}
class CTimer
{
public:
CTimer();
void Set(uint32 seconds);
void Signal();
bool Expired();
private:
uint32 mTimer;
};
inline void CTimer::Set(uint32 interval)
{
mTimer = (uint32)time(0) + interval;
}
inline void CTimer::Signal()
{
mTimer = 0;
}
inline bool CTimer::Expired()
{
return (mTimer <= (uint32)time(0));
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif BASE_WIN32_PLATFORM_H
@@ -0,0 +1,315 @@
////////////////////////////////////////
// Thread.cpp
//
// Purpose:
// 1. Implementation of the CThread class.
//
// Revisions:
// 07/10/2001 Created
//
#pragma warning ( disable: 4786 )
#if !defined(_MT)
# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_MT)" )
#else
#include <process.h>
#include <time.h>
#include "Thread.h"
using namespace std;
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
void threadProc(void *threadPtr)
{
CThread &thread = *((CThread*)threadPtr);
thread.mThreadActive = true;
thread.ThreadProc();
thread.mThreadActive = false;
}
CThread::CThread()
{
mThreadID = 0;
mThreadActive = false;
mThreadContinue = false;
}
CThread::~CThread()
{
StopThread();
}
void CThread::StartThread()
{
mThreadContinue = true;
mThreadID = _beginthread(threadProc,0,this);
while (!IsThreadActive())
Base::sleep(1);
}
int32 CThread::StopThread(int32 timeout)
{
timeout += time(0);
mThreadContinue = false;
while (mThreadActive && time(0)<timeout)
sleep(1);
if (mThreadActive)
{
mThreadActive = false;
return eSTOP_TIMEOUT;
}
return eSTOP_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////
CThreadPool::CMember::CMember(CThreadPool * parent) :
mParent(parent),
mFunction(NULL),
mArgument(NULL),
mSemaphore()
{
StartThread();
}
CThreadPool::CMember::~CMember()
{
}
void CThreadPool::CMember::Destroy()
{
mThreadContinue = false;
mSemaphore.Signal();
}
bool CThreadPool::CMember::Execute(void( __cdecl *function )( void * ), void * arg)
{
if (mFunction)
return false;
mArgument = arg;
mFunction = function;
mSemaphore.Signal();
return true;
}
void CThreadPool::CMember::ThreadProc()
{
mParent->OnStartup(this);
while (mThreadContinue)
{
mParent->OnIdle(this);
mSemaphore.Wait(mParent->GetTimeOut()*1000);
if (mFunction)
{
mFunction(mArgument);
mArgument = NULL;
mFunction = NULL;
}
else if (mParent->OnDestory(this))
mThreadContinue = false;
}
}
////////////////////////////////////////////////////////////////////////////////
CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) :
mMutex(),
mIdleMember(),
mBusyMember(),
mNullMember(),
mThreadCount(0),
mMaxThreads(maxThreads),
mMinThreads(minThreads),
mTimeOut(timeout)
{
if (mMaxThreads == 0) mMaxThreads = 1;
if (mMinThreads == 0) mMinThreads = 1;
if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads;
for (uint32 i=0; i<mMinThreads; i++)
new CMember(this);
}
CThreadPool::~CThreadPool()
{
set<CMember *>::iterator setIterator;
////////////////////////////////////////
// (1) Destory all busy member threads
mMutex.Lock();
setIterator = mBusyMember.begin();
while (setIterator != mBusyMember.end())
(*setIterator++)->Destroy();
mMutex.Unlock();
////////////////////////////////////////
// (2) Destory all idle member threads
while (mThreadCount)
{
mMutex.Lock();
setIterator = mIdleMember.begin();
while (setIterator != mIdleMember.end())
(*setIterator++)->Destroy();
mMutex.Unlock();
sleep(1);
}
////////////////////////////////////////
// (3) Delete the null member threads
mMutex.Lock();
while (!mNullMember.empty())
{
delete mNullMember.front();
mNullMember.pop_front();
}
mMutex.Unlock();
}
bool CThreadPool::Execute(void( __cdecl *function )( void * ), void * arg, uint32 poolGrowthSize )
{
mMutex.Lock();
////////////////////////////////////////
// (1) If no idle members, return false to indicate that no threads
// were available. If the thread count is below the max, create
// a new thread.
if (mIdleMember.empty())
{
if (mThreadCount < mMaxThreads)
{
if (!poolGrowthSize)
poolGrowthSize = mMinThreads;
if ((mThreadCount + poolGrowthSize) > mMaxThreads)
poolGrowthSize = mMaxThreads - mThreadCount;
for (uint32 i(0); i < poolGrowthSize; i++)
new CMember(this);
mMutex.Unlock();
time_t idleTimeout = time(0) + 5;
while(mIdleMember.empty())
{
if (time(0) >= idleTimeout)
{
return false;
}
Base::sleep(10);
}
mMutex.Lock();
}
else
{
mMutex.Unlock();
return false;
}
}
////////////////////////////////////////
// (2) Delete any null member threads.
while (!mNullMember.empty())
{
delete mNullMember.front();
mNullMember.pop_front();
}
////////////////////////////////////////
// (3) Move the first idle thread to the busy set and signal the
// thread to execute the specified function.
CMember * member = *(mIdleMember.begin());
mIdleMember.erase(member);
mBusyMember.insert(member);
member->Execute(function,arg);
mMutex.Unlock();
return true;
}
uint32 CThreadPool::GetTimeOut()
{
return mTimeOut;
}
void CThreadPool::OnStartup(CMember * member)
{
mMutex.Lock();
mThreadCount++;
mIdleMember.insert(member);
mMutex.Unlock();
}
void CThreadPool::OnIdle(CMember * member)
{
mMutex.Lock();
mBusyMember.erase(member);
mIdleMember.insert(member);
mMutex.Unlock();
}
bool CThreadPool::OnDestory(CMember * member)
{
set<CMember *>::iterator setIterator;
mMutex.Lock();
bool result = (setIterator = mIdleMember.find(member)) != mIdleMember.end();
if (result)
{
mNullMember.push_back(member);
mIdleMember.erase(setIterator);
mThreadCount--;
}
mMutex.Unlock();
return result;
}
SwitchableScopeLock::SwitchableScopeLock(CMutex & mutex, bool isOn) :
mMutex(mutex),
mIsOn(isOn)
{
if(mIsOn) { mMutex.Lock(); }
}
SwitchableScopeLock::~SwitchableScopeLock()
{
if(mIsOn) { mMutex.Unlock(); }
}
////////////////////////////////////////////////////////////////////////////////
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_MT)
@@ -0,0 +1,152 @@
////////////////////////////////////////
// Thread.h
//
// Purpose:
// 1. Declair the CThread class that encapsulates threading functionality.
// This abstract base class in intended to be used to encapsulate
// individual tasks that require threading in derived classes.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_WIN32_THREAD_H
#define BASE_WIN32_THREAD_H
#if defined(_MT)
#pragma warning( disable : 4786)
#include <list>
#include <set>
#include "Platform.h"
#include "Mutex.h"
#include "Event.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
////////////////////////////////////////
// Class:
// CThread
//
// Purpose:
// Encapsulates threading functionality. Creating classes derived
// from CThread provides an easy way to encapsulate tasks that require
// their own thread.
//
// Public Methods:
// StartThread() : Creates the low-level thread handle and begins executing
// the CThread::ThreadProc() function within the new thread.
// StopThread() : Signals the ThreadProc() function to stop executing using
// the mThreadContinue member variable, and waits for the ThreadProc()
// function to exit. By default, the function will block for a maximum
// of 5 seconds before exiting without the thread halting.
// IsThreadActive() : Returns true if the physical thread is still executing
// within the ThreadProc() function, otherwise it returns false.
// ThreadProc() : Pure-virtual function that will be executed when the StartThread()
// function is called. Derived classes must implement this function. The
// mThreadContinue member variable should be used internal the the ThreadProc()
// function to indicate whether it should continue executing or exit.
// Protected Attributes:
// mThreadContinue : Boolean value indicating to the ThreadProc() function
// whether to continue executing or to exit. If mThreadContinue is true,
// ThreadProc() should continue, otherwise ThreadProc() should exit. It
// left up to the derived class to implement a ThreadProc() function that
// uses the mThreadContinue member.
//
//
class CThread
{
friend void threadProc(void *);
public:
enum { eSTOP_SUCCESS, eSTOP_TIMEOUT };
public:
CThread();
virtual ~CThread();
void StartThread();
int32 StopThread(int32 timeout=5);
bool IsThreadActive() { return mThreadActive; }
protected:
virtual void ThreadProc() = 0;
protected:
bool mThreadContinue;
private:
uint32 mThreadID;
bool mThreadActive;
};
class CThreadPool
{
private:
class CMember : public CThread
{
public:
CMember(CThreadPool * parent);
virtual ~CMember();
bool Execute(void( __cdecl *function )( void * ), void * arg);
void Destroy();
protected:
virtual void ThreadProc();
private:
CThreadPool * mParent;
void( __cdecl * mFunction )( void * );
void * mArgument;
CEvent mSemaphore;
};
friend class CMember;
public:
CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60);
~CThreadPool();
virtual bool Execute(void( __cdecl *function )( void * ), void * arg, uint32 poolGrowthSize = 0);
private:
uint32 GetTimeOut();
void OnStartup(CMember * member);
void OnIdle(CMember * member);
bool OnDestory(CMember * member);
private:
CMutex mMutex;
std::set<CMember *> mIdleMember;
std::set<CMember *> mBusyMember;
std::list<CMember *> mNullMember;
uint32 mThreadCount;
uint32 mMaxThreads;
uint32 mMinThreads;
uint32 mTimeOut;
};
class SwitchableScopeLock
{
public:
SwitchableScopeLock(CMutex & mutex, bool isOn);
~SwitchableScopeLock();
private:
CMutex & mMutex;
bool mIsOn;
};
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // #if defined(_MT)
#endif // BASE_WIN32_THREAD_H
@@ -0,0 +1,42 @@
////////////////////////////////////////
// Types.h
//
// Purpose:
// 1. Define integer types that are unambiguous with respect to size
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_WIN32_TYPES_H
#define BASE_WIN32_TYPES_H
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#define INT32_MAX 0x7FFFFFFF
#define INT32_MIN 0x80000000
#define UINT32_MAX 0xFFFFFFFF
typedef signed char int8;
typedef unsigned char uint8;
typedef short int16;
typedef unsigned short uint16;
typedef int int32;
typedef unsigned uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // BASE_WIN32_TYPES_H