Subversion Repositories spk

Rev

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