Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#ifndef STRING_BUILDER_INCLUDED
#define STRING_BUILDER_INCLUDED
#include <math.h>
#include "ext_stream.h"
template <class Ty>
class string_builder_base : public ext::stream_base
{
public:
typedef ext::stream_base base;
typedef Ty value_type;
typedef Ty* value_type_ptr;
typedef const Ty* const_value_type_ptr;
private:
value_type_ptr m_buffer;
size_t m_bufferSize;
size_t m_stringSize;
size_t m_growby;
bool allocate(size_t newsize)
{
if(allocated() < newsize) {
value_type_ptr old=m_buffer;
size_t oldsize=m_bufferSize;
int c=(int)ceil((float)newsize / growby());
m_bufferSize=c * growby();
m_buffer=new value_type[m_bufferSize];
if(m_buffer==NULL){
setstate(failbit);
m_buffer=old;
m_bufferSize=oldsize;
}
else{
memcpy(m_buffer, old, oldsize * sizeof(value_type));
delete[] old;
}
}
return (state() & failbit)==0;
}
void size(size_t newsize) { m_stringSize=newsize; }
void init()
{
m_buffer=0; m_bufferSize=m_stringSize=0;
base::clear(badbit);
}
size_t strlen(const wchar_t *str) { return ::wcslen(str); }
size_t strlen(const char *str) { return ::strlen(str); }
public:
string_builder_base() { init(); growby(0); }
string_builder_base(const_value_type_ptr str)
{
init(); growby(0);
append(str);
}
size_t allocated() const { return m_bufferSize; }
size_t size() const { return m_stringSize; }
size_t growby() const { return m_growby; }
void growby(size_t newgrow) { if(newgrow==0) newgrow=50; m_growby=newgrow; }
~string_builder_base() { delete[] m_buffer; }
void append(const_value_type_ptr str)
{
size_t s=strlen(str);
size_t newsize=size() + s;
if(allocate(newsize + 1)==false)
return;
memcpy(m_buffer + size(), str, (s + 1) * sizeof(value_type));
size(newsize);
base::clear(m_buffer ? goodbit : badbit);
}
void append(const value_type& ch)
{
if(!good()) return;
size_t newsize=size() + 1;
if(allocate(newsize + 1)==false)
return;
m_buffer[size()]=ch;
m_buffer[size() + 1]=0;
size(newsize);
base::clear(m_buffer ? goodbit : badbit);
}
value_type_ptr getbuffer()
{
value_type_ptr b=m_buffer;
init();
return b;
}
void clear()
{
delete[] m_buffer;
init();
}
operator const_value_type_ptr () const { return m_buffer; }
string_builder_base& operator = (const string_builder_base& other)
{
if(other.m_buffer==0) {
delete[] m_buffer;
init();
}
else
(*this)=other.m_buffer;
return *this;
}
string_builder_base& operator = (const_value_type_ptr str)
{
size(0);
append(str);
base::clear(m_buffer ? goodbit : badbit);
return *this;
}
};
class string_builder : public string_builder_base<char>
{
public:
string_builder() : string_builder_base<char>() { }
string_builder(const char *str) : string_builder_base<char>(str) { }
};
inline string_builder& operator << (string_builder& is, const char *str)
{
is.append(str);
return is;
}
inline string_builder& operator << (string_builder& is, char ch)
{
is.append(ch);
return is;
}
class wstring_builder : public string_builder_base<wchar_t>
{
public:
wstring_builder() : string_builder_base<wchar_t>() { }
wstring_builder(const wchar_t *str) : string_builder_base<wchar_t>(str) { }
};
inline wstring_builder& operator << (wstring_builder& is, const wchar_t *str)
{
is.append(str);
return is;
}
inline wstring_builder& operator << (wstring_builder& is, wchar_t ch)
{
is.append(ch);
return is;
}
inline wstring_builder& operator << (wstring_builder& is, int i)
{
is.append(i);
return is;
}
#endif // !defined(STRING_BUILDER_INCLUDED)