Subversion Repositories spk

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
#ifndef STRING_BUILDER_INCLUDED
2
#define STRING_BUILDER_INCLUDED
3
 
4
#include <math.h>
5
#include "ext_stream.h"
6
 
7
template <class Ty>
8
class string_builder_base : public ext::stream_base
9
{
10
	public:
11
		typedef ext::stream_base base;
12
		typedef Ty value_type;
13
		typedef Ty* value_type_ptr;
14
		typedef const Ty* const_value_type_ptr;
15
 
16
	private:
17
		value_type_ptr m_buffer;
18
		size_t m_bufferSize;
19
		size_t m_stringSize;
20
		size_t m_growby;
21
 
22
		bool allocate(size_t newsize)
23
		{
24
			if(allocated() < newsize) {
25
				value_type_ptr old=m_buffer;
26
				size_t oldsize=m_bufferSize;
27
 
28
				int c=(int)ceil((float)newsize / growby());
29
				m_bufferSize=c * growby();
30
				m_buffer=new value_type[m_bufferSize];
31
				if(m_buffer==NULL){
32
					setstate(failbit);
33
					m_buffer=old;
34
					m_bufferSize=oldsize;
35
				}
36
				else{
37
					memcpy(m_buffer, old, oldsize * sizeof(value_type));
38
					delete[] old;
39
				}
40
			}
41
			return (state() & failbit)==0;
42
		}
43
 
44
		void size(size_t newsize) { m_stringSize=newsize; }
45
 
46
		void init()
47
		{
48
			m_buffer=0; m_bufferSize=m_stringSize=0; 
49
			base::clear(badbit);
50
		}
51
 
52
		size_t strlen(const wchar_t *str) { return ::wcslen(str); }
53
		size_t strlen(const char *str) { return ::strlen(str); }
54
 
55
	public:
56
		string_builder_base() { init(); growby(0); }
57
		string_builder_base(const_value_type_ptr str) 
58
		{
59
			init();	growby(0);
60
			append(str);
61
		}
62
 
63
		size_t allocated() const { return m_bufferSize; }
64
		size_t size() const { return m_stringSize; }
65
 
66
		size_t growby() const { return m_growby; }
67
		void growby(size_t newgrow) { if(newgrow==0) newgrow=50; m_growby=newgrow; }
68
 
69
		~string_builder_base() { delete[] m_buffer; }
70
 
71
		void append(const_value_type_ptr str)
72
		{
73
			size_t s=strlen(str);
74
			size_t newsize=size() + s;
75
			if(allocate(newsize + 1)==false)
76
				return;
77
			memcpy(m_buffer + size(), str, (s + 1) * sizeof(value_type));
78
			size(newsize);
79
			base::clear(m_buffer ? goodbit : badbit);
80
		}
81
 
82
		void append(const value_type& ch)
83
		{
84
			if(!good()) return;
85
			size_t newsize=size() + 1;
86
			if(allocate(newsize + 1)==false) 
87
				return;
88
			m_buffer[size()]=ch;
89
			m_buffer[size() + 1]=0;
90
			size(newsize);
91
			base::clear(m_buffer ? goodbit : badbit);
92
		}
93
 
94
		value_type_ptr getbuffer() 
95
		{
96
			value_type_ptr b=m_buffer;
97
			init();
98
			return b;
99
		}
100
 
101
		void clear()
102
		{
103
			delete[] m_buffer;
104
			init();
105
		}
106
 
107
		operator const_value_type_ptr () const { return m_buffer; }
108
 
109
		string_builder_base& operator = (const string_builder_base& other)
110
		{
111
			if(other.m_buffer==0) {
112
				delete[] m_buffer;
113
				init();
114
			}
115
			else 
116
				(*this)=other.m_buffer;
117
 
118
			return *this;
119
		}
120
 
121
		string_builder_base& operator = (const_value_type_ptr str)
122
		{
123
			size(0);
124
			append(str);
125
			base::clear(m_buffer ? goodbit : badbit);
126
			return *this;
127
		}
128
 
129
};
130
 
131
class string_builder : public string_builder_base<char>
132
{
133
	public:
134
		string_builder() : string_builder_base<char>() { }
135
		string_builder(const char *str) : string_builder_base<char>(str) { }
136
};
137
 
138
inline string_builder& operator << (string_builder& is, const char *str)
139
{
140
	is.append(str);
141
	return is;
142
}
143
 
144
inline string_builder& operator << (string_builder& is, char ch)
145
{
146
	is.append(ch);
147
	return is;
148
}
149
 
150
class wstring_builder : public string_builder_base<wchar_t>
151
{
152
	public:
153
		wstring_builder() : string_builder_base<wchar_t>() { }
154
		wstring_builder(const wchar_t *str) : string_builder_base<wchar_t>(str) { }
155
};
156
 
157
inline wstring_builder& operator << (wstring_builder& is, const wchar_t *str)
158
{
159
	is.append(str);
160
	return is;
161
}
162
 
163
inline wstring_builder& operator << (wstring_builder& is, wchar_t ch)
164
{
165
	is.append(ch);
166
	return is;
167
}
168
 
169
inline wstring_builder& operator << (wstring_builder& is, int i)
170
{
171
	is.append(i);
172
	return is;
173
}
174
 
175
#endif // !defined(STRING_BUILDER_INCLUDED)