Rev 1 | 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)