summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2007-03-15 06:57:03 +0000
committerMike Buland <eichlan@xagasoft.com>2007-03-15 06:57:03 +0000
commit505410a5c3b93f81deda8b9653c2237a433be5c1 (patch)
treee4ac25af48878cdf466571a3d70577de9d3f890a
parentcf847cc534a2a7ad06750c446028b7c6d126fe21 (diff)
downloadlibbu++-505410a5c3b93f81deda8b9653c2237a433be5c1.tar.gz
libbu++-505410a5c3b93f81deda8b9653c2237a433be5c1.tar.bz2
libbu++-505410a5c3b93f81deda8b9653c2237a433be5c1.tar.xz
libbu++-505410a5c3b93f81deda8b9653c2237a433be5c1.zip
This version may break hashing of strings, but at least you can hash FStrings...
templates are confusing.
Diffstat (limited to '')
-rw-r--r--src/fstring.cpp11
-rw-r--r--src/fstring.h174
-rw-r--r--src/hash.cpp82
-rw-r--r--src/hash.h37
-rw-r--r--src/tests/fstring.cpp10
5 files changed, 186 insertions, 128 deletions
diff --git a/src/fstring.cpp b/src/fstring.cpp
index 8fe2941..82d024d 100644
--- a/src/fstring.cpp
+++ b/src/fstring.cpp
@@ -1,2 +1,13 @@
1#include "fstring.h" 1#include "fstring.h"
2#include "hash.h"
3
4template<> uint32_t __calcHashCode<FString>( const FString &k )
5{
6 return __calcHashCode( k.c_str() );
7}
8
9template<> bool __cmpHashKeys<FString>( const FString &a, const FString &b )
10{
11 return a == b;
12}
2 13
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
diff --git a/src/hash.cpp b/src/hash.cpp
index d428dd6..004d6dd 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -2,48 +2,57 @@
2 2
3subExceptionDef( HashException ) 3subExceptionDef( HashException )
4 4
5template<> uint32_t __calcHashCode<const int>( const int k ) 5template<> uint32_t __calcHashCode<int>( const int &k )
6{ 6{
7 return k; 7 return k;
8} 8}
9 9
10template<> bool __cmpHashKeys<const int>( const int a, const int b ) 10template<> bool __cmpHashKeys<int>( const int &a, const int &b )
11{ 11{
12 return a == b; 12 return a == b;
13} 13}
14 14
15template<> uint32_t __calcHashCode<int>( int k ) 15template<> uint32_t __calcHashCode<unsigned int>( const unsigned int &k )
16{ 16{
17 return k; 17 return k;
18} 18}
19 19
20template<> bool __cmpHashKeys<int>( int a, int b ) 20template<> bool __cmpHashKeys<unsigned int>( const unsigned int &a, const unsigned int &b )
21{ 21{
22 return a == b; 22 return a == b;
23} 23}
24 24
25template<> uint32_t __calcHashCode<const unsigned int>( const unsigned int k ) 25template<>
26uint32_t __calcHashCode<const char *>( const char * const &k )
26{ 27{
27 return k; 28 if (k == NULL)
28} 29 {
30 return 0;
31 }
32
33 unsigned long int nPos = 0;
34 for( const char *s = k; *s; s++ )
35 {
36 nPos = *s + (nPos << 6) + (nPos << 16) - nPos;
37 }
29 38
30template<> bool __cmpHashKeys<const unsigned int>( const unsigned int a, const unsigned int b ) 39 return nPos;
31{
32 return a == b;
33} 40}
34 41
35template<> uint32_t __calcHashCode<unsigned int>( unsigned int k ) 42template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b )
36{ 43{
37 return k; 44 if( a == b )
38} 45 return true;
39 46
40template<> bool __cmpHashKeys<unsigned int>( unsigned int a, unsigned int b ) 47 for(int j=0; a[j] == b[j]; j++ )
41{ 48 if( *a == '\0' )
42 return a == b; 49 return true;
50
51 return false;
43} 52}
44 53
45template<> 54template<>
46uint32_t __calcHashCode<const char *>( const char * k ) 55uint32_t __calcHashCode<char *>( char * const &k )
47{ 56{
48 if (k == NULL) 57 if (k == NULL)
49 { 58 {
@@ -59,30 +68,19 @@ uint32_t __calcHashCode<const char *>( const char * k )
59 return nPos; 68 return nPos;
60} 69}
61 70
62template<> bool __cmpHashKeys<const char *>( const char *a, const char *b ) 71template<> bool __cmpHashKeys<char *>( char * const &a, char * const &b )
63{ 72{
64 if( a == b ) 73 if( a == b )
65 return true; 74 return true;
66 75
67 for(; *a == *b; a++, b++ ) 76 for(int j=0; a[j] == b[j]; j++ )
68 if( *a == '\0' ) 77 if( *a == '\0' )
69 return true; 78 return true;
70 79
71 return false; 80 return false;
72} 81}
73 82
74template<> 83template<> uint32_t __calcHashCode<std::string>( const std::string &k )
75uint32_t __calcHashCode<char *>( char *k )
76{
77 return __calcHashCode<const char *>((const char *)k );
78}
79
80template<> bool __cmpHashKeys<char *>( char *a, char *b )
81{
82 return __cmpHashKeys<const char *>((const char *)a, (const char *)b );
83}
84
85template<> uint32_t __calcHashCode<const std::string>( const std::string k )
86{ 84{
87 std::string::size_type j, sz = k.size(); 85 std::string::size_type j, sz = k.size();
88 const char *s = k.c_str(); 86 const char *s = k.c_str();
@@ -96,28 +94,20 @@ template<> uint32_t __calcHashCode<const std::string>( const std::string k )
96 return nPos; 94 return nPos;
97} 95}
98 96
99template<> bool __cmpHashKeys<const std::string>( const std::string a, const std::string b ) 97template<> bool __cmpHashKeys<std::string>( const std::string &a, const std::string &b )
100{ 98{
101 return a == b; 99 return a == b;
102} 100}
103 101
104template<> uint32_t __calcHashCode<std::string>( std::string k ) 102template<> uint32_t __calcHashCode<Hashable>( const Hashable &k )
105{
106 return __calcHashCode<const std::string>( k );
107}
108
109template<> bool __cmpHashKeys<std::string>( std::string a, std::string b )
110{ 103{
111 return __cmpHashKeys<const std::string>( a, b ); 104 return 0;
105 //return k.getHashCode();
112} 106}
113 107
114template<> uint32_t __calcHashCode<Hashable &>( Hashable &k ) 108template<> bool __cmpHashKeys<Hashable>( const Hashable &a, const Hashable &b )
115{ 109{
116 return k.getHashCode(); 110 return false;
117} 111 //return a.compareForHash( b );
118
119template<> bool __cmpHashKeys<Hashable &>( Hashable &a, Hashable &b )
120{
121 return a.compareForHash( b );
122} 112}
123 113
diff --git a/src/hash.h b/src/hash.h
index 7f1ac65..6671ae6 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -18,10 +18,10 @@ enum eHashException
18}; 18};
19 19
20template<typename T> 20template<typename T>
21uint32_t __calcHashCode( T k ); 21uint32_t __calcHashCode( const T &k );
22 22
23template<typename T> 23template<typename T>
24bool __cmpHashKeys( T a, T b ); 24bool __cmpHashKeys( const T &a, const T &b );
25 25
26struct __calcNextTSize_fast 26struct __calcNextTSize_fast
27{ 27{
@@ -649,31 +649,22 @@ protected:
649 sizecalc szCalc; 649 sizecalc szCalc;
650}; 650};
651 651
652template<> uint32_t __calcHashCode<const int>( const int k ); 652template<> uint32_t __calcHashCode<int>( const int &k );
653template<> bool __cmpHashKeys<const int>( const int a, const int b ); 653template<> bool __cmpHashKeys<int>( const int &a, const int &b );
654 654
655template<> uint32_t __calcHashCode<int>( int k ); 655template<> uint32_t __calcHashCode<unsigned int>( const unsigned int &k );
656template<> bool __cmpHashKeys<int>( int a, int b ); 656template<> bool __cmpHashKeys<unsigned int>( const unsigned int &a, const unsigned int &b );
657 657
658template<> uint32_t __calcHashCode<const unsigned int>( const unsigned int k ); 658template<> uint32_t __calcHashCode<const char *>( const char * const &k );
659template<> bool __cmpHashKeys<const unsigned int>( const unsigned int a, const unsigned int b ); 659template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b );
660 660
661template<> uint32_t __calcHashCode<unsigned int>( unsigned int k ); 661template<> uint32_t __calcHashCode<char *>( char * const &k );
662template<> bool __cmpHashKeys<unsigned int>( unsigned int a, unsigned int b ); 662template<> bool __cmpHashKeys<char *>( char * const &a, char * const &b );
663 663
664template<> uint32_t __calcHashCode<const char *>( const char *k ); 664template<> uint32_t __calcHashCode<std::string>( const std::string &k );
665template<> bool __cmpHashKeys<const char *>( const char *a, const char *b ); 665template<> bool __cmpHashKeys<std::string>( const std::string &a, const std::string &b );
666 666
667template<> uint32_t __calcHashCode<char *>( char *k ); 667template<> uint32_t __calcHashCode<Hashable>( const Hashable &k );
668template<> bool __cmpHashKeys<char *>( char *a, char *b ); 668template<> bool __cmpHashKeys<Hashable>( const Hashable &a, const Hashable &b );
669
670template<> uint32_t __calcHashCode<const std::string>( const std::string k );
671template<> bool __cmpHashKeys<const std::string>( const std::string a, const std::string b );
672
673template<> uint32_t __calcHashCode<std::string>( std::string k );
674template<> bool __cmpHashKeys<std::string>( std::string a, std::string b );
675
676template<> uint32_t __calcHashCode<Hashable &>( Hashable &k );
677template<> bool __cmpHashKeys<Hashable &>( Hashable &a, Hashable &b );
678 669
679#endif 670#endif
diff --git a/src/tests/fstring.cpp b/src/tests/fstring.cpp
index cb85282..33e24b4 100644
--- a/src/tests/fstring.cpp
+++ b/src/tests/fstring.cpp
@@ -1,3 +1,4 @@
1#include "hash.h"
1#include "fstring.h" 2#include "fstring.h"
2 3
3FString genThing() 4FString genThing()
@@ -11,6 +12,11 @@ FString genThing()
11 return bob; 12 return bob;
12} 13}
13 14
15void thing( FString str )
16{
17 printf("Hey: %s\n", str.c_str() );
18}
19
14#define pem printf("---------\n%08X: %s\n%08X: %s\n", (unsigned int)str.c_str(), str.c_str(), (unsigned int)str2.c_str(), str2.c_str() ); 20#define pem printf("---------\n%08X: %s\n%08X: %s\n", (unsigned int)str.c_str(), str.c_str(), (unsigned int)str2.c_str(), str2.c_str() );
15int main( int argc, char *argv ) 21int main( int argc, char *argv )
16{ 22{
@@ -33,5 +39,9 @@ int main( int argc, char *argv )
33 39
34 str = str2; 40 str = str2;
35 pem; 41 pem;
42
43 thing( str2 );
44
45 printf("%d == %d\n", __calcHashCode( str ), __calcHashCode( str.c_str() ) );
36} 46}
37 47