diff options
author | Mike Buland <eichlan@xagasoft.com> | 2006-11-21 12:23:13 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2006-11-21 12:23:13 +0000 |
commit | 4b8bad3d711f39db84f094edf83c5496a3f02cd6 (patch) | |
tree | bbaf654af3e82e67544ae17f07b7fbe7d02ce0ec /src | |
parent | 737b1aee54da9ff45a4fb6eb7e636eff9019128e (diff) | |
download | libbu++-4b8bad3d711f39db84f094edf83c5496a3f02cd6.tar.gz libbu++-4b8bad3d711f39db84f094edf83c5496a3f02cd6.tar.bz2 libbu++-4b8bad3d711f39db84f094edf83c5496a3f02cd6.tar.xz libbu++-4b8bad3d711f39db84f094edf83c5496a3f02cd6.zip |
Wow, craziness. Part way through working on the confpair system I got some
sudden insperation and completely redid Hash. Now everything but delete is
implemented, including typesafe iterators and more. It's really cool, and
everyone should check it out and start using it right away!
Diffstat (limited to '')
-rw-r--r-- | src/confpair.h | 48 | ||||
-rw-r--r-- | src/confpairbase.cpp | 17 | ||||
-rw-r--r-- | src/confpairbase.h | 24 | ||||
-rw-r--r-- | src/hash.cpp | 80 | ||||
-rw-r--r-- | src/hash.h | 447 | ||||
-rw-r--r-- | src/hashable.h | 5 | ||||
-rw-r--r-- | src/staticstring.cpp | 20 | ||||
-rw-r--r-- | src/staticstring.h | 5 | ||||
-rw-r--r-- | src/tests/confpair.cpp | 11 | ||||
-rw-r--r-- | src/tests/hash.cpp | 77 |
10 files changed, 662 insertions, 72 deletions
diff --git a/src/confpair.h b/src/confpair.h index 5be33c8..56eb06e 100644 --- a/src/confpair.h +++ b/src/confpair.h | |||
@@ -3,11 +3,14 @@ | |||
3 | 3 | ||
4 | #include <stdint.h> | 4 | #include <stdint.h> |
5 | #include <string> | 5 | #include <string> |
6 | #include <sstream> | ||
7 | #include "confpairbase.h" | ||
8 | |||
6 | /** | 9 | /** |
7 | * | 10 | * |
8 | */ | 11 | */ |
9 | template<class T> | 12 | template<class T> |
10 | class ConfPair | 13 | class ConfPair : public ConfPairBase |
11 | { | 14 | { |
12 | public: | 15 | public: |
13 | ConfPair( const std::string &sName ) : | 16 | ConfPair( const std::string &sName ) : |
@@ -27,9 +30,52 @@ public: | |||
27 | return sName; | 30 | return sName; |
28 | } | 31 | } |
29 | 32 | ||
33 | virtual void setFromString( const std::string &sStr ) | ||
34 | { | ||
35 | std::stringstream(sStr) >> tValue; | ||
36 | } | ||
37 | |||
38 | virtual std::string getAsString() | ||
39 | { | ||
40 | std::stringstream tmp; | ||
41 | tmp << tValue; | ||
42 | return tmp.str(); | ||
43 | } | ||
44 | |||
30 | private: | 45 | private: |
31 | std::string sName; | 46 | std::string sName; |
32 | T tValue; | 47 | T tValue; |
33 | }; | 48 | }; |
34 | 49 | ||
50 | template<> | ||
51 | void ConfPair<std::string>::setFromString( const std::string &sStr ) | ||
52 | { | ||
53 | tValue = sStr; | ||
54 | } | ||
55 | |||
56 | template<> | ||
57 | std::string ConfPair<std::string>::getAsString() | ||
58 | { | ||
59 | return tValue; | ||
60 | } | ||
61 | |||
62 | template<> | ||
63 | void ConfPair<bool>::setFromString( const std::string &sStr ) | ||
64 | { | ||
65 | if( !strcasecmp( sStr.c_str(), "true" ) || | ||
66 | !strcasecmp( sStr.c_str(), "yes" ) || | ||
67 | !strcasecmp( sStr.c_str(), "on" ) ) | ||
68 | tValue = true; | ||
69 | else | ||
70 | tValue = false; | ||
71 | } | ||
72 | |||
73 | template<> | ||
74 | std::string ConfPair<bool>::getAsString() | ||
75 | { | ||
76 | if( tValue == true ) | ||
77 | return "True"; | ||
78 | return "False"; | ||
79 | } | ||
80 | |||
35 | #endif | 81 | #endif |
diff --git a/src/confpairbase.cpp b/src/confpairbase.cpp new file mode 100644 index 0000000..1203dc0 --- /dev/null +++ b/src/confpairbase.cpp | |||
@@ -0,0 +1,17 @@ | |||
1 | #include "confpairbase.h" | ||
2 | |||
3 | ConfPairBase::ConfPairBase() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | ConfPairBase::~ConfPairBase() | ||
8 | { | ||
9 | } | ||
10 | |||
11 | ConfPairBase &ConfPairBase::operator=( const std::string &s ) | ||
12 | { | ||
13 | setFromString( s ); | ||
14 | |||
15 | return *this; | ||
16 | } | ||
17 | |||
diff --git a/src/confpairbase.h b/src/confpairbase.h new file mode 100644 index 0000000..2530756 --- /dev/null +++ b/src/confpairbase.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef CONF_PAIR_BASE_H | ||
2 | #define CONF_PAIR_BASE_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <string> | ||
6 | #include <ostream> | ||
7 | #include <istream> | ||
8 | |||
9 | class ConfPairBase | ||
10 | { | ||
11 | public: | ||
12 | ConfPairBase(); | ||
13 | virtual ~ConfPairBase(); | ||
14 | |||
15 | virtual void setFromString( const std::string &sStr )=0; | ||
16 | virtual std::string getAsString()=0; | ||
17 | |||
18 | ConfPairBase &operator=( const std::string &s ); | ||
19 | |||
20 | private: | ||
21 | |||
22 | }; | ||
23 | |||
24 | #endif | ||
diff --git a/src/hash.cpp b/src/hash.cpp index b4aac77..14be208 100644 --- a/src/hash.cpp +++ b/src/hash.cpp | |||
@@ -1 +1,81 @@ | |||
1 | #include "hash.h" | 1 | #include "hash.h" |
2 | |||
3 | template<> | ||
4 | uint32_t __calcHashCode<const char *>( const char * k ) | ||
5 | { | ||
6 | if (k == NULL) | ||
7 | { | ||
8 | return 0; | ||
9 | } | ||
10 | |||
11 | unsigned long int nPos = 0; | ||
12 | for( const char *s = k; *s; s++ ) | ||
13 | { | ||
14 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | ||
15 | } | ||
16 | |||
17 | return nPos; | ||
18 | } | ||
19 | |||
20 | template<> bool __cmpHashKeys<const char *>( const char *a, const char *b ) | ||
21 | { | ||
22 | if( a == b ) | ||
23 | return true; | ||
24 | |||
25 | for(; *a != *b; a++, b++ ) | ||
26 | if( *a == '\0' && *b == '\0' ) | ||
27 | return true; | ||
28 | |||
29 | return false; | ||
30 | } | ||
31 | |||
32 | template<> | ||
33 | uint32_t __calcHashCode<char *>( char *k ) | ||
34 | { | ||
35 | return __calcHashCode<const char *>((const char *)k ); | ||
36 | } | ||
37 | |||
38 | template<> bool __cmpHashKeys<char *>( char *a, char *b ) | ||
39 | { | ||
40 | return __cmpHashKeys<const char *>((const char *)a, (const char *)b ); | ||
41 | } | ||
42 | |||
43 | template<> uint32_t __calcHashCode<const std::string>( const std::string k ) | ||
44 | { | ||
45 | std::string::size_type j, sz = k.size(); | ||
46 | const char *s = k.c_str(); | ||
47 | |||
48 | unsigned long int nPos = 0; | ||
49 | for( j = 0; j < sz; j++, s++ ) | ||
50 | { | ||
51 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | ||
52 | } | ||
53 | |||
54 | return nPos; | ||
55 | } | ||
56 | |||
57 | template<> bool __cmpHashKeys<const std::string>( const std::string a, const std::string b ) | ||
58 | { | ||
59 | return a == b; | ||
60 | } | ||
61 | |||
62 | template<> uint32_t __calcHashCode<std::string>( std::string k ) | ||
63 | { | ||
64 | return __calcHashCode<const std::string>( k ); | ||
65 | } | ||
66 | |||
67 | template<> bool __cmpHashKeys<std::string>( std::string a, std::string b ) | ||
68 | { | ||
69 | return __cmpHashKeys<const std::string>( a, b ); | ||
70 | } | ||
71 | |||
72 | template<> uint32_t __calcHashCode<Hashable &>( Hashable &k ) | ||
73 | { | ||
74 | return k.getHashCode(); | ||
75 | } | ||
76 | |||
77 | template<> bool __cmpHashKeys<Hashable &>( Hashable &a, Hashable &b ) | ||
78 | { | ||
79 | return a.compareForHash( b ); | ||
80 | } | ||
81 | |||
@@ -1,106 +1,431 @@ | |||
1 | #ifndef HASH_H | 1 | #ifndef HASH_H |
2 | #define HASH_H | 2 | #define HASH_H |
3 | /* | 3 | |
4 | #include <stddef.h> | 4 | #include <stddef.h> |
5 | #include <string.h> | 5 | #include <string.h> |
6 | #include <memory> | ||
7 | #include <iostream> | ||
6 | #include "hashable.h" | 8 | #include "hashable.h" |
7 | 9 | ||
8 | #define bitsToBytes( n ) (n/8+(n%8>0 ? 1 : 0)) | 10 | #define bitsToBytes( n ) (n/32+(n%32>0 ? 1 : 0)) |
11 | |||
12 | template<typename T> | ||
13 | uint32_t __calcHashCode( T k ); | ||
14 | |||
15 | template<typename T> | ||
16 | bool __cmpHashKeys( T a, T b ); | ||
17 | |||
18 | struct __calcNextTSize_fast | ||
19 | { | ||
20 | uint32_t operator()( uint32_t nCapacity, uint32_t nFill, uint32_t nDeleted ) const | ||
21 | { | ||
22 | return nCapacity*2+1; | ||
23 | } | ||
24 | }; | ||
25 | |||
26 | template<typename key, typename value, typename sizecalc = __calcNextTSize_fast, typename keyalloc = std::allocator<key>, typename valuealloc = std::allocator<value>, typename challoc = std::allocator<uint32_t> > | ||
27 | class Hash; | ||
28 | |||
29 | template< typename key, typename value, typename sizecalc, typename keyalloc, typename valuealloc, typename challoc > | ||
30 | struct HashProxy | ||
31 | { | ||
32 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | ||
33 | private: | ||
34 | HashProxy( Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &h, key k, value v ) : | ||
35 | hsh( h ), | ||
36 | tKey( k ), | ||
37 | tValue( v ), | ||
38 | bFilled( true ) | ||
39 | { | ||
40 | } | ||
41 | |||
42 | HashProxy( Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &h, key k ) : | ||
43 | hsh( h ), | ||
44 | tKey( k ), | ||
45 | bFilled( false ) | ||
46 | { | ||
47 | } | ||
48 | |||
49 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &hsh; | ||
50 | key tKey; | ||
51 | value tValue; | ||
52 | bool bFilled; | ||
53 | |||
54 | public: | ||
55 | operator value() | ||
56 | { | ||
57 | if( bFilled == false ) | ||
58 | throw "Nope, no data there"; | ||
59 | return tValue; | ||
60 | } | ||
9 | 61 | ||
10 | template<class key, class value> | 62 | value operator=( value nval ) |
63 | { | ||
64 | hsh.insert( tKey, nval ); | ||
65 | return nval; | ||
66 | } | ||
67 | |||
68 | }; | ||
69 | |||
70 | template<typename key, typename value, typename sizecalc, typename keyalloc, typename valuealloc, typename challoc > | ||
11 | class Hash | 71 | class Hash |
12 | { | 72 | { |
13 | class iterator | 73 | public: |
74 | Hash() : | ||
75 | nCapacity( 11 ), | ||
76 | nFilled( 0 ), | ||
77 | nDeleted( 0 ), | ||
78 | bFilled( NULL ), | ||
79 | aKeys( NULL ), | ||
80 | aValues( NULL ), | ||
81 | aHashCodes( NULL ) | ||
14 | { | 82 | { |
15 | friend class Hash<key, value>; | 83 | nKeysSize = bitsToBytes( nCapacity ); |
16 | private: | 84 | bFilled = ca.allocate( nKeysSize ); |
17 | iterator( Hash<key, value> *hsh, int nIndex, key keyval, bool bInsert ) : | 85 | bDeleted = ca.allocate( nKeysSize ); |
18 | hsh( hsh ), | 86 | clearBits(); |
19 | nIndex( nIndex ), | 87 | |
20 | keyval( keyval ), | 88 | aHashCodes = ca.allocate( nCapacity ); |
21 | bInsert( bInsert ) | 89 | aKeys = ka.allocate( nCapacity ); |
90 | aValues = va.allocate( nCapacity ); | ||
91 | } | ||
92 | |||
93 | virtual ~Hash() | ||
94 | { | ||
95 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
22 | { | 96 | { |
97 | if( isFilled( j ) ) | ||
98 | { | ||
99 | va.destroy( &aValues[j] ); | ||
100 | ka.destroy( &aKeys[j] ); | ||
101 | } | ||
23 | } | 102 | } |
103 | va.deallocate( aValues, nCapacity ); | ||
104 | ka.deallocate( aKeys, nCapacity ); | ||
105 | ca.deallocate( bFilled, nKeysSize ); | ||
106 | ca.deallocate( bDeleted, nKeysSize ); | ||
107 | ca.deallocate( aHashCodes, nCapacity ); | ||
108 | } | ||
24 | 109 | ||
25 | public: | 110 | void clearBits() |
26 | iterator() : | 111 | { |
27 | hsh( NULL ), | 112 | for( uint32_t j = 0; j < nKeysSize; j++ ) |
28 | nIndex( -1 ) | ||
29 | { | 113 | { |
114 | bFilled[j] = bDeleted[j] = 0; | ||
30 | } | 115 | } |
116 | } | ||
117 | |||
118 | int hasKey( key keyval ) | ||
119 | { | ||
120 | printf("%s\n", keyval ); | ||
121 | } | ||
122 | |||
123 | uint32_t getCapacity() | ||
124 | { | ||
125 | return nCapacity; | ||
126 | } | ||
127 | |||
128 | uint32_t getFill() | ||
129 | { | ||
130 | return nFilled; | ||
131 | } | ||
132 | |||
133 | uint32_t getDeleted() | ||
134 | { | ||
135 | return nDeleted; | ||
136 | } | ||
137 | |||
138 | HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc> operator[]( key k ) | ||
139 | { | ||
140 | uint32_t hash = __calcHashCode( k ); | ||
141 | bool bFill; | ||
142 | uint32_t nPos = probe( hash, k, bFill ); | ||
31 | 143 | ||
32 | iterator &operator=( iterator &src ) | 144 | if( bFill ) |
33 | { | 145 | { |
34 | this->hsh = src.hsh; | 146 | return HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc>( *this, aKeys[nPos], aValues[nPos] ); |
35 | this->nIndex = src.nIndex; | ||
36 | } | 147 | } |
148 | else | ||
149 | { | ||
150 | return HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc>( *this, k ); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | void insert( key k, value v ) | ||
155 | { | ||
156 | uint32_t hash = __calcHashCode( k ); | ||
157 | bool bFill; | ||
158 | uint32_t nPos = probe( hash, k, bFill ); | ||
37 | 159 | ||
38 | iterator &operator=( value &src ) | 160 | if( bFill ) |
39 | { | 161 | { |
40 | if( bInsert ) | 162 | va.destroy( &aValues[nPos] ); |
41 | printf("You wanted to insert %d\n", src ); | 163 | va.construct( &aValues[nPos], v ); |
42 | else | 164 | } |
43 | printf("You wanted to insert %d\n", src ); | 165 | else |
166 | { | ||
167 | va.construct( &aValues[nPos], v ); | ||
168 | ka.construct( &aKeys[nPos], k ); | ||
169 | fill( nPos ); | ||
170 | aHashCodes[nPos] = hash; | ||
171 | nFilled++; | ||
44 | } | 172 | } |
173 | } | ||
45 | 174 | ||
46 | private: | 175 | value get( key k ) |
47 | Hash<key, value> *hsh; | 176 | { |
48 | int nIndex; | 177 | uint32_t hash = __calcHashCode( k ); |
49 | bool bInsert; | 178 | bool bFill; |
50 | key keyval; | 179 | uint32_t nPos = probe( hash, k, bFill ); |
51 | }; | 180 | |
181 | if( bFill ) | ||
182 | { | ||
183 | return aValues[nPos]; | ||
184 | } | ||
185 | else | ||
186 | { | ||
187 | throw "Hey, no such thing..."; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | uint32_t probe( uint32_t hash, key k, bool &bFill, bool rehash=true ) | ||
192 | { | ||
193 | uint32_t nCur = hash%nCapacity; | ||
194 | |||
195 | // First we scan to see if the key is already there, abort if we | ||
196 | // run out of probing room, or we find a non-filled entry | ||
197 | for( int8_t j = 0; | ||
198 | isFilled( nCur ) && j < 32; | ||
199 | nCur = (nCur + (1<<j))%nCapacity, j++ | ||
200 | ) | ||
201 | { | ||
202 | // Is this the same hash code we were looking for? | ||
203 | if( hash == aHashCodes[nCur] ) | ||
204 | { | ||
205 | // Is it really the same key? (for safety) | ||
206 | if( __cmpHashKeys( aKeys[nCur], k ) == true && | ||
207 | isDeleted( nCur ) == false ) | ||
208 | { | ||
209 | bFill = true; | ||
210 | return nCur; | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||
215 | // This is our insurance, if the table is full, then go ahead and | ||
216 | // rehash, then try again. | ||
217 | if( isFilled( nCur ) && rehash == true ) | ||
218 | { | ||
219 | reHash( szCalc(getCapacity(), getFill(), getDeleted()) ); | ||
220 | |||
221 | // This is potentially dangerous, and could cause an infinite loop. | ||
222 | // Be careful writing probe, eh? | ||
223 | return probe( hash, k, bFill ); | ||
224 | } | ||
225 | |||
226 | bFill = false; | ||
227 | return nCur; | ||
228 | } | ||
229 | |||
230 | void reHash( uint32_t nNewSize ) | ||
231 | { | ||
232 | // Save all the old data | ||
233 | uint32_t nOldCapacity = nCapacity; | ||
234 | uint32_t *bOldFilled = bFilled; | ||
235 | uint32_t *aOldHashCodes = aHashCodes; | ||
236 | uint32_t nOldKeysSize = nKeysSize; | ||
237 | uint32_t *bOldDeleted = bDeleted; | ||
238 | value *aOldValues = aValues; | ||
239 | key *aOldKeys = aKeys; | ||
240 | |||
241 | // Calculate new sizes | ||
242 | nCapacity = nNewSize; | ||
243 | nKeysSize = bitsToBytes( nCapacity ); | ||
244 | |||
245 | // Allocate new memory + prep | ||
246 | bFilled = ca.allocate( nKeysSize ); | ||
247 | bDeleted = ca.allocate( nKeysSize ); | ||
248 | clearBits(); | ||
249 | |||
250 | aHashCodes = ca.allocate( nCapacity ); | ||
251 | aKeys = ka.allocate( nCapacity ); | ||
252 | aValues = va.allocate( nCapacity ); | ||
253 | |||
254 | // Re-insert all of the old data (except deleted items) | ||
255 | for( uint32_t j = 0; j < nOldCapacity; j++ ) | ||
256 | { | ||
257 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 ) | ||
258 | { | ||
259 | insert( aOldKeys[j], aOldValues[j] ); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | // Delete all of the old data | ||
264 | for( uint32_t j = 0; j < nOldCapacity; j++ ) | ||
265 | { | ||
266 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 ) | ||
267 | { | ||
268 | va.destroy( &aOldValues[j] ); | ||
269 | ka.destroy( &aOldKeys[j] ); | ||
270 | } | ||
271 | } | ||
272 | va.deallocate( aOldValues, nOldCapacity ); | ||
273 | ka.deallocate( aOldKeys, nOldCapacity ); | ||
274 | ca.deallocate( bOldFilled, nOldKeysSize ); | ||
275 | ca.deallocate( bOldDeleted, nOldKeysSize ); | ||
276 | ca.deallocate( aOldHashCodes, nOldCapacity ); | ||
277 | } | ||
52 | 278 | ||
53 | template<class refval> | 279 | void fill( uint32_t loc ) |
54 | class VRef | ||
55 | { | 280 | { |
281 | bFilled[loc/32] |= (1<<(loc%32)); | ||
282 | } | ||
283 | |||
284 | bool isFilled( uint32_t loc ) | ||
285 | { | ||
286 | return (bFilled[loc/32]&(1<<(loc%32)))!=0; | ||
287 | } | ||
288 | |||
289 | bool isDeleted( uint32_t loc ) | ||
290 | { | ||
291 | return (bDeleted[loc/32]&(1<<(loc%32)))!=0; | ||
292 | } | ||
293 | |||
294 | typedef struct iterator | ||
295 | { | ||
296 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | ||
297 | private: | ||
298 | iterator( Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &hsh ) : | ||
299 | hsh( hsh ), | ||
300 | bFinished( false ), | ||
301 | nPos( 0 ) | ||
302 | { | ||
303 | nPos = hsh.getFirstPos( bFinished ); | ||
304 | } | ||
305 | |||
306 | iterator( Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &hsh, bool bDone ) : | ||
307 | hsh( hsh ), | ||
308 | nPos( 0 ), | ||
309 | bFinished( bDone ) | ||
310 | { | ||
311 | } | ||
312 | |||
313 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &hsh; | ||
314 | |||
315 | uint32_t nPos; | ||
316 | bool bFinished; | ||
317 | |||
56 | public: | 318 | public: |
57 | VRef( refval &data ) : | 319 | iterator operator++( int ) |
58 | data( data ) | ||
59 | { | 320 | { |
321 | if( bFinished == false ) | ||
322 | nPos = hsh.getNextPos( nPos, bFinished ); | ||
323 | |||
324 | return *this; | ||
325 | } | ||
326 | |||
327 | iterator operator++() | ||
328 | { | ||
329 | if( bFinished == false ) | ||
330 | nPos = hsh.getNextPos( nPos, bFinished ); | ||
331 | |||
332 | return *this; | ||
333 | } | ||
334 | |||
335 | bool operator==( const iterator &oth ) | ||
336 | { | ||
337 | if( bFinished != oth.bFinished ) | ||
338 | return false; | ||
339 | if( bFinished == true ) | ||
340 | { | ||
341 | return true; | ||
342 | } | ||
343 | else | ||
344 | { | ||
345 | if( oth.nPos == nPos ) | ||
346 | return true; | ||
347 | return false; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | bool operator!=( const iterator &oth ) | ||
352 | { | ||
353 | return !(*this == oth ); | ||
354 | } | ||
355 | |||
356 | std::pair<key,value> operator *() | ||
357 | { | ||
358 | return hsh.getAtPos( nPos ); | ||
60 | } | 359 | } |
61 | refval &data; | ||
62 | }; | 360 | }; |
63 | 361 | ||
64 | public: | 362 | iterator begin() |
65 | Hash() : | ||
66 | nCapacity( 11 ), | ||
67 | nFilled( 0 ), | ||
68 | bFilled( NULL ), | ||
69 | aKeys( NULL ), | ||
70 | aValues( NULL ), | ||
71 | aHashCodes( NULL ) | ||
72 | { | 363 | { |
73 | int nKeysSize = bitsToBytes( nCapacity ); | 364 | return iterator( *this ); |
74 | bFilled = new unsigned char[ nKeysSize ]; | 365 | } |
75 | memset( bFilled, 0, nKeysSize ); | 366 | |
76 | 367 | iterator end() | |
77 | aKeys = new VRef<key>*[nCapacity]; | 368 | { |
78 | aValues = new value[nCapacity]; | 369 | return iterator( *this, true ); |
79 | } | 370 | } |
80 | 371 | ||
81 | virtual ~Hash() | 372 | private: |
373 | std::pair<key,value> getAtPos( uint32_t nPos ) | ||
82 | { | 374 | { |
375 | return std::pair<key,value>(aKeys[nPos],aValues[nPos]); | ||
83 | } | 376 | } |
84 | 377 | ||
85 | iterator operator[]( key keyval ) | 378 | uint32_t getFirstPos( bool &bFinished ) |
86 | { | 379 | { |
87 | //iterator i( this, 4, keyval, true ); | 380 | for( uint32_t j = 0; j < nCapacity; j++ ) |
88 | //return i; | 381 | { |
89 | printf("%s\n", keyval.getString() ); | 382 | if( isFilled( j ) ) |
383 | return j; | ||
384 | } | ||
385 | |||
386 | bFinished = true; | ||
90 | } | 387 | } |
91 | 388 | ||
92 | int hasKey( key keyval ) | 389 | uint32_t getNextPos( uint32_t nPos, bool &bFinished ) |
93 | { | 390 | { |
94 | printf("%s\n", keyval.getString() ); | 391 | for( uint32_t j = nPos+1; j < nCapacity; j++ ) |
392 | { | ||
393 | if( isFilled( j ) ) | ||
394 | return j; | ||
395 | } | ||
396 | |||
397 | bFinished = true; | ||
95 | } | 398 | } |
96 | 399 | ||
97 | private: | 400 | private: |
98 | int nCapacity; | 401 | uint32_t nCapacity; |
99 | int nFilled; | 402 | uint32_t nFilled; |
100 | unsigned char *bFilled; | 403 | uint32_t nDeleted; |
101 | VRef<key> **aKeys; | 404 | uint32_t *bFilled; |
102 | unsigned long int *aHashCodes; | 405 | uint32_t *bDeleted; |
406 | uint32_t *aHashCodes; | ||
407 | uint32_t nKeysSize; | ||
103 | value *aValues; | 408 | value *aValues; |
409 | key *aKeys; | ||
410 | valuealloc va; | ||
411 | keyalloc ka; | ||
412 | challoc ca; | ||
413 | sizecalc szCalc; | ||
104 | }; | 414 | }; |
105 | */ | 415 | |
416 | template<> uint32_t __calcHashCode<const char *>( const char *k ); | ||
417 | template<> bool __cmpHashKeys<const char *>( const char *a, const char *b ); | ||
418 | |||
419 | template<> uint32_t __calcHashCode<char *>( char *k ); | ||
420 | template<> bool __cmpHashKeys<char *>( char *a, char *b ); | ||
421 | |||
422 | template<> uint32_t __calcHashCode<const std::string>( const std::string k ); | ||
423 | template<> bool __cmpHashKeys<const std::string>( const std::string a, const std::string b ); | ||
424 | |||
425 | template<> uint32_t __calcHashCode<std::string>( std::string k ); | ||
426 | template<> bool __cmpHashKeys<std::string>( std::string a, std::string b ); | ||
427 | |||
428 | template<> uint32_t __calcHashCode<Hashable &>( Hashable &k ); | ||
429 | template<> bool __cmpHashKeys<Hashable &>( Hashable &a, Hashable &b ); | ||
430 | |||
106 | #endif | 431 | #endif |
diff --git a/src/hashable.h b/src/hashable.h index 33ff8b8..ce49130 100644 --- a/src/hashable.h +++ b/src/hashable.h | |||
@@ -1,10 +1,11 @@ | |||
1 | #ifndef HASHABLE_H | 1 | #ifndef HASHABLE_H |
2 | #define HASHABLE_H | 2 | #define HASHABLE_H |
3 | /* | 3 | |
4 | class Hashable | 4 | class Hashable |
5 | { | 5 | { |
6 | public: | 6 | public: |
7 | virtual unsigned long int getHashCode() = 0; | 7 | virtual unsigned long int getHashCode() = 0; |
8 | virtual bool compareForHash( Hashable &other ) = 0; | ||
8 | }; | 9 | }; |
9 | */ | 10 | |
10 | #endif | 11 | #endif |
diff --git a/src/staticstring.cpp b/src/staticstring.cpp index 9eac92e..0012b0f 100644 --- a/src/staticstring.cpp +++ b/src/staticstring.cpp | |||
@@ -243,10 +243,28 @@ bool StaticString::operator!=( StaticString &str ) | |||
243 | unsigned long int StaticString::getHashCode() | 243 | unsigned long int StaticString::getHashCode() |
244 | { | 244 | { |
245 | unsigned long int nPos = nLen; | 245 | unsigned long int nPos = nLen; |
246 | for( const char *s = (const char *)lpStr; *s; s++ ) | 246 | unsigned long int j = 0; |
247 | for( const char *s = (const char *)lpStr; j< nLen; s++, j++ ) | ||
247 | { | 248 | { |
248 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | 249 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; |
249 | } | 250 | } |
250 | return nPos; | 251 | return nPos; |
251 | } | 252 | } |
252 | 253 | ||
254 | bool StaticString::compareForHash( Hashable &other ) | ||
255 | { | ||
256 | if( ((StaticString &)other).nLen != nLen ) | ||
257 | return false; | ||
258 | |||
259 | const char *a = ((StaticString &)other).lpStr; | ||
260 | const char *b = lpStr; | ||
261 | if( a == b ) | ||
262 | return true; | ||
263 | |||
264 | for( unsigned long j = 0; j < nLen; j++, a++, b++ ) | ||
265 | if( *a != *b ) | ||
266 | return false; | ||
267 | |||
268 | return true; | ||
269 | } | ||
270 | |||
diff --git a/src/staticstring.h b/src/staticstring.h index 61501bf..1ff3f63 100644 --- a/src/staticstring.h +++ b/src/staticstring.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | #include <string> | 4 | #include <string> |
5 | #include "serializable.h" | 5 | #include "serializable.h" |
6 | //#include "hashable.h" | 6 | #include "hashable.h" |
7 | 7 | ||
8 | /** | 8 | /** |
9 | * Simple string managing class. Allows for dynamically allocated string data | 9 | * Simple string managing class. Allows for dynamically allocated string data |
@@ -12,7 +12,7 @@ | |||
12 | * and making accessing meta-info like length fast and reliable as well. | 12 | * and making accessing meta-info like length fast and reliable as well. |
13 | *@author Mike Buland | 13 | *@author Mike Buland |
14 | */ | 14 | */ |
15 | class StaticString : public Serializable//, public Hashable | 15 | class StaticString : public Serializable, public Hashable |
16 | { | 16 | { |
17 | public: | 17 | public: |
18 | StaticString(); | 18 | StaticString(); |
@@ -51,6 +51,7 @@ public: | |||
51 | virtual void serialize( class Serializer &ar ); | 51 | virtual void serialize( class Serializer &ar ); |
52 | 52 | ||
53 | virtual unsigned long int getHashCode(); | 53 | virtual unsigned long int getHashCode(); |
54 | virtual bool compareForHash( Hashable &other ); | ||
54 | 55 | ||
55 | private: | 56 | private: |
56 | char *lpStr; | 57 | char *lpStr; |
diff --git a/src/tests/confpair.cpp b/src/tests/confpair.cpp index 8e03730..fb1b0d3 100644 --- a/src/tests/confpair.cpp +++ b/src/tests/confpair.cpp | |||
@@ -5,10 +5,15 @@ using namespace std; | |||
5 | 5 | ||
6 | int main() | 6 | int main() |
7 | { | 7 | { |
8 | ConfPair<bool> p1("DebugMode"); | 8 | ConfPair<float> p1("DebugMode"); |
9 | p1.value() = true; | 9 | p1.value() = 12; |
10 | cout << p1.value() << "\n"; | 10 | cout << p1.value() << "\n"; |
11 | p1.value() = false; | 11 | p1.value() = 55; |
12 | cout << p1.value() << "\n"; | 12 | cout << p1.value() << "\n"; |
13 | |||
14 | ConfPairBase &p = p1; | ||
15 | |||
16 | p = "33.12"; | ||
17 | cout << p.getAsString(); | ||
13 | } | 18 | } |
14 | 19 | ||
diff --git a/src/tests/hash.cpp b/src/tests/hash.cpp index d0f5fa6..8406439 100644 --- a/src/tests/hash.cpp +++ b/src/tests/hash.cpp | |||
@@ -3,8 +3,81 @@ | |||
3 | 3 | ||
4 | int main() | 4 | int main() |
5 | { | 5 | { |
6 | //Hash<class StaticString, int> sTest; | 6 | const char *names[]={ |
7 | "Homer the Great", | ||
8 | "And Maggie Makes Three", | ||
9 | "Bart's Comet", | ||
10 | "Homie The Clown", | ||
11 | "Bart Vs Australia", | ||
12 | "Homer vs Patty and Selma", | ||
13 | "A star is burns", | ||
14 | "Lisa's Wedding", | ||
15 | "Two Dozen and One Greyhounds", | ||
16 | "The PTA Disbands", | ||
17 | "Round Springfield", | ||
18 | "The Springfield connection", | ||
19 | "Lemon of Troy", | ||
20 | "Who Shot Mr. Burns (Pt. 1)", | ||
21 | "Who Shot Mr. Burns (pt. 2)", | ||
22 | "Radioactive Man", | ||
23 | "Home Sweet Homediddly-dum-doodly", | ||
24 | "Bart Sells His Soul", | ||
25 | "Lisa the Vegetarian", | ||
26 | "Treehouse of horror VI", | ||
27 | "King Size Homer", | ||
28 | "Mother Simpson", | ||
29 | "Sideshow Bob's Last Gleaming", | ||
30 | "The Simpson's 138th Show Spectacular", | ||
31 | "Marge Be Not Proud", | ||
32 | "Team Homer", | ||
33 | "Two Bad Neighbors", | ||
34 | "Scenes From the Class Struggle in Springfield", | ||
35 | "Bart the Fink", | ||
36 | "Lisa the Iconoclast", | ||
37 | "Homer the Smithers", | ||
38 | "The Day the Violence Died", | ||
39 | "A Fish Called Selma", | ||
40 | "Bart on the road", | ||
41 | "22 Short Films about Springfield", | ||
42 | "The Curse of the Flying Hellfish", | ||
43 | "Much Apu about Nothing", | ||
44 | "Homerpalooza", | ||
45 | "The Summer of 4 Ft 2", | ||
46 | "Treehouse of Horror VII", | ||
47 | "You Only Move Twice", | ||
48 | "The Homer They Fall", | ||
49 | "Burns Baby Burns", | ||
50 | "Bart After Dark", | ||
51 | "A Millhouse Divided", | ||
52 | "Lisas Date With Destiny", | ||
53 | "Hurricane Neddy", | ||
54 | "The Mysterious Voyage of Our Homer", | ||
55 | "The Springfield Files", | ||
56 | "The Twisted World of Marge Simpson", | ||
57 | "Mountain of Madness", | ||
58 | NULL | ||
59 | }; | ||
7 | 60 | ||
8 | //sTest.hasKey("hello"); | 61 | Hash<std::string, int> sTest; |
62 | |||
63 | printf("Inserting\n-------------------\n\n"); | ||
64 | for( int j = 0; j < 33; j++ ) | ||
65 | { | ||
66 | sTest[names[j]] = j; | ||
67 | } | ||
68 | |||
69 | printf("Getting\n-------------------\n\n"); | ||
70 | printf("%d\n", sTest.get( names[10] ) ); | ||
71 | printf("%d\n", (int)sTest[names[10]] ); | ||
72 | sTest[names[10]] = 22; | ||
73 | sTest["That one guy"] = 135; | ||
74 | printf("%d\n", (int)sTest[names[10]] ); | ||
75 | |||
76 | for( Hash<std::string, int>::iterator i = sTest.begin(); | ||
77 | i != sTest.end(); i++ ) | ||
78 | { | ||
79 | Hash<std::string, int>::iterator j = i; | ||
80 | printf("%d: %s\n", (*j).second, (*j).first.c_str() ); | ||
81 | } | ||
9 | } | 82 | } |
10 | 83 | ||