diff options
Diffstat (limited to '')
-rw-r--r-- | src/fstring.h | 174 |
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 | */ |
18 | template< typename chr=char, typename chralloc=std::allocator<chr>, typename chunkalloc=std::allocator<struct FStringChunk<chr> > > | 26 | template< typename chr=char, typename chralloc=std::allocator<chr>, typename chunkalloc=std::allocator<struct FStringChunk<chr> > > |
19 | class FBasicString | 27 | class 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 | ||
222 | private: | 246 | private: |
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 | ||
443 | private: | 494 | private: |
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 | ||
453 | typedef FBasicString<char> FString; | 504 | typedef FBasicString<char> FString; |
454 | 505 | ||
506 | #include "hash.h" | ||
507 | template<> uint32_t __calcHashCode<FString>( const FString &k ); | ||
508 | template<> bool __cmpHashKeys<FString>( const FString &a, const FString &b ); | ||
509 | |||
510 | |||
455 | #endif | 511 | #endif |