aboutsummaryrefslogtreecommitdiff
path: root/src/fstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/fstring.h')
-rw-r--r--src/fstring.h174
1 files changed, 115 insertions, 59 deletions
diff --git a/src/fstring.h b/src/fstring.h
index db54cdd..95ba382 100644
--- a/src/fstring.h
+++ b/src/fstring.h
@@ -13,7 +13,15 @@ struct FStringChunk
13}; 13};
14 14
15/** 15/**
16 * 16 * Flexible String class. This class was designed with string passing and
17 * generation in mind. Like the standard string class you can specify what
18 * datatype to use for each character. Unlike the standard string class,
19 * collection of appended and prepended terms is done lazily, making long
20 * operations that involve many appends very inexpensive. In addition internal
21 * ref-counting means that if you pass strings around between functions there's
22 * almost no overhead in time or memory since a reference is created and no
23 * data is actually copied. This also means that you never need to put any
24 * FBasicString into a ref-counting container class.
17 */ 25 */
18template< typename chr=char, typename chralloc=std::allocator<chr>, typename chunkalloc=std::allocator<struct FStringChunk<chr> > > 26template< typename chr=char, typename chralloc=std::allocator<chr>, typename chunkalloc=std::allocator<struct FStringChunk<chr> > >
19class FBasicString 27class FBasicString
@@ -49,6 +57,7 @@ public:
49 append( pData, nLength ); 57 append( pData, nLength );
50 } 58 }
51 59
60 /*
52 FBasicString( MyType &rSrc ) : 61 FBasicString( MyType &rSrc ) :
53 nLength( 0 ), 62 nLength( 0 ),
54 pnRefs( NULL ), 63 pnRefs( NULL ),
@@ -56,9 +65,9 @@ public:
56 pLast( NULL ) 65 pLast( NULL )
57 { 66 {
58 joinShare( rSrc ); 67 joinShare( rSrc );
59 } 68 }*/
60 69
61 FBasicString( const FBasicString<chr, chralloc, chunkalloc> &rSrc ) : 70 FBasicString( const MyType &rSrc ) :
62 nLength( 0 ), 71 nLength( 0 ),
63 pnRefs( NULL ), 72 pnRefs( NULL ),
64 pFirst( NULL ), 73 pFirst( NULL ),
@@ -68,7 +77,8 @@ public:
68 // In the case that the source were flat, we could get a reference, it 77 // In the case that the source were flat, we could get a reference, it
69 // would make some things faster, but not matter in many other cases. 78 // would make some things faster, but not matter in many other cases.
70 79
71 copyFrom( rSrc ); 80 joinShare( rSrc );
81 //copyFrom( rSrc );
72 } 82 }
73 83
74 virtual ~FBasicString() 84 virtual ~FBasicString()
@@ -118,28 +128,7 @@ public:
118 128
119 void clear() 129 void clear()
120 { 130 {
121 if( pFirst == NULL ) 131 realClear();
122 return;
123
124 if( isShared() )
125 {
126 decRefs();
127 }
128 else
129 {
130 Chunk *i = pFirst;
131 for(;;)
132 {
133 Chunk *n = i->pNext;
134 aChr.deallocate( i->pData, i->nLength+1 );
135 aChunk.deallocate( i, 1 );
136 if( n == NULL )
137 break;
138 i = n;
139 }
140 pFirst = pLast = NULL;
141 nLength = 0;
142 }
143 } 132 }
144 133
145 chr *c_str() 134 chr *c_str()
@@ -150,6 +139,15 @@ public:
150 flatten(); 139 flatten();
151 return pFirst->pData; 140 return pFirst->pData;
152 } 141 }
142
143 const chr *c_str() const
144 {
145 if( pFirst == NULL )
146 return NULL;
147
148 flatten();
149 return pFirst->pData;
150 }
153 151
154 MyType &operator +=( const chr *pData ) 152 MyType &operator +=( const chr *pData )
155 { 153 {
@@ -168,26 +166,20 @@ public:
168 166
169 MyType &operator =( const MyType &rSrc ) 167 MyType &operator =( const MyType &rSrc )
170 { 168 {
171 if( rSrc.isFlat() ) 169 //if( rSrc.isFlat() )
172 { 170 //{
173 joinShare( rSrc ); 171 joinShare( rSrc );
174 } 172 //}
175 else 173 //else
176 { 174 //{
177 copyFrom( rSrc ); 175 // copyFrom( rSrc );
178 } 176 //}
177 //
179 178
180 return (*this); 179 return (*this);
181 } 180 }
182 181
183 MyType &operator =( MyType &rSrc ) 182 bool operator ==( const chr *pData ) const
184 {
185 joinShare( rSrc );
186
187 return (*this);
188 }
189
190 bool operator ==( const chr *pData )
191 { 183 {
192 if( pFirst == NULL ) { 184 if( pFirst == NULL ) {
193 if( pData == NULL ) 185 if( pData == NULL )
@@ -206,8 +198,33 @@ public:
206 198
207 return true; 199 return true;
208 } 200 }
201
202 bool operator ==( const MyType &pData ) const
203 {
204 if( pFirst == pData.pFirst )
205 return true;
206 if( pFirst == NULL )
207 return false;
208
209 flatten();
210 pData.flatten();
211 const chr *a = pData.pFirst->pData;
212 chr *b = pFirst->pData;
213 for( ; *a!=(chr)0; a++, b++ )
214 {
215 if( *a != *b )
216 return false;
217 }
218
219 return true;
220 }
209 221
210 bool operator !=(const chr *pData ) 222 bool operator !=(const chr *pData ) const
223 {
224 return !(*this == pData);
225 }
226
227 bool operator !=(const MyType &pData ) const
211 { 228 {
212 return !(*this == pData); 229 return !(*this == pData);
213 } 230 }
@@ -218,9 +235,16 @@ public:
218 235
219 return pFirst->pData[nIndex]; 236 return pFirst->pData[nIndex];
220 } 237 }
238
239 const chr &operator[]( long nIndex ) const
240 {
241 flatten();
242
243 return pFirst->pData[nIndex];
244 }
221 245
222private: 246private:
223 void flatten() 247 void flatten() const
224 { 248 {
225 if( isFlat() ) 249 if( isFlat() )
226 return; 250 return;
@@ -241,9 +265,36 @@ private:
241 if( i == NULL ) 265 if( i == NULL )
242 break; 266 break;
243 } 267 }
244 clear(); 268 realClear();
245 269
246 appendChunk( pNew ); 270 pLast = pFirst = pNew;
271 nLength = pNew->nLength;
272 }
273
274 void realClear() const
275 {
276 if( pFirst == NULL )
277 return;
278
279 if( isShared() )
280 {
281 decRefs();
282 }
283 else
284 {
285 Chunk *i = pFirst;
286 for(;;)
287 {
288 Chunk *n = i->pNext;
289 aChr.deallocate( i->pData, i->nLength+1 );
290 aChunk.deallocate( i, 1 );
291 if( n == NULL )
292 break;
293 i = n;
294 }
295 pFirst = pLast = NULL;
296 nLength = 0;
297 }
247 } 298 }
248 299
249 void copyFrom( const FBasicString<chr, chralloc, chunkalloc> &rSrc ) 300 void copyFrom( const FBasicString<chr, chralloc, chunkalloc> &rSrc )
@@ -279,14 +330,14 @@ private:
279 return (pnRefs != NULL); 330 return (pnRefs != NULL);
280 } 331 }
281 332
282 Chunk *newChunk() 333 Chunk *newChunk() const
283 { 334 {
284 Chunk *pNew = aChunk.allocate( 1 ); 335 Chunk *pNew = aChunk.allocate( 1 );
285 pNew->pNext = NULL; 336 pNew->pNext = NULL;
286 return pNew; 337 return pNew;
287 } 338 }
288 339
289 Chunk *newChunk( long nLen ) 340 Chunk *newChunk( long nLen ) const
290 { 341 {
291 Chunk *pNew = aChunk.allocate( 1 ); 342 Chunk *pNew = aChunk.allocate( 1 );
292 pNew->pNext = NULL; 343 pNew->pNext = NULL;
@@ -365,7 +416,7 @@ private:
365 * that was being shared so that this copy can be changed. This should be 416 * that was being shared so that this copy can be changed. This should be
366 * added before any call that will change this object; 417 * added before any call that will change this object;
367 */ 418 */
368 void unShare() 419 void unShare() const
369 { 420 {
370 if( isShared() == false ) 421 if( isShared() == false )
371 return; 422 return;
@@ -382,8 +433,8 @@ private:
382 break; 433 break;
383 } 434 }
384 decRefs(); 435 decRefs();
385 appendChunk( pNew ); 436 pLast = pFirst = pNew;
386 decRefs(); 437 nLength = pNew->nLength;
387 } 438 }
388 439
389 /** 440 /**
@@ -391,7 +442,7 @@ private:
391 * count hits zero because of this, it destroys the share. This is not 442 * count hits zero because of this, it destroys the share. This is not
392 * safe to call on it's own, it's much better to call unShare. 443 * safe to call on it's own, it's much better to call unShare.
393 */ 444 */
394 void decRefs() 445 void decRefs() const
395 { 446 {
396 if( isShared() ) 447 if( isShared() )
397 { 448 {
@@ -414,14 +465,14 @@ private:
414 * itself. This should only be called when the refcount for the share has 465 * itself. This should only be called when the refcount for the share has
415 * or is about to reach zero. 466 * or is about to reach zero.
416 */ 467 */
417 void destroyShare() 468 void destroyShare() const
418 { 469 {
419 delete pnRefs; 470 delete pnRefs;
420 pnRefs = NULL; 471 pnRefs = NULL;
421 clear(); 472 realClear();
422 } 473 }
423 474
424 void cpy( chr *dest, const chr *src, long count ) 475 void cpy( chr *dest, const chr *src, long count ) const
425 { 476 {
426 for( int j = 0; j < count; j++ ) 477 for( int j = 0; j < count; j++ )
427 { 478 {
@@ -441,15 +492,20 @@ private:
441 } 492 }
442 493
443private: 494private:
444 long nLength; 495 mutable long nLength;
445 mutable uint32_t *pnRefs; 496 mutable uint32_t *pnRefs;
446 Chunk *pFirst; 497 mutable Chunk *pFirst;
447 Chunk *pLast; 498 mutable Chunk *pLast;
448 499
449 chralloc aChr; 500 mutable chralloc aChr;
450 chunkalloc aChunk; 501 mutable chunkalloc aChunk;
451}; 502};
452 503
453typedef FBasicString<char> FString; 504typedef FBasicString<char> FString;
454 505
506#include "hash.h"
507template<> uint32_t __calcHashCode<FString>( const FString &k );
508template<> bool __cmpHashKeys<FString>( const FString &a, const FString &b );
509
510
455#endif 511#endif