#ifndef _COMMON_STRINGBUFFER_HPP_
#define _COMMON_STRINGBUFFER_HPP_
#ifndef _COMMON_STRING_HPP_
#include <common/string.hpp>
#endif
#ifndef _COMMON_ARRAY_HPP_
#include <common/array.hpp>
#endif

class StringBuffer
{
public:
  StringBuffer();
	StringBuffer(DWORD initialSize);
	virtual ~StringBuffer();
	StringBuffer &append(const String &string);
	StringBuffer &append(const char &ch);
	void growBy(DWORD growBy);
	String toString(void)const;
private:
  enum{GrowBy=2048};
	void preallocate(DWORD items);
  Array<BYTE> mInternalRep;  
	DWORD mItemCount;
	DWORD mGrowBy;
};


inline
StringBuffer::StringBuffer()
: mGrowBy(GrowBy), mItemCount(0)
{
  mInternalRep.size(mGrowBy);
}

inline
StringBuffer::StringBuffer(DWORD initialSize)
: mGrowBy(initialSize?initialSize:GrowBy), mItemCount(0)
{ 
  mInternalRep.size(mGrowBy);
}

inline
StringBuffer::~StringBuffer()
{
}

inline
StringBuffer &StringBuffer::append(const String &string)
{
  int length(string.length());
  preallocate(length);
	::memcpy(&mInternalRep[mItemCount],string.str(),length);
	mItemCount+=length;
	return *this;
}

inline
StringBuffer &StringBuffer::append(const char &ch)
{
  preallocate(1);
	mInternalRep[mItemCount]=ch;
	mItemCount++;
	return *this;
}

inline
void StringBuffer::preallocate(DWORD items)
{
  if(mInternalRep.size()>mItemCount+items)return;
	Array<BYTE> tmpArray;
	tmpArray.size(mInternalRep.size()+(mGrowBy>items?mGrowBy:items));
	::memcpy(&tmpArray[0],&mInternalRep[0],mInternalRep.size());
	mInternalRep.size(tmpArray.size());
	::memcpy(&mInternalRep[0],&tmpArray[0],mItemCount);
}

inline
void StringBuffer::growBy(DWORD growBy)
{
  if(growBy)mGrowBy=growBy;
}

inline
String StringBuffer::toString(void)const
{
  String str;
	str.reserve(mItemCount+1);
	::memcpy(str.str(),&((Array<BYTE>&)mInternalRep)[0],mItemCount);
  (str.str())[mItemCount]=0;
  return str;
}
#endif
