mirror of
https://github.com/SWG-Source/src.git
synced 2026-08-01 01:16:03 -04:00
Added ChatServer and soePlatform
This commit is contained in:
@@ -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
|
||||
+238
@@ -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
|
||||
+200
@@ -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
|
||||
+110
@@ -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
|
||||
+102
@@ -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
|
||||
+112
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user