summaryrefslogtreecommitdiff
path: root/src/fstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/fstring.h')
-rw-r--r--src/fstring.h239
1 files changed, 231 insertions, 8 deletions
diff --git a/src/fstring.h b/src/fstring.h
index 2eaa4ba..287641f 100644
--- a/src/fstring.h
+++ b/src/fstring.h
@@ -4,28 +4,251 @@
4#include <stdint.h> 4#include <stdint.h>
5#include <memory> 5#include <memory>
6 6
7template< typename chr=char >
8struct FStringChunk
9{
10 long nLength;
11 chr *pData;
12 FStringChunk *pNext;
13};
14
7/** 15/**
8 * 16 *
9 */ 17 */
10template< typename chr, typename chralloc = std::allocator<chr> > 18template< typename chr=char, typename chralloc=std::allocator<chr>, typename chunkalloc=std::allocator<struct FStringChunk<chr> > >
11class FString 19class FBasicString
12{ 20{
21private:
22 typedef struct FStringChunk<chr> Chunk;
23
13public: 24public:
14 FString() : 25 FBasicString() :
15 pData( NULL ), 26 nLength( 0 ),
16 pnRefs( NULL ) 27 pnRefs( NULL ),
28 pFirst( NULL ),
29 pLast( NULL )
30 {
31 }
32
33 FBasicString( const chr *pData ) :
34 nLength( 0 ),
35 pnRefs( NULL ),
36 pFirst( NULL ),
37 pLast( NULL )
38 {
39 append( pData );
40 }
41
42 FBasicString( const chr *pData, long nLength ) :
43 nLength( 0 ),
44 pnRefs( NULL ),
45 pFirst( NULL ),
46 pLast( NULL )
47 {
48 append( pData, nLength );
49 }
50
51 virtual ~FBasicString()
52 {
53 }
54
55 void append( const chr *pData )
56 {
57 long nLen;
58 for( nLen = 0; pData[nLen] != (chr)0; nLen++ );
59
60 Chunk *pNew = newChunk( nLen );
61 memcpy( pNew->pData, pData, nLen * sizeof(chr) );
62
63 appendChunk( pNew );
64 }
65
66 void append( const chr *pData, long nLen )
67 {
68 Chunk *pNew = newChunk( nLen );
69
70 memcpy( pNew->pData, pData, nLen * sizeof(chr) );
71
72 appendChunk( pNew );
73 }
74
75 void prepend( const chr *pData )
76 {
77 long nLen;
78 for( nLen = 0; pData[nLen] != (chr)0; nLen++ );
79
80 Chunk *pNew = newChunk( nLen );
81 memcpy( pNew->pData, pData, nLen * sizeof(chr) );
82
83 prependChunk( pNew );
84 }
85
86 void prepend( const chr *pData, long nLen )
87 {
88 Chunk *pNew = newChunk( nLen );
89
90 memcpy( pNew->pData, pData, nLen * sizeof(chr) );
91
92 prependChunk( pNew );
93 }
94
95 void clear()
96 {
97 if( pFirst == NULL )
98 return;
99
100 Chunk *i = pFirst;
101 for(;;)
102 {
103 Chunk *n = i->pNext;
104 aChr.deallocate( i->pData, i->nLength+1 );
105 aChunk.deallocate( i, 1 );
106 if( n == NULL )
107 break;
108 i = n;
109 }
110 pFirst = pLast = NULL;
111 nLength = 0;
112 }
113
114 chr *c_str()
115 {
116 if( pFirst == NULL )
117 return NULL;
118
119 flatten();
120 return pFirst->pData;
121 }
122
123 FBasicString<chr, chralloc, chunkalloc> &operator +=( const chr *pData )
17 { 124 {
125 append( pData );
126
127 return (*this);
18 } 128 }
19 129
20 virtual ~FString() 130 FBasicString<chr, chralloc, chunkalloc> &operator =( const chr *pData )
21 { 131 {
132 clear();
133 append( pData );
134
135 return (*this);
136 }
137
138 bool operator ==( const chr *pData )
139 {
140 if( pFirst == NULL ) {
141 if( pData == NULL )
142 return true;
143 return false;
144 }
145
146 flatten();
147 const chr *a = pData;
148 chr *b = pFirst->pData;
149 for( ; *a!=(chr)0; a++, b++ )
150 {
151 if( *a != *b )
152 return false;
153 }
154
155 return true;
156 }
157
158 bool operator !=(const chr *pData )
159 {
160 return !(*this == pData);
161 }
162
163
164
165private:
166 void flatten()
167 {
168 if( isFlat() )
169 return;
170
171 if( pFirst == NULL )
172 return;
173
174 Chunk *pNew = newChunk( nLength );
175 chr *pos = pNew->pData;
176 Chunk *i = pFirst;
177 for(;;)
178 {
179 memcpy( pos, i->pData, i->nLength*sizeof(chr) );
180 pos += i->nLength;
181 i = i->pNext;
182 if( i == NULL )
183 break;
184 }
185 clear();
186
187 appendChunk( pNew );
188 }
189
190 bool isFlat()
191 {
192 return (pFirst == pLast);
193 }
194
195 bool isShared()
196 {
197 return (pnRefs != NULL);
198 }
199
200 Chunk *newChunk()
201 {
202 Chunk *pNew = aChunk.allocate( 1 );
203 pNew->pNext = NULL;
204 return pNew;
205 }
206
207 Chunk *newChunk( long nLen )
208 {
209 Chunk *pNew = aChunk.allocate( 1 );
210 pNew->pNext = NULL;
211 pNew->nLength = nLen;
212 pNew->pData = aChr.allocate( nLen+1 );
213 return pNew;
214 }
215
216 void appendChunk( Chunk *pNewChunk )
217 {
218 if( pFirst == NULL )
219 pLast = pFirst = pNewChunk;
220 else
221 {
222 pLast->pNext = pNewChunk;
223 pLast = pNewChunk;
224 }
225
226 nLength += pNewChunk->nLength;
227 }
228
229 void prependChunk( Chunk *pNewChunk )
230 {
231 if( pFirst == NULL )
232 pLast = pFirst = pNewChunk;
233 else
234 {
235 pNewChunk->pNext = pFirst;
236 pFirst = pNewChunk;
237 }
238
239 nLength += pNewChunk->nLength;
22 } 240 }
23 241
24private: 242private:
25 long nLength; 243 long nLength;
26 chr *pData;
27 uint32_t *pnRefs; 244 uint32_t *pnRefs;
28 chralloc aChars; 245 Chunk *pFirst;
246 Chunk *pLast;
247
248 chralloc aChr;
249 chunkalloc aChunk;
29}; 250};
30 251
252typedef FBasicString<char> FString;
253
31#endif 254#endif