Files
src/external/3rd/library/soePlatform/ChatAPI/utils/Base/Archive.h
T
2017-01-25 16:25:04 +00:00

599 lines
15 KiB
C++
Executable File

////////////////////////////////////////////////////////////////////////////////
// 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);
}
}
////////////////////////////////////////////////////////////////////////////////
inline void get(ByteStream::ReadIterator & source, ByteStream & target)
{
target.put(source.getBuffer(), source.getSize());
source.advance(source.getSize());
}
template <typename T>
inline void get(ByteStream::ReadIterator & source, T & target)
{
source.get(&target, sizeof(T));
target = byteSwap(target);
}
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());
}
template <typename T>
inline void put(ByteStream & target, const T value)
{
T temp = byteSwap(value);
target.put(&temp, sizeof(T));
}
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);
////////////////////////////////////////////////////////////////////////////////
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
{
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)
{
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
{
using Base::put;
unsigned int arraySize = array.size();
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);
}
}
////////////////////////////////////////////////////////////////////////////////
template <typename T>
inline bool overwriteEnd(ByteStream & target, const T value)
{
T temp = byteSwap(value);
return target.overwriteEnd(&temp, sizeof(T));
}
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