diff options
author | Mike Buland <eichlan@xagasoft.com> | 2007-04-03 04:50:36 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2007-04-03 04:50:36 +0000 |
commit | da89e6d30e57bd6dbb10b4d36b093ce9bbf5c666 (patch) | |
tree | 0c8d31d13521011dc52a3fbadbf9e7e27929308f | |
parent | f4c20290509d7ed3a8fd5304577e7a4cc0b9d974 (diff) | |
download | libbu++-da89e6d30e57bd6dbb10b4d36b093ce9bbf5c666.tar.gz libbu++-da89e6d30e57bd6dbb10b4d36b093ce9bbf5c666.tar.bz2 libbu++-da89e6d30e57bd6dbb10b4d36b093ce9bbf5c666.tar.xz libbu++-da89e6d30e57bd6dbb10b4d36b093ce9bbf5c666.zip |
The first batch seem to have made it alright. Unfortunately the Archive class
isn't done yet, I'm going to make it rely on streams, so those will be next,
then we can make it work all sortsa' well.
32 files changed, 1913 insertions, 1928 deletions
diff --git a/src/archable.cpp b/src/archable.cpp new file mode 100644 index 0000000..38fc31f --- /dev/null +++ b/src/archable.cpp | |||
@@ -0,0 +1,10 @@ | |||
1 | #include "archable.h" | ||
2 | |||
3 | Bu::Archable::Archable() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | Bu::Archable::~Archable() | ||
8 | { | ||
9 | } | ||
10 | |||
diff --git a/src/archable.h b/src/archable.h new file mode 100644 index 0000000..ed05a78 --- /dev/null +++ b/src/archable.h | |||
@@ -0,0 +1,35 @@ | |||
1 | #ifndef ARCHABLE_H | ||
2 | #define ARCHABLE_H | ||
3 | |||
4 | namespace Bu | ||
5 | { | ||
6 | /** | ||
7 | * The base class for any class you want to archive. Simply include this as | ||
8 | * a base class, implement the purely virtual archive function and you've | ||
9 | * got an easily archiveable class. | ||
10 | */ | ||
11 | class Archable | ||
12 | { | ||
13 | public: | ||
14 | /** | ||
15 | * Does nothing, here for completeness. | ||
16 | */ | ||
17 | Archable(); | ||
18 | |||
19 | /** | ||
20 | * Here to ensure the deconstructor is virtual. | ||
21 | */ | ||
22 | virtual ~Archable(); | ||
23 | |||
24 | /** | ||
25 | * This is the main workhorse of the archive system, just override and | ||
26 | * you've got a archiveable class. A reference to the Archive | ||
27 | * used is passed in as your only parameter, query it to discover if | ||
28 | * you are loading or saving. | ||
29 | * @param ar A reference to the Archive object to use. | ||
30 | */ | ||
31 | virtual void archive( class Archive &ar )=0; | ||
32 | }; | ||
33 | } | ||
34 | |||
35 | #endif | ||
diff --git a/src/old/serializer.cpp b/src/archive.cpp index 636224e..5f5145c 100644 --- a/src/old/serializer.cpp +++ b/src/archive.cpp | |||
@@ -1,152 +1,150 @@ | |||
1 | #include "serializer.h" | 1 | #include "archive.h" |
2 | #include "serializable.h" | ||
3 | #include <list> | ||
4 | 2 | ||
5 | Serializer::Serializer(bool bLoading): | 3 | Bu::Archive::Archive(bool bLoading): |
6 | bLoading(bLoading) | 4 | bLoading(bLoading) |
7 | { | 5 | { |
8 | } | 6 | } |
9 | Serializer::~Serializer() | 7 | Bu::Archive::~Archive() |
10 | { | 8 | { |
11 | } | 9 | } |
12 | 10 | ||
13 | bool Serializer::isLoading() | 11 | bool Bu::Archive::isLoading() |
14 | { | 12 | { |
15 | return bLoading; | 13 | return bLoading; |
16 | } | 14 | } |
17 | Serializer &Serializer::operator<<(bool p) | 15 | Bu::Archive &Bu::Archive::operator<<(bool p) |
18 | { | 16 | { |
19 | write( &p, sizeof(p) ); | 17 | write( &p, sizeof(p) ); |
20 | return *this; | 18 | return *this; |
21 | } | 19 | } |
22 | Serializer &Serializer::operator<<(int8_t p) | 20 | Bu::Archive &Bu::Archive::operator<<(int8_t p) |
23 | { | 21 | { |
24 | write( &p, sizeof(p) ); | 22 | write( &p, sizeof(p) ); |
25 | return *this; | 23 | return *this; |
26 | } | 24 | } |
27 | Serializer &Serializer::operator<<(int16_t p) | 25 | Bu::Archive &Bu::Archive::operator<<(int16_t p) |
28 | { | 26 | { |
29 | write( &p, sizeof(p) ); | 27 | write( &p, sizeof(p) ); |
30 | return *this; | 28 | return *this; |
31 | } | 29 | } |
32 | Serializer &Serializer::operator<<(int32_t p) | 30 | Bu::Archive &Bu::Archive::operator<<(int32_t p) |
33 | { | 31 | { |
34 | write( &p, sizeof(p) ); | 32 | write( &p, sizeof(p) ); |
35 | return *this; | 33 | return *this; |
36 | } | 34 | } |
37 | Serializer &Serializer::operator<<(int64_t p) | 35 | Bu::Archive &Bu::Archive::operator<<(int64_t p) |
38 | { | 36 | { |
39 | write( &p, sizeof(p) ); | 37 | write( &p, sizeof(p) ); |
40 | return *this; | 38 | return *this; |
41 | } | 39 | } |
42 | Serializer &Serializer::operator<<(uint8_t p) | 40 | Bu::Archive &Bu::Archive::operator<<(uint8_t p) |
43 | { | 41 | { |
44 | write( &p, sizeof(p) ); | 42 | write( &p, sizeof(p) ); |
45 | return *this; | 43 | return *this; |
46 | } | 44 | } |
47 | Serializer &Serializer::operator<<(uint16_t p) | 45 | Bu::Archive &Bu::Archive::operator<<(uint16_t p) |
48 | { | 46 | { |
49 | write( &p, sizeof(p) ); | 47 | write( &p, sizeof(p) ); |
50 | return *this; | 48 | return *this; |
51 | } | 49 | } |
52 | Serializer &Serializer::operator<<(uint32_t p) | 50 | Bu::Archive &Bu::Archive::operator<<(uint32_t p) |
53 | { | 51 | { |
54 | write( &p, sizeof(p) ); | 52 | write( &p, sizeof(p) ); |
55 | return *this; | 53 | return *this; |
56 | } | 54 | } |
57 | Serializer &Serializer::operator<<(uint64_t p) | 55 | Bu::Archive &Bu::Archive::operator<<(uint64_t p) |
58 | { | 56 | { |
59 | write( &p, sizeof(p) ); | 57 | write( &p, sizeof(p) ); |
60 | return *this; | 58 | return *this; |
61 | } | 59 | } |
62 | Serializer &Serializer::operator<<(long p) | 60 | Bu::Archive &Bu::Archive::operator<<(long p) |
63 | { | 61 | { |
64 | write( &p, sizeof(p) ); | 62 | write( &p, sizeof(p) ); |
65 | return *this; | 63 | return *this; |
66 | } | 64 | } |
67 | Serializer &Serializer::operator<<(float p) | 65 | Bu::Archive &Bu::Archive::operator<<(float p) |
68 | { | 66 | { |
69 | write( &p, sizeof(p) ); | 67 | write( &p, sizeof(p) ); |
70 | return *this; | 68 | return *this; |
71 | } | 69 | } |
72 | Serializer &Serializer::operator<<(double p) | 70 | Bu::Archive &Bu::Archive::operator<<(double p) |
73 | { | 71 | { |
74 | write( &p, sizeof(p) ); | 72 | write( &p, sizeof(p) ); |
75 | return *this; | 73 | return *this; |
76 | } | 74 | } |
77 | Serializer &Serializer::operator<<(long double p) | 75 | Bu::Archive &Bu::Archive::operator<<(long double p) |
78 | { | 76 | { |
79 | write( &p, sizeof(p) ); | 77 | write( &p, sizeof(p) ); |
80 | return *this; | 78 | return *this; |
81 | } | 79 | } |
82 | 80 | ||
83 | Serializer &Serializer::operator>>(bool &p) | 81 | Bu::Archive &Bu::Archive::operator>>(bool &p) |
84 | { | 82 | { |
85 | read( &p, sizeof(p) ); | 83 | read( &p, sizeof(p) ); |
86 | return *this; | 84 | return *this; |
87 | } | 85 | } |
88 | Serializer &Serializer::operator>>(int8_t &p) | 86 | Bu::Archive &Bu::Archive::operator>>(int8_t &p) |
89 | { | 87 | { |
90 | read( &p, sizeof(p) ); | 88 | read( &p, sizeof(p) ); |
91 | return *this; | 89 | return *this; |
92 | } | 90 | } |
93 | Serializer &Serializer::operator>>(int16_t &p) | 91 | Bu::Archive &Bu::Archive::operator>>(int16_t &p) |
94 | { | 92 | { |
95 | read( &p, sizeof(p) ); | 93 | read( &p, sizeof(p) ); |
96 | return *this; | 94 | return *this; |
97 | } | 95 | } |
98 | Serializer &Serializer::operator>>(int32_t &p) | 96 | Bu::Archive &Bu::Archive::operator>>(int32_t &p) |
99 | { | 97 | { |
100 | read( &p, sizeof(p) ); | 98 | read( &p, sizeof(p) ); |
101 | return *this; | 99 | return *this; |
102 | } | 100 | } |
103 | Serializer &Serializer::operator>>(int64_t &p) | 101 | Bu::Archive &Bu::Archive::operator>>(int64_t &p) |
104 | { | 102 | { |
105 | read( &p, sizeof(p) ); | 103 | read( &p, sizeof(p) ); |
106 | return *this; | 104 | return *this; |
107 | } | 105 | } |
108 | Serializer &Serializer::operator>>(uint8_t &p) | 106 | Bu::Archive &Bu::Archive::operator>>(uint8_t &p) |
109 | { | 107 | { |
110 | read( &p, sizeof(p) ); | 108 | read( &p, sizeof(p) ); |
111 | return *this; | 109 | return *this; |
112 | } | 110 | } |
113 | Serializer &Serializer::operator>>(uint16_t &p) | 111 | Bu::Archive &Bu::Archive::operator>>(uint16_t &p) |
114 | { | 112 | { |
115 | read( &p, sizeof(p) ); | 113 | read( &p, sizeof(p) ); |
116 | return *this; | 114 | return *this; |
117 | } | 115 | } |
118 | Serializer &Serializer::operator>>(uint32_t &p) | 116 | Bu::Archive &Bu::Archive::operator>>(uint32_t &p) |
119 | { | 117 | { |
120 | read( &p, sizeof(p) ); | 118 | read( &p, sizeof(p) ); |
121 | return *this; | 119 | return *this; |
122 | } | 120 | } |
123 | Serializer &Serializer::operator>>(uint64_t &p) | 121 | Bu::Archive &Bu::Archive::operator>>(uint64_t &p) |
124 | { | 122 | { |
125 | read( &p, sizeof(p) ); | 123 | read( &p, sizeof(p) ); |
126 | return *this; | 124 | return *this; |
127 | } | 125 | } |
128 | Serializer &Serializer::operator>>(long &p) | 126 | Bu::Archive &Bu::Archive::operator>>(long &p) |
129 | { | 127 | { |
130 | read( &p, sizeof(p) ); | 128 | read( &p, sizeof(p) ); |
131 | return *this; | 129 | return *this; |
132 | } | 130 | } |
133 | Serializer &Serializer::operator>>(float &p) | 131 | Bu::Archive &Bu::Archive::operator>>(float &p) |
134 | { | 132 | { |
135 | read( &p, sizeof(p) ); | 133 | read( &p, sizeof(p) ); |
136 | return *this; | 134 | return *this; |
137 | } | 135 | } |
138 | Serializer &Serializer::operator>>(double &p) | 136 | Bu::Archive &Bu::Archive::operator>>(double &p) |
139 | { | 137 | { |
140 | read( &p, sizeof(p) ); | 138 | read( &p, sizeof(p) ); |
141 | return *this; | 139 | return *this; |
142 | } | 140 | } |
143 | Serializer &Serializer::operator>>(long double &p) | 141 | Bu::Archive &Bu::Archive::operator>>(long double &p) |
144 | { | 142 | { |
145 | read( &p, sizeof(p) ); | 143 | read( &p, sizeof(p) ); |
146 | return *this; | 144 | return *this; |
147 | } | 145 | } |
148 | 146 | ||
149 | Serializer &Serializer::operator&&(bool &p) | 147 | Bu::Archive &Bu::Archive::operator&&(bool &p) |
150 | { | 148 | { |
151 | if (bLoading) | 149 | if (bLoading) |
152 | { | 150 | { |
@@ -158,7 +156,7 @@ Serializer &Serializer::operator&&(bool &p) | |||
158 | } | 156 | } |
159 | } | 157 | } |
160 | 158 | ||
161 | Serializer &Serializer::operator&&(int8_t &p) | 159 | Bu::Archive &Bu::Archive::operator&&(int8_t &p) |
162 | { | 160 | { |
163 | if (bLoading) | 161 | if (bLoading) |
164 | { | 162 | { |
@@ -170,7 +168,7 @@ Serializer &Serializer::operator&&(int8_t &p) | |||
170 | } | 168 | } |
171 | } | 169 | } |
172 | 170 | ||
173 | Serializer &Serializer::operator&&(int16_t &p) | 171 | Bu::Archive &Bu::Archive::operator&&(int16_t &p) |
174 | { | 172 | { |
175 | if (bLoading) | 173 | if (bLoading) |
176 | { | 174 | { |
@@ -182,7 +180,7 @@ Serializer &Serializer::operator&&(int16_t &p) | |||
182 | } | 180 | } |
183 | } | 181 | } |
184 | 182 | ||
185 | Serializer &Serializer::operator&&(int32_t &p) | 183 | Bu::Archive &Bu::Archive::operator&&(int32_t &p) |
186 | { | 184 | { |
187 | if (bLoading) | 185 | if (bLoading) |
188 | { | 186 | { |
@@ -194,7 +192,7 @@ Serializer &Serializer::operator&&(int32_t &p) | |||
194 | } | 192 | } |
195 | } | 193 | } |
196 | 194 | ||
197 | Serializer &Serializer::operator&&(int64_t &p) | 195 | Bu::Archive &Bu::Archive::operator&&(int64_t &p) |
198 | { | 196 | { |
199 | if (bLoading) | 197 | if (bLoading) |
200 | { | 198 | { |
@@ -206,7 +204,7 @@ Serializer &Serializer::operator&&(int64_t &p) | |||
206 | } | 204 | } |
207 | } | 205 | } |
208 | 206 | ||
209 | Serializer &Serializer::operator&&(uint8_t &p) | 207 | Bu::Archive &Bu::Archive::operator&&(uint8_t &p) |
210 | { | 208 | { |
211 | if (bLoading) | 209 | if (bLoading) |
212 | { | 210 | { |
@@ -218,7 +216,7 @@ Serializer &Serializer::operator&&(uint8_t &p) | |||
218 | } | 216 | } |
219 | } | 217 | } |
220 | 218 | ||
221 | Serializer &Serializer::operator&&(uint16_t &p) | 219 | Bu::Archive &Bu::Archive::operator&&(uint16_t &p) |
222 | { | 220 | { |
223 | if (bLoading) | 221 | if (bLoading) |
224 | { | 222 | { |
@@ -230,7 +228,7 @@ Serializer &Serializer::operator&&(uint16_t &p) | |||
230 | } | 228 | } |
231 | } | 229 | } |
232 | 230 | ||
233 | Serializer &Serializer::operator&&(uint32_t &p) | 231 | Bu::Archive &Bu::Archive::operator&&(uint32_t &p) |
234 | { | 232 | { |
235 | if (bLoading) | 233 | if (bLoading) |
236 | { | 234 | { |
@@ -242,7 +240,7 @@ Serializer &Serializer::operator&&(uint32_t &p) | |||
242 | } | 240 | } |
243 | } | 241 | } |
244 | 242 | ||
245 | Serializer &Serializer::operator&&(uint64_t &p) | 243 | Bu::Archive &Bu::Archive::operator&&(uint64_t &p) |
246 | { | 244 | { |
247 | if (bLoading) | 245 | if (bLoading) |
248 | { | 246 | { |
@@ -254,7 +252,7 @@ Serializer &Serializer::operator&&(uint64_t &p) | |||
254 | } | 252 | } |
255 | } | 253 | } |
256 | 254 | ||
257 | Serializer &Serializer::operator&&(float &p) | 255 | Bu::Archive &Bu::Archive::operator&&(float &p) |
258 | { | 256 | { |
259 | if (bLoading) | 257 | if (bLoading) |
260 | { | 258 | { |
@@ -266,7 +264,7 @@ Serializer &Serializer::operator&&(float &p) | |||
266 | } | 264 | } |
267 | } | 265 | } |
268 | 266 | ||
269 | Serializer &Serializer::operator&&(double &p) | 267 | Bu::Archive &Bu::Archive::operator&&(double &p) |
270 | { | 268 | { |
271 | if (bLoading) | 269 | if (bLoading) |
272 | { | 270 | { |
@@ -278,7 +276,7 @@ Serializer &Serializer::operator&&(double &p) | |||
278 | } | 276 | } |
279 | } | 277 | } |
280 | 278 | ||
281 | Serializer &Serializer::operator&&(long double &p) | 279 | Bu::Archive &Bu::Archive::operator&&(long double &p) |
282 | { | 280 | { |
283 | if (bLoading) | 281 | if (bLoading) |
284 | { | 282 | { |
@@ -291,19 +289,20 @@ Serializer &Serializer::operator&&(long double &p) | |||
291 | } | 289 | } |
292 | 290 | ||
293 | 291 | ||
294 | Serializer &operator<<(Serializer &s, Serializable &p) | 292 | Bu::Archive &Bu::operator<<(Bu::Archive &s, Bu::Archable &p) |
295 | { | 293 | { |
296 | p.serialize( s ); | 294 | p.archive( s ); |
297 | return s; | 295 | return s; |
298 | } | 296 | } |
299 | 297 | ||
300 | Serializer &operator>>(Serializer &s, Serializable &p) | 298 | Bu::Archive &Bu::operator>>(Bu::Archive &s, Bu::Archable &p) |
301 | { | 299 | { |
302 | p.serialize( s ); | 300 | p.archive( s ); |
303 | return s; | 301 | return s; |
304 | } | 302 | } |
305 | 303 | ||
306 | Serializer &operator&&(Serializer &s, Serializable &p) | 304 | /* |
305 | Bu::Archive &Bu::operator&&(Bu::Archive &s, Bu::Archable &p) | ||
307 | { | 306 | { |
308 | if (s.isLoading()) | 307 | if (s.isLoading()) |
309 | { | 308 | { |
@@ -313,9 +312,9 @@ Serializer &operator&&(Serializer &s, Serializable &p) | |||
313 | { | 312 | { |
314 | return s << p; | 313 | return s << p; |
315 | } | 314 | } |
316 | } | 315 | }*/ |
317 | 316 | ||
318 | Serializer &operator<<( Serializer &ar, std::string &s ) | 317 | Bu::Archive &Bu::operator<<( Bu::Archive &ar, std::string &s ) |
319 | { | 318 | { |
320 | ar << (uint32_t)s.length(); | 319 | ar << (uint32_t)s.length(); |
321 | ar.write( s.c_str(), s.length() ); | 320 | ar.write( s.c_str(), s.length() ); |
@@ -323,7 +322,7 @@ Serializer &operator<<( Serializer &ar, std::string &s ) | |||
323 | return ar; | 322 | return ar; |
324 | } | 323 | } |
325 | 324 | ||
326 | Serializer &operator>>( Serializer &ar, std::string &s ) | 325 | Bu::Archive &Bu::operator>>( Bu::Archive &ar, std::string &s ) |
327 | { | 326 | { |
328 | uint32_t l; | 327 | uint32_t l; |
329 | ar >> l; | 328 | ar >> l; |
diff --git a/src/archive.h b/src/archive.h new file mode 100644 index 0000000..7de9220 --- /dev/null +++ b/src/archive.h | |||
@@ -0,0 +1,93 @@ | |||
1 | #ifndef ARCHIVE_H | ||
2 | #define ARCHIVE_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <string> | ||
6 | #include "archable.h" | ||
7 | |||
8 | namespace Bu | ||
9 | { | ||
10 | class Archive | ||
11 | { | ||
12 | private: | ||
13 | bool bLoading; | ||
14 | public: | ||
15 | bool isLoading(); | ||
16 | |||
17 | enum | ||
18 | { | ||
19 | load = true, | ||
20 | save = false | ||
21 | }; | ||
22 | |||
23 | Archive( bool bLoading ); | ||
24 | virtual ~Archive(); | ||
25 | virtual void close()=0; | ||
26 | |||
27 | virtual void write(const void *, int32_t)=0; | ||
28 | virtual void read(void *, int32_t)=0; | ||
29 | |||
30 | virtual Archive &operator<<(bool); | ||
31 | virtual Archive &operator<<(int8_t); | ||
32 | virtual Archive &operator<<(int16_t); | ||
33 | virtual Archive &operator<<(int32_t); | ||
34 | virtual Archive &operator<<(int64_t); | ||
35 | virtual Archive &operator<<(uint8_t); | ||
36 | virtual Archive &operator<<(uint16_t); | ||
37 | virtual Archive &operator<<(uint32_t); | ||
38 | virtual Archive &operator<<(uint64_t); | ||
39 | virtual Archive &operator<<(long); | ||
40 | virtual Archive &operator<<(float); | ||
41 | virtual Archive &operator<<(double); | ||
42 | virtual Archive &operator<<(long double); | ||
43 | |||
44 | virtual Archive &operator>>(bool &); | ||
45 | virtual Archive &operator>>(int8_t &); | ||
46 | virtual Archive &operator>>(int16_t &); | ||
47 | virtual Archive &operator>>(int32_t &); | ||
48 | virtual Archive &operator>>(int64_t &); | ||
49 | virtual Archive &operator>>(uint8_t &); | ||
50 | virtual Archive &operator>>(uint16_t &); | ||
51 | virtual Archive &operator>>(uint32_t &); | ||
52 | virtual Archive &operator>>(uint64_t &); | ||
53 | virtual Archive &operator>>(long &); | ||
54 | virtual Archive &operator>>(float &); | ||
55 | virtual Archive &operator>>(double &); | ||
56 | virtual Archive &operator>>(long double &); | ||
57 | |||
58 | virtual Archive &operator&&(bool &); | ||
59 | virtual Archive &operator&&(int8_t &); | ||
60 | virtual Archive &operator&&(int16_t &); | ||
61 | virtual Archive &operator&&(int32_t &); | ||
62 | virtual Archive &operator&&(int64_t &); | ||
63 | virtual Archive &operator&&(uint8_t &); | ||
64 | virtual Archive &operator&&(uint16_t &); | ||
65 | virtual Archive &operator&&(uint32_t &); | ||
66 | virtual Archive &operator&&(uint64_t &); | ||
67 | virtual Archive &operator&&(float &); | ||
68 | virtual Archive &operator&&(double &); | ||
69 | virtual Archive &operator&&(long double &); | ||
70 | }; | ||
71 | |||
72 | Archive &operator<<(Archive &, class Bu::Archable &); | ||
73 | Archive &operator>>(Archive &, class Bu::Archable &); | ||
74 | //Archive &operator&&(Archive &s, class Bu::Archable &p); | ||
75 | |||
76 | Archive &operator<<(Archive &, std::string &); | ||
77 | Archive &operator>>(Archive &, std::string &); | ||
78 | //Archive &operator&&(Archive &, std::string &); | ||
79 | |||
80 | template<typename T> Archive &operator&&( Archive &ar, T &dat ) | ||
81 | { | ||
82 | if( ar.isLoading() ) | ||
83 | { | ||
84 | return ar >> dat; | ||
85 | } | ||
86 | else | ||
87 | { | ||
88 | return ar << dat; | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
93 | #endif | ||
diff --git a/src/old/exceptionbase.cpp b/src/exceptionbase.cpp index f3d22da..f6ec625 100644 --- a/src/old/exceptionbase.cpp +++ b/src/exceptionbase.cpp | |||
@@ -1,7 +1,7 @@ | |||
1 | #include "exceptionbase.h" | 1 | #include "exceptionbase.h" |
2 | #include <stdarg.h> | 2 | #include <stdarg.h> |
3 | 3 | ||
4 | ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : | 4 | Bu::ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : |
5 | nErrorCode( 0 ), | 5 | nErrorCode( 0 ), |
6 | sWhat( NULL ) | 6 | sWhat( NULL ) |
7 | { | 7 | { |
@@ -12,7 +12,7 @@ ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : | |||
12 | va_end(ap); | 12 | va_end(ap); |
13 | } | 13 | } |
14 | 14 | ||
15 | ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : | 15 | Bu::ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : |
16 | nErrorCode( nCode ), | 16 | nErrorCode( nCode ), |
17 | sWhat( NULL ) | 17 | sWhat( NULL ) |
18 | { | 18 | { |
@@ -23,13 +23,13 @@ ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : | |||
23 | va_end(ap); | 23 | va_end(ap); |
24 | } | 24 | } |
25 | 25 | ||
26 | ExceptionBase::ExceptionBase( int nCode ) throw() : | 26 | Bu::ExceptionBase::ExceptionBase( int nCode ) throw() : |
27 | nErrorCode( nCode ), | 27 | nErrorCode( nCode ), |
28 | sWhat( NULL ) | 28 | sWhat( NULL ) |
29 | { | 29 | { |
30 | } | 30 | } |
31 | 31 | ||
32 | ExceptionBase::~ExceptionBase() throw() | 32 | Bu::ExceptionBase::~ExceptionBase() throw() |
33 | { | 33 | { |
34 | if( sWhat ) | 34 | if( sWhat ) |
35 | { | 35 | { |
@@ -38,7 +38,7 @@ ExceptionBase::~ExceptionBase() throw() | |||
38 | } | 38 | } |
39 | } | 39 | } |
40 | 40 | ||
41 | void ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) | 41 | void Bu::ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) |
42 | { | 42 | { |
43 | if( sWhat ) delete[] sWhat; | 43 | if( sWhat ) delete[] sWhat; |
44 | int nSize; | 44 | int nSize; |
@@ -48,7 +48,7 @@ void ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) | |||
48 | vsnprintf( sWhat, nSize+1, lpFormat, vargs ); | 48 | vsnprintf( sWhat, nSize+1, lpFormat, vargs ); |
49 | } | 49 | } |
50 | 50 | ||
51 | void ExceptionBase::setWhat( const char *lpText ) | 51 | void Bu::ExceptionBase::setWhat( const char *lpText ) |
52 | { | 52 | { |
53 | if( sWhat ) delete[] sWhat; | 53 | if( sWhat ) delete[] sWhat; |
54 | int nSize; | 54 | int nSize; |
@@ -58,12 +58,12 @@ void ExceptionBase::setWhat( const char *lpText ) | |||
58 | strcpy( sWhat, lpText ); | 58 | strcpy( sWhat, lpText ); |
59 | } | 59 | } |
60 | 60 | ||
61 | const char *ExceptionBase::what() const throw() | 61 | const char *Bu::ExceptionBase::what() const throw() |
62 | { | 62 | { |
63 | return sWhat; | 63 | return sWhat; |
64 | } | 64 | } |
65 | 65 | ||
66 | int ExceptionBase::getErrorCode() | 66 | int Bu::ExceptionBase::getErrorCode() |
67 | { | 67 | { |
68 | return nErrorCode; | 68 | return nErrorCode; |
69 | } | 69 | } |
diff --git a/src/exceptionbase.h b/src/exceptionbase.h new file mode 100644 index 0000000..fd78089 --- /dev/null +++ b/src/exceptionbase.h | |||
@@ -0,0 +1,114 @@ | |||
1 | #ifndef EXCEPTION_BASE_H | ||
2 | #define EXCEPTION_BASE_H | ||
3 | |||
4 | #include <string> | ||
5 | #include <exception> | ||
6 | #include <stdarg.h> | ||
7 | |||
8 | namespace Bu | ||
9 | { | ||
10 | /** | ||
11 | * A generalized Exception base class. This is nice for making general and | ||
12 | * flexible child classes that can create new error code classes. | ||
13 | * | ||
14 | * In order to create your own exception class use these two lines. | ||
15 | * | ||
16 | * in your header: subExceptionDecl( NewClassName ); | ||
17 | * | ||
18 | * in your source: subExcpetienDef( NewClassName ); | ||
19 | */ | ||
20 | class ExceptionBase : public std::exception | ||
21 | { | ||
22 | public: | ||
23 | /** | ||
24 | * Construct an exception with an error code of zero, but with a | ||
25 | * description. The use of this is not reccomended most of the time, | ||
26 | * it's generally best to include an error code with the exception so | ||
27 | * your program can handle the exception in a better way. | ||
28 | * @param sFormat The format of the text. See printf for more info. | ||
29 | */ | ||
30 | ExceptionBase( const char *sFormat, ... ) throw(); | ||
31 | |||
32 | /** | ||
33 | * | ||
34 | * @param nCode | ||
35 | * @param sFormat | ||
36 | */ | ||
37 | ExceptionBase( int nCode, const char *sFormat, ... ) throw(); | ||
38 | |||
39 | /** | ||
40 | * | ||
41 | * @param nCode | ||
42 | * @return | ||
43 | */ | ||
44 | ExceptionBase( int nCode=0 ) throw(); | ||
45 | |||
46 | /** | ||
47 | * | ||
48 | * @return | ||
49 | */ | ||
50 | virtual ~ExceptionBase() throw(); | ||
51 | |||
52 | /** | ||
53 | * | ||
54 | * @return | ||
55 | */ | ||
56 | virtual const char *what() const throw(); | ||
57 | |||
58 | /** | ||
59 | * | ||
60 | * @return | ||
61 | */ | ||
62 | int getErrorCode(); | ||
63 | |||
64 | /** | ||
65 | * | ||
66 | * @param lpFormat | ||
67 | * @param vargs | ||
68 | */ | ||
69 | void setWhat( const char *lpFormat, va_list &vargs ); | ||
70 | |||
71 | /** | ||
72 | * | ||
73 | * @param lpText | ||
74 | */ | ||
75 | void setWhat( const char *lpText ); | ||
76 | |||
77 | private: | ||
78 | int nErrorCode; /**< The code for the error that occured. */ | ||
79 | char *sWhat; /**< The text string telling people what went wrong. */ | ||
80 | }; | ||
81 | } | ||
82 | |||
83 | #define subExceptionDecl( name ) \ | ||
84 | class name : public ExceptionBase \ | ||
85 | { \ | ||
86 | public: \ | ||
87 | name( const char *sFormat, ... ) throw (); \ | ||
88 | name( int nCode, const char *sFormat, ... ) throw(); \ | ||
89 | name( int nCode=0 ) throw (); \ | ||
90 | }; | ||
91 | |||
92 | #define subExceptionDef( name ) \ | ||
93 | name::name( const char *lpFormat, ... ) throw() : \ | ||
94 | ExceptionBase( 0 ) \ | ||
95 | { \ | ||
96 | va_list ap; \ | ||
97 | va_start( ap, lpFormat ); \ | ||
98 | setWhat( lpFormat, ap ); \ | ||
99 | va_end( ap ); \ | ||
100 | } \ | ||
101 | name::name( int nCode, const char *lpFormat, ... ) throw() : \ | ||
102 | ExceptionBase( nCode ) \ | ||
103 | { \ | ||
104 | va_list ap; \ | ||
105 | va_start( ap, lpFormat ); \ | ||
106 | setWhat( lpFormat, ap ); \ | ||
107 | va_end( ap ); \ | ||
108 | } \ | ||
109 | name::name( int nCode ) throw() : \ | ||
110 | ExceptionBase( nCode ) \ | ||
111 | { \ | ||
112 | } | ||
113 | |||
114 | #endif | ||
diff --git a/src/exceptions.cpp b/src/exceptions.cpp new file mode 100644 index 0000000..37f09a4 --- /dev/null +++ b/src/exceptions.cpp | |||
@@ -0,0 +1,10 @@ | |||
1 | #include "exceptions.h" | ||
2 | #include <stdarg.h> | ||
3 | |||
4 | namespace Bu | ||
5 | { | ||
6 | subExceptionDef( XmlException ) | ||
7 | subExceptionDef( FileException ) | ||
8 | subExceptionDef( ConnectionException ) | ||
9 | subExceptionDef( PluginException ) | ||
10 | } | ||
diff --git a/src/exceptions.h b/src/exceptions.h new file mode 100644 index 0000000..b28d292 --- /dev/null +++ b/src/exceptions.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef EXCEPTIONS_H | ||
2 | #define EXCEPTIONS_H | ||
3 | |||
4 | #include "exceptionbase.h" | ||
5 | #include <stdarg.h> | ||
6 | |||
7 | namespace Bu | ||
8 | { | ||
9 | subExceptionDecl( XmlException ) | ||
10 | subExceptionDecl( FileException ) | ||
11 | subExceptionDecl( ConnectionException ) | ||
12 | subExceptionDecl( PluginException ) | ||
13 | |||
14 | enum eFileException | ||
15 | { | ||
16 | excodeEOF | ||
17 | }; | ||
18 | |||
19 | enum eConnectionException | ||
20 | { | ||
21 | excodeReadError, | ||
22 | excodeBadReadError, | ||
23 | excodeConnectionClosed, | ||
24 | excodeSocketTimeout | ||
25 | }; | ||
26 | } | ||
27 | |||
28 | #endif | ||
diff --git a/src/fstring.cpp b/src/fstring.cpp new file mode 100644 index 0000000..56d2173 --- /dev/null +++ b/src/fstring.cpp | |||
@@ -0,0 +1,14 @@ | |||
1 | #include "fstring.h" | ||
2 | #include "hash.h" | ||
3 | |||
4 | template<> uint32_t Bu::__calcHashCode<Bu::FString>( const Bu::FString &k ) | ||
5 | { | ||
6 | return __calcHashCode( k.c_str() ); | ||
7 | } | ||
8 | |||
9 | template<> bool Bu::__cmpHashKeys<Bu::FString>( | ||
10 | const Bu::FString &a, const Bu::FString &b ) | ||
11 | { | ||
12 | return a == b; | ||
13 | } | ||
14 | |||
diff --git a/src/fstring.h b/src/fstring.h new file mode 100644 index 0000000..717068f --- /dev/null +++ b/src/fstring.h | |||
@@ -0,0 +1,653 @@ | |||
1 | #ifndef F_STRING_H | ||
2 | #define F_STRING_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <memory> | ||
6 | #include "archable.h" | ||
7 | #include "archive.h" | ||
8 | #include "hash.h" | ||
9 | |||
10 | namespace Bu | ||
11 | { | ||
12 | template< typename chr > | ||
13 | struct FStringChunk | ||
14 | { | ||
15 | long nLength; | ||
16 | chr *pData; | ||
17 | FStringChunk *pNext; | ||
18 | }; | ||
19 | |||
20 | /** | ||
21 | * Flexible String class. This class was designed with string passing and | ||
22 | * generation in mind. Like the standard string class you can specify what | ||
23 | * datatype to use for each character. Unlike the standard string class, | ||
24 | * collection of appended and prepended terms is done lazily, making long | ||
25 | * operations that involve many appends very inexpensive. In addition internal | ||
26 | * ref-counting means that if you pass strings around between functions there's | ||
27 | * almost no overhead in time or memory since a reference is created and no | ||
28 | * data is actually copied. This also means that you never need to put any | ||
29 | * FBasicString into a ref-counting container class. | ||
30 | */ | ||
31 | template< typename chr, typename chralloc=std::allocator<chr>, typename chunkalloc=std::allocator<struct FStringChunk<chr> > > | ||
32 | class FBasicString : public Archable | ||
33 | { | ||
34 | #ifndef VALTEST | ||
35 | #define cpy( dest, src, size ) memcpy( dest, src, size*sizeof(chr) ) | ||
36 | #endif | ||
37 | private: | ||
38 | typedef struct FStringChunk<chr> Chunk; | ||
39 | typedef struct FBasicString<chr, chralloc, chunkalloc> MyType; | ||
40 | |||
41 | public: | ||
42 | FBasicString() : | ||
43 | nLength( 0 ), | ||
44 | pnRefs( NULL ), | ||
45 | pFirst( NULL ), | ||
46 | pLast( NULL ) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | FBasicString( const chr *pData ) : | ||
51 | nLength( 0 ), | ||
52 | pnRefs( NULL ), | ||
53 | pFirst( NULL ), | ||
54 | pLast( NULL ) | ||
55 | { | ||
56 | append( pData ); | ||
57 | } | ||
58 | |||
59 | FBasicString( const chr *pData, long nLength ) : | ||
60 | nLength( 0 ), | ||
61 | pnRefs( NULL ), | ||
62 | pFirst( NULL ), | ||
63 | pLast( NULL ) | ||
64 | { | ||
65 | append( pData, nLength ); | ||
66 | } | ||
67 | |||
68 | FBasicString( const MyType &rSrc ) : | ||
69 | nLength( 0 ), | ||
70 | pnRefs( NULL ), | ||
71 | pFirst( NULL ), | ||
72 | pLast( NULL ) | ||
73 | { | ||
74 | // Here we have no choice but to copy, since the other guy is a const. | ||
75 | // In the case that the source were flat, we could get a reference, it | ||
76 | // would make some things faster, but not matter in many other cases. | ||
77 | |||
78 | joinShare( rSrc ); | ||
79 | //copyFrom( rSrc ); | ||
80 | } | ||
81 | |||
82 | FBasicString( const MyType &rSrc, long nLength ) : | ||
83 | nLength( 0 ), | ||
84 | pnRefs( NULL ), | ||
85 | pFirst( NULL ), | ||
86 | pLast( NULL ) | ||
87 | { | ||
88 | append( rSrc.pFirst->pData, nLength ); | ||
89 | } | ||
90 | |||
91 | FBasicString( const MyType &rSrc, long nStart, long nLength ) : | ||
92 | nLength( 0 ), | ||
93 | pnRefs( NULL ), | ||
94 | pFirst( NULL ), | ||
95 | pLast( NULL ) | ||
96 | { | ||
97 | append( rSrc.pFirst->pData+nStart, nLength ); | ||
98 | } | ||
99 | |||
100 | FBasicString( long nSize ) : | ||
101 | nLength( nSize ), | ||
102 | pnRefs( NULL ), | ||
103 | pFirst( NULL ), | ||
104 | pLast( NULL ) | ||
105 | { | ||
106 | pFirst = pLast = newChunk( nSize ); | ||
107 | } | ||
108 | |||
109 | virtual ~FBasicString() | ||
110 | { | ||
111 | clear(); | ||
112 | } | ||
113 | |||
114 | void append( const chr *pData ) | ||
115 | { | ||
116 | long nLen; | ||
117 | for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); | ||
118 | |||
119 | Chunk *pNew = newChunk( nLen ); | ||
120 | cpy( pNew->pData, pData, nLen ); | ||
121 | |||
122 | appendChunk( pNew ); | ||
123 | } | ||
124 | |||
125 | void append( const chr *pData, long nLen ) | ||
126 | { | ||
127 | Chunk *pNew = newChunk( nLen ); | ||
128 | |||
129 | cpy( pNew->pData, pData, nLen ); | ||
130 | |||
131 | appendChunk( pNew ); | ||
132 | } | ||
133 | |||
134 | void prepend( const chr *pData ) | ||
135 | { | ||
136 | long nLen; | ||
137 | for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); | ||
138 | |||
139 | Chunk *pNew = newChunk( nLen ); | ||
140 | cpy( pNew->pData, pData, nLen ); | ||
141 | |||
142 | prependChunk( pNew ); | ||
143 | } | ||
144 | |||
145 | void prepend( const chr *pData, long nLen ) | ||
146 | { | ||
147 | Chunk *pNew = newChunk( nLen ); | ||
148 | |||
149 | cpy( pNew->pData, pData, nLen ); | ||
150 | |||
151 | prependChunk( pNew ); | ||
152 | } | ||
153 | |||
154 | void clear() | ||
155 | { | ||
156 | realClear(); | ||
157 | } | ||
158 | |||
159 | void resize( long nNewSize ) | ||
160 | { | ||
161 | if( nLength == nNewSize ) | ||
162 | return; | ||
163 | |||
164 | flatten(); | ||
165 | |||
166 | Chunk *pNew = newChunk( nNewSize ); | ||
167 | long nNewLen = (nNewSize<nLength)?(nNewSize):(nLength); | ||
168 | cpy( pNew->pData, pFirst->pData, nNewLen ); | ||
169 | pNew->pData[nNewLen] = (chr)0; | ||
170 | aChr.deallocate( pFirst->pData, pFirst->nLength+1 ); | ||
171 | aChunk.deallocate( pFirst, 1 ); | ||
172 | pFirst = pLast = pNew; | ||
173 | nLength = nNewSize; | ||
174 | } | ||
175 | |||
176 | long getSize() const | ||
177 | { | ||
178 | return nLength; | ||
179 | } | ||
180 | |||
181 | chr *getStr() | ||
182 | { | ||
183 | if( pFirst == NULL ) | ||
184 | return NULL; | ||
185 | |||
186 | flatten(); | ||
187 | return pFirst->pData; | ||
188 | } | ||
189 | |||
190 | const chr *getStr() const | ||
191 | { | ||
192 | if( pFirst == NULL ) | ||
193 | return NULL; | ||
194 | |||
195 | flatten(); | ||
196 | return pFirst->pData; | ||
197 | } | ||
198 | |||
199 | chr *c_str() | ||
200 | { | ||
201 | if( pFirst == NULL ) | ||
202 | return NULL; | ||
203 | |||
204 | flatten(); | ||
205 | return pFirst->pData; | ||
206 | } | ||
207 | |||
208 | const chr *c_str() const | ||
209 | { | ||
210 | if( pFirst == NULL ) | ||
211 | return NULL; | ||
212 | |||
213 | flatten(); | ||
214 | return pFirst->pData; | ||
215 | } | ||
216 | |||
217 | MyType &operator +=( const chr *pData ) | ||
218 | { | ||
219 | append( pData ); | ||
220 | |||
221 | return (*this); | ||
222 | } | ||
223 | |||
224 | MyType &operator +=( const MyType &rSrc ) | ||
225 | { | ||
226 | rSrc.flatten(); | ||
227 | append( rSrc.pFirst->pData, rSrc.nLength ); | ||
228 | |||
229 | return (*this); | ||
230 | } | ||
231 | |||
232 | MyType &operator +=( const chr pData ) | ||
233 | { | ||
234 | chr tmp[2] = { pData, (chr)0 }; | ||
235 | append( tmp ); | ||
236 | |||
237 | return (*this); | ||
238 | } | ||
239 | |||
240 | MyType &operator =( const chr *pData ) | ||
241 | { | ||
242 | clear(); | ||
243 | append( pData ); | ||
244 | |||
245 | return (*this); | ||
246 | } | ||
247 | |||
248 | MyType &operator =( const MyType &rSrc ) | ||
249 | { | ||
250 | //if( rSrc.isFlat() ) | ||
251 | //{ | ||
252 | joinShare( rSrc ); | ||
253 | //} | ||
254 | //else | ||
255 | //{ | ||
256 | // copyFrom( rSrc ); | ||
257 | //} | ||
258 | // | ||
259 | |||
260 | return (*this); | ||
261 | } | ||
262 | |||
263 | bool operator ==( const chr *pData ) const | ||
264 | { | ||
265 | if( pFirst == NULL ) { | ||
266 | if( pData == NULL ) | ||
267 | return true; | ||
268 | return false; | ||
269 | } | ||
270 | |||
271 | flatten(); | ||
272 | const chr *a = pData; | ||
273 | chr *b = pFirst->pData; | ||
274 | for( ; *a!=(chr)0; a++, b++ ) | ||
275 | { | ||
276 | if( *a != *b ) | ||
277 | return false; | ||
278 | } | ||
279 | |||
280 | return true; | ||
281 | } | ||
282 | |||
283 | bool operator ==( const MyType &pData ) const | ||
284 | { | ||
285 | if( pFirst == pData.pFirst ) | ||
286 | return true; | ||
287 | if( pFirst == NULL ) | ||
288 | return false; | ||
289 | |||
290 | flatten(); | ||
291 | pData.flatten(); | ||
292 | const chr *a = pData.pFirst->pData; | ||
293 | chr *b = pFirst->pData; | ||
294 | for( ; *a!=(chr)0; a++, b++ ) | ||
295 | { | ||
296 | if( *a != *b ) | ||
297 | return false; | ||
298 | } | ||
299 | |||
300 | return true; | ||
301 | } | ||
302 | |||
303 | bool operator !=(const chr *pData ) const | ||
304 | { | ||
305 | return !(*this == pData); | ||
306 | } | ||
307 | |||
308 | bool operator !=(const MyType &pData ) const | ||
309 | { | ||
310 | return !(*this == pData); | ||
311 | } | ||
312 | |||
313 | chr &operator[]( long nIndex ) | ||
314 | { | ||
315 | flatten(); | ||
316 | |||
317 | return pFirst->pData[nIndex]; | ||
318 | } | ||
319 | |||
320 | const chr &operator[]( long nIndex ) const | ||
321 | { | ||
322 | flatten(); | ||
323 | |||
324 | return pFirst->pData[nIndex]; | ||
325 | } | ||
326 | |||
327 | bool isWS( long nIndex ) const | ||
328 | { | ||
329 | flatten(); | ||
330 | |||
331 | return pFirst->pData[nIndex]==' ' || pFirst->pData[nIndex]=='\t' | ||
332 | || pFirst->pData[nIndex]=='\r' || pFirst->pData[nIndex]=='\n'; | ||
333 | } | ||
334 | |||
335 | bool isAlpha( long nIndex ) const | ||
336 | { | ||
337 | flatten(); | ||
338 | |||
339 | return (pFirst->pData[nIndex] >= 'a' && pFirst->pData[nIndex] <= 'z') | ||
340 | || (pFirst->pData[nIndex] >= 'A' && pFirst->pData[nIndex] <= 'Z'); | ||
341 | } | ||
342 | |||
343 | void toLower() | ||
344 | { | ||
345 | flatten(); | ||
346 | unShare(); | ||
347 | |||
348 | for( long j = 0; j < nLength; j++ ) | ||
349 | { | ||
350 | if( pFirst->pData[j] >= 'A' && pFirst->pData[j] <= 'Z' ) | ||
351 | pFirst->pData[j] -= 'A'-'a'; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | void toUpper() | ||
356 | { | ||
357 | flatten(); | ||
358 | unShare(); | ||
359 | |||
360 | for( long j = 0; j < nLength; j++ ) | ||
361 | { | ||
362 | if( pFirst->pData[j] >= 'a' && pFirst->pData[j] <= 'z' ) | ||
363 | pFirst->pData[j] += 'A'-'a'; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | void archive( class Archive &ar ) | ||
368 | { | ||
369 | if( ar.isLoading() ) | ||
370 | { | ||
371 | clear(); | ||
372 | long nLen; | ||
373 | ar >> nLen; | ||
374 | |||
375 | Chunk *pNew = newChunk( nLen ); | ||
376 | ar.read( pNew->pData, nLen*sizeof(chr) ); | ||
377 | appendChunk( pNew ); | ||
378 | } | ||
379 | else | ||
380 | { | ||
381 | flatten(); | ||
382 | |||
383 | ar << nLength; | ||
384 | ar.write( pFirst->pData, nLength*sizeof(chr) ); | ||
385 | } | ||
386 | } | ||
387 | |||
388 | private: | ||
389 | void flatten() const | ||
390 | { | ||
391 | if( isFlat() ) | ||
392 | return; | ||
393 | |||
394 | if( pFirst == NULL ) | ||
395 | return; | ||
396 | |||
397 | unShare(); | ||
398 | |||
399 | Chunk *pNew = newChunk( nLength ); | ||
400 | chr *pos = pNew->pData; | ||
401 | Chunk *i = pFirst; | ||
402 | for(;;) | ||
403 | { | ||
404 | cpy( pos, i->pData, i->nLength ); | ||
405 | pos += i->nLength; | ||
406 | i = i->pNext; | ||
407 | if( i == NULL ) | ||
408 | break; | ||
409 | } | ||
410 | realClear(); | ||
411 | |||
412 | pLast = pFirst = pNew; | ||
413 | nLength = pNew->nLength; | ||
414 | } | ||
415 | |||
416 | void realClear() const | ||
417 | { | ||
418 | if( pFirst == NULL ) | ||
419 | return; | ||
420 | |||
421 | if( isShared() ) | ||
422 | { | ||
423 | decRefs(); | ||
424 | } | ||
425 | else | ||
426 | { | ||
427 | Chunk *i = pFirst; | ||
428 | for(;;) | ||
429 | { | ||
430 | Chunk *n = i->pNext; | ||
431 | aChr.deallocate( i->pData, i->nLength+1 ); | ||
432 | aChunk.deallocate( i, 1 ); | ||
433 | if( n == NULL ) | ||
434 | break; | ||
435 | i = n; | ||
436 | } | ||
437 | pFirst = pLast = NULL; | ||
438 | nLength = 0; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | void copyFrom( const FBasicString<chr, chralloc, chunkalloc> &rSrc ) | ||
443 | { | ||
444 | if( rSrc.pFirst == NULL ) | ||
445 | return; | ||
446 | |||
447 | decRefs(); | ||
448 | |||
449 | Chunk *pNew = newChunk( rSrc.nLength ); | ||
450 | chr *pos = pNew->pData; | ||
451 | Chunk *i = rSrc.pFirst; | ||
452 | for(;;) | ||
453 | { | ||
454 | cpy( pos, i->pData, i->nLength ); | ||
455 | pos += i->nLength; | ||
456 | i = i->pNext; | ||
457 | if( i == NULL ) | ||
458 | break; | ||
459 | } | ||
460 | clear(); | ||
461 | |||
462 | appendChunk( pNew ); | ||
463 | } | ||
464 | |||
465 | bool isFlat() const | ||
466 | { | ||
467 | return (pFirst == pLast); | ||
468 | } | ||
469 | |||
470 | bool isShared() const | ||
471 | { | ||
472 | return (pnRefs != NULL); | ||
473 | } | ||
474 | |||
475 | Chunk *newChunk() const | ||
476 | { | ||
477 | Chunk *pNew = aChunk.allocate( 1 ); | ||
478 | pNew->pNext = NULL; | ||
479 | return pNew; | ||
480 | } | ||
481 | |||
482 | Chunk *newChunk( long nLen ) const | ||
483 | { | ||
484 | Chunk *pNew = aChunk.allocate( 1 ); | ||
485 | pNew->pNext = NULL; | ||
486 | pNew->nLength = nLen; | ||
487 | pNew->pData = aChr.allocate( nLen+1 ); | ||
488 | pNew->pData[nLen] = (chr)0; | ||
489 | return pNew; | ||
490 | } | ||
491 | |||
492 | void appendChunk( Chunk *pNewChunk ) | ||
493 | { | ||
494 | unShare(); | ||
495 | |||
496 | if( pFirst == NULL ) | ||
497 | pLast = pFirst = pNewChunk; | ||
498 | else | ||
499 | { | ||
500 | pLast->pNext = pNewChunk; | ||
501 | pLast = pNewChunk; | ||
502 | } | ||
503 | |||
504 | nLength += pNewChunk->nLength; | ||
505 | } | ||
506 | |||
507 | void prependChunk( Chunk *pNewChunk ) | ||
508 | { | ||
509 | unShare(); | ||
510 | |||
511 | if( pFirst == NULL ) | ||
512 | pLast = pFirst = pNewChunk; | ||
513 | else | ||
514 | { | ||
515 | pNewChunk->pNext = pFirst; | ||
516 | pFirst = pNewChunk; | ||
517 | } | ||
518 | |||
519 | nLength += pNewChunk->nLength; | ||
520 | } | ||
521 | |||
522 | void joinShare( MyType &rSrc ) | ||
523 | { | ||
524 | clear(); | ||
525 | |||
526 | if( !rSrc.isFlat() ) | ||
527 | rSrc.flatten(); | ||
528 | |||
529 | rSrc.initCount(); | ||
530 | pnRefs = rSrc.pnRefs; | ||
531 | (*pnRefs)++; | ||
532 | nLength = rSrc.nLength; | ||
533 | pFirst = rSrc.pFirst; | ||
534 | pLast = rSrc.pLast; | ||
535 | } | ||
536 | |||
537 | void joinShare( const MyType &rSrc ) | ||
538 | { | ||
539 | clear(); | ||
540 | |||
541 | rSrc.flatten(); | ||
542 | |||
543 | if( !rSrc.isShared() ) | ||
544 | { | ||
545 | rSrc.pnRefs = new uint32_t; | ||
546 | (*rSrc.pnRefs) = 1; | ||
547 | } | ||
548 | pnRefs = rSrc.pnRefs; | ||
549 | (*pnRefs)++; | ||
550 | nLength = rSrc.nLength; | ||
551 | pFirst = rSrc.pFirst; | ||
552 | pLast = rSrc.pLast; | ||
553 | } | ||
554 | |||
555 | /** | ||
556 | * This takes an object that was shared and makes a copy of the base data | ||
557 | * that was being shared so that this copy can be changed. This should be | ||
558 | * added before any call that will change this object; | ||
559 | */ | ||
560 | void unShare() const | ||
561 | { | ||
562 | if( isShared() == false ) | ||
563 | return; | ||
564 | |||
565 | Chunk *pNew = newChunk( nLength ); | ||
566 | chr *pos = pNew->pData; | ||
567 | Chunk *i = pFirst; | ||
568 | for(;;) | ||
569 | { | ||
570 | cpy( pos, i->pData, i->nLength ); | ||
571 | pos += i->nLength; | ||
572 | i = i->pNext; | ||
573 | if( i == NULL ) | ||
574 | break; | ||
575 | } | ||
576 | decRefs(); | ||
577 | pLast = pFirst = pNew; | ||
578 | nLength = pNew->nLength; | ||
579 | } | ||
580 | |||
581 | /** | ||
582 | * This decrements our ref count and pulls us out of the share. If the ref | ||
583 | * count hits zero because of this, it destroys the share. This is not | ||
584 | * safe to call on it's own, it's much better to call unShare. | ||
585 | */ | ||
586 | void decRefs() const | ||
587 | { | ||
588 | if( isShared() ) | ||
589 | { | ||
590 | (*pnRefs)--; | ||
591 | if( (*pnRefs) == 0 ) | ||
592 | destroyShare(); | ||
593 | else | ||
594 | { | ||
595 | pnRefs = NULL; | ||
596 | pFirst = NULL; | ||
597 | pLast = NULL; | ||
598 | nLength = 0; | ||
599 | } | ||
600 | } | ||
601 | } | ||
602 | |||
603 | /** | ||
604 | * While the unShare function removes an instance from a share, this | ||
605 | * function destroys the data that was in the share, removing the share | ||
606 | * itself. This should only be called when the refcount for the share has | ||
607 | * or is about to reach zero. | ||
608 | */ | ||
609 | void destroyShare() const | ||
610 | { | ||
611 | delete pnRefs; | ||
612 | pnRefs = NULL; | ||
613 | realClear(); | ||
614 | } | ||
615 | |||
616 | #ifdef VALTEST | ||
617 | void cpy( chr *dest, const chr *src, long count ) const | ||
618 | { | ||
619 | for( int j = 0; j < count; j++ ) | ||
620 | { | ||
621 | *dest = *src; | ||
622 | dest++; | ||
623 | src++; | ||
624 | } | ||
625 | } | ||
626 | #endif | ||
627 | |||
628 | void initCount() const | ||
629 | { | ||
630 | if( !isShared() ) | ||
631 | { | ||
632 | pnRefs = new uint32_t; | ||
633 | (*pnRefs) = 1; | ||
634 | } | ||
635 | } | ||
636 | |||
637 | private: | ||
638 | mutable long nLength; | ||
639 | mutable uint32_t *pnRefs; | ||
640 | mutable Chunk *pFirst; | ||
641 | mutable Chunk *pLast; | ||
642 | |||
643 | mutable chralloc aChr; | ||
644 | mutable chunkalloc aChunk; | ||
645 | }; | ||
646 | |||
647 | typedef FBasicString<char> FString; | ||
648 | |||
649 | template<> uint32_t __calcHashCode<FString>( const FString &k ); | ||
650 | template<> bool __cmpHashKeys<FString>( const FString &a, const FString &b ); | ||
651 | } | ||
652 | |||
653 | #endif | ||
diff --git a/src/hash.cpp b/src/hash.cpp new file mode 100644 index 0000000..a207c29 --- /dev/null +++ b/src/hash.cpp | |||
@@ -0,0 +1,101 @@ | |||
1 | #include "hash.h" | ||
2 | |||
3 | namespace Bu { subExceptionDef( HashException ) } | ||
4 | |||
5 | template<> uint32_t Bu::__calcHashCode<int>( const int &k ) | ||
6 | { | ||
7 | return k; | ||
8 | } | ||
9 | |||
10 | template<> bool Bu::__cmpHashKeys<int>( const int &a, const int &b ) | ||
11 | { | ||
12 | return a == b; | ||
13 | } | ||
14 | |||
15 | template<> uint32_t Bu::__calcHashCode<unsigned int>( const unsigned int &k ) | ||
16 | { | ||
17 | return k; | ||
18 | } | ||
19 | |||
20 | template<> bool Bu::__cmpHashKeys<unsigned int>( const unsigned int &a, const unsigned int &b ) | ||
21 | { | ||
22 | return a == b; | ||
23 | } | ||
24 | |||
25 | template<> | ||
26 | uint32_t Bu::__calcHashCode<const char *>( const char * const &k ) | ||
27 | { | ||
28 | if (k == NULL) | ||
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 | } | ||
38 | |||
39 | return nPos; | ||
40 | } | ||
41 | |||
42 | template<> bool Bu::__cmpHashKeys<const char *>( const char * const &a, const char * const &b ) | ||
43 | { | ||
44 | if( a == b ) | ||
45 | return true; | ||
46 | |||
47 | for(int j=0; a[j] == b[j]; j++ ) | ||
48 | if( a[j] == '\0' ) | ||
49 | return true; | ||
50 | |||
51 | return false; | ||
52 | } | ||
53 | |||
54 | template<> | ||
55 | uint32_t Bu::__calcHashCode<char *>( char * const &k ) | ||
56 | { | ||
57 | if (k == NULL) | ||
58 | { | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | unsigned long int nPos = 0; | ||
63 | for( const char *s = k; *s; s++ ) | ||
64 | { | ||
65 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | ||
66 | } | ||
67 | |||
68 | return nPos; | ||
69 | } | ||
70 | |||
71 | template<> bool Bu::__cmpHashKeys<char *>( char * const &a, char * const &b ) | ||
72 | { | ||
73 | if( a == b ) | ||
74 | return true; | ||
75 | |||
76 | for(int j=0; a[j] == b[j]; j++ ) | ||
77 | if( a[j] == '\0' ) | ||
78 | return true; | ||
79 | |||
80 | return false; | ||
81 | } | ||
82 | |||
83 | template<> uint32_t Bu::__calcHashCode<std::string>( const std::string &k ) | ||
84 | { | ||
85 | std::string::size_type j, sz = k.size(); | ||
86 | const char *s = k.c_str(); | ||
87 | |||
88 | unsigned long int nPos = 0; | ||
89 | for( j = 0; j < sz; j++, s++ ) | ||
90 | { | ||
91 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | ||
92 | } | ||
93 | |||
94 | return nPos; | ||
95 | } | ||
96 | |||
97 | template<> bool Bu::__cmpHashKeys<std::string>( const std::string &a, const std::string &b ) | ||
98 | { | ||
99 | return a == b; | ||
100 | } | ||
101 | |||
diff --git a/src/hash.h b/src/hash.h new file mode 100644 index 0000000..9e498f1 --- /dev/null +++ b/src/hash.h | |||
@@ -0,0 +1,745 @@ | |||
1 | #ifndef HASH_H | ||
2 | #define HASH_H | ||
3 | |||
4 | #include <stddef.h> | ||
5 | #include <string.h> | ||
6 | #include <memory> | ||
7 | #include <iostream> | ||
8 | #include <list> | ||
9 | #include <utility> | ||
10 | #include "exceptionbase.h" | ||
11 | #include "archable.h" | ||
12 | #include "archive.h" | ||
13 | |||
14 | #define bitsToBytes( n ) (n/32+(n%32>0 ? 1 : 0)) | ||
15 | |||
16 | namespace Bu | ||
17 | { | ||
18 | subExceptionDecl( HashException ) | ||
19 | |||
20 | enum eHashException | ||
21 | { | ||
22 | excodeNotFilled | ||
23 | }; | ||
24 | |||
25 | template<typename T> | ||
26 | uint32_t __calcHashCode( const T &k ); | ||
27 | |||
28 | template<typename T> | ||
29 | bool __cmpHashKeys( const T &a, const T &b ); | ||
30 | |||
31 | struct __calcNextTSize_fast | ||
32 | { | ||
33 | uint32_t operator()( uint32_t nCapacity, uint32_t nFill, uint32_t nDeleted ) const | ||
34 | { | ||
35 | if( nDeleted >= nCapacity/2 ) | ||
36 | return nCapacity; | ||
37 | return nCapacity*2+1; | ||
38 | } | ||
39 | }; | ||
40 | |||
41 | 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> > | ||
42 | class Hash; | ||
43 | |||
44 | 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> > | ||
45 | struct HashProxy | ||
46 | { | ||
47 | friend class Hash<key, _value, sizecalc, keyalloc, valuealloc, challoc>; | ||
48 | private: | ||
49 | HashProxy( Hash<key, _value, sizecalc, keyalloc, valuealloc, challoc> &h, key *k, uint32_t nPos, uint32_t hash ) : | ||
50 | hsh( h ), | ||
51 | pKey( k ), | ||
52 | nPos( nPos ), | ||
53 | hash( hash ), | ||
54 | bFilled( false ) | ||
55 | { | ||
56 | } | ||
57 | |||
58 | HashProxy( Hash<key, _value, sizecalc, keyalloc, valuealloc, challoc> &h, uint32_t nPos, _value *pValue ) : | ||
59 | hsh( h ), | ||
60 | nPos( nPos ), | ||
61 | pValue( pValue ), | ||
62 | bFilled( true ) | ||
63 | { | ||
64 | } | ||
65 | |||
66 | Hash<key, _value, sizecalc, keyalloc, valuealloc, challoc> &hsh; | ||
67 | key *pKey; | ||
68 | uint32_t nPos; | ||
69 | _value *pValue; | ||
70 | uint32_t hash; | ||
71 | bool bFilled; | ||
72 | |||
73 | public: | ||
74 | operator _value &() | ||
75 | { | ||
76 | if( bFilled == false ) | ||
77 | throw HashException( | ||
78 | excodeNotFilled, | ||
79 | "No data assosiated with that key." | ||
80 | ); | ||
81 | return *pValue; | ||
82 | } | ||
83 | |||
84 | _value &value() | ||
85 | { | ||
86 | if( bFilled == false ) | ||
87 | throw HashException( | ||
88 | excodeNotFilled, | ||
89 | "No data assosiated with that key." | ||
90 | ); | ||
91 | return *pValue; | ||
92 | } | ||
93 | |||
94 | bool isFilled() | ||
95 | { | ||
96 | return bFilled; | ||
97 | } | ||
98 | |||
99 | void erase() | ||
100 | { | ||
101 | if( bFilled ) | ||
102 | { | ||
103 | hsh._erase( nPos ); | ||
104 | hsh.onDelete(); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | _value operator=( _value nval ) | ||
109 | { | ||
110 | if( bFilled ) | ||
111 | { | ||
112 | hsh.va.destroy( pValue ); | ||
113 | hsh.va.construct( pValue, nval ); | ||
114 | hsh.onUpdate(); | ||
115 | } | ||
116 | else | ||
117 | { | ||
118 | hsh.fill( nPos, *pKey, nval, hash ); | ||
119 | hsh.onInsert(); | ||
120 | } | ||
121 | |||
122 | return nval; | ||
123 | } | ||
124 | |||
125 | _value *operator->() | ||
126 | { | ||
127 | if( bFilled == false ) | ||
128 | throw HashException( | ||
129 | excodeNotFilled, | ||
130 | "No data assosiated with that key." | ||
131 | ); | ||
132 | return pValue; | ||
133 | } | ||
134 | }; | ||
135 | |||
136 | template<typename key, typename value, typename sizecalc, typename keyalloc, typename valuealloc, typename challoc > | ||
137 | class Hash | ||
138 | { | ||
139 | friend struct HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc>; | ||
140 | public: | ||
141 | Hash() : | ||
142 | nCapacity( 11 ), | ||
143 | nFilled( 0 ), | ||
144 | nDeleted( 0 ), | ||
145 | bFilled( NULL ), | ||
146 | bDeleted( NULL ), | ||
147 | aKeys( NULL ), | ||
148 | aValues( NULL ), | ||
149 | aHashCodes( NULL ) | ||
150 | { | ||
151 | nKeysSize = bitsToBytes( nCapacity ); | ||
152 | bFilled = ca.allocate( nKeysSize ); | ||
153 | bDeleted = ca.allocate( nKeysSize ); | ||
154 | clearBits(); | ||
155 | |||
156 | aHashCodes = ca.allocate( nCapacity ); | ||
157 | aKeys = ka.allocate( nCapacity ); | ||
158 | aValues = va.allocate( nCapacity ); | ||
159 | } | ||
160 | |||
161 | Hash( const Hash &src ) : | ||
162 | nCapacity( src.nCapacity ), | ||
163 | nFilled( 0 ), | ||
164 | nDeleted( 0 ), | ||
165 | bFilled( NULL ), | ||
166 | bDeleted( NULL ), | ||
167 | aKeys( NULL ), | ||
168 | aValues( NULL ), | ||
169 | aHashCodes( NULL ) | ||
170 | { | ||
171 | nKeysSize = bitsToBytes( nCapacity ); | ||
172 | bFilled = ca.allocate( nKeysSize ); | ||
173 | bDeleted = ca.allocate( nKeysSize ); | ||
174 | clearBits(); | ||
175 | |||
176 | aHashCodes = ca.allocate( nCapacity ); | ||
177 | aKeys = ka.allocate( nCapacity ); | ||
178 | aValues = va.allocate( nCapacity ); | ||
179 | |||
180 | for( uint32_t j = 0; j < src.nCapacity; j++ ) | ||
181 | { | ||
182 | if( src.isFilled( j ) ) | ||
183 | { | ||
184 | insert( src.aKeys[j], src.aValues[j] ); | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | |||
189 | Hash &operator=( const Hash &src ) | ||
190 | { | ||
191 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
192 | { | ||
193 | if( isFilled( j ) ) | ||
194 | if( !isDeleted( j ) ) | ||
195 | { | ||
196 | va.destroy( &aValues[j] ); | ||
197 | ka.destroy( &aKeys[j] ); | ||
198 | } | ||
199 | } | ||
200 | va.deallocate( aValues, nCapacity ); | ||
201 | ka.deallocate( aKeys, nCapacity ); | ||
202 | ca.deallocate( bFilled, nKeysSize ); | ||
203 | ca.deallocate( bDeleted, nKeysSize ); | ||
204 | ca.deallocate( aHashCodes, nCapacity ); | ||
205 | |||
206 | nFilled = 0; | ||
207 | nDeleted = 0; | ||
208 | nCapacity = src.nCapacity; | ||
209 | nKeysSize = bitsToBytes( nCapacity ); | ||
210 | bFilled = ca.allocate( nKeysSize ); | ||
211 | bDeleted = ca.allocate( nKeysSize ); | ||
212 | clearBits(); | ||
213 | |||
214 | aHashCodes = ca.allocate( nCapacity ); | ||
215 | aKeys = ka.allocate( nCapacity ); | ||
216 | aValues = va.allocate( nCapacity ); | ||
217 | |||
218 | for( uint32_t j = 0; j < src.nCapacity; j++ ) | ||
219 | { | ||
220 | if( src.isFilled( j ) ) | ||
221 | { | ||
222 | insert( src.aKeys[j], src.aValues[j] ); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | return *this; | ||
227 | } | ||
228 | |||
229 | virtual ~Hash() | ||
230 | { | ||
231 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
232 | { | ||
233 | if( isFilled( j ) ) | ||
234 | if( !isDeleted( j ) ) | ||
235 | { | ||
236 | va.destroy( &aValues[j] ); | ||
237 | ka.destroy( &aKeys[j] ); | ||
238 | } | ||
239 | } | ||
240 | va.deallocate( aValues, nCapacity ); | ||
241 | ka.deallocate( aKeys, nCapacity ); | ||
242 | ca.deallocate( bFilled, nKeysSize ); | ||
243 | ca.deallocate( bDeleted, nKeysSize ); | ||
244 | ca.deallocate( aHashCodes, nCapacity ); | ||
245 | } | ||
246 | |||
247 | uint32_t getCapacity() | ||
248 | { | ||
249 | return nCapacity; | ||
250 | } | ||
251 | |||
252 | uint32_t getFill() | ||
253 | { | ||
254 | return nFilled; | ||
255 | } | ||
256 | |||
257 | uint32_t size() | ||
258 | { | ||
259 | return nFilled-nDeleted; | ||
260 | } | ||
261 | |||
262 | uint32_t getDeleted() | ||
263 | { | ||
264 | return nDeleted; | ||
265 | } | ||
266 | |||
267 | virtual HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc> operator[]( key k ) | ||
268 | { | ||
269 | uint32_t hash = __calcHashCode( k ); | ||
270 | bool bFill; | ||
271 | uint32_t nPos = probe( hash, k, bFill ); | ||
272 | |||
273 | if( bFill ) | ||
274 | { | ||
275 | return HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc>( *this, nPos, &aValues[nPos] ); | ||
276 | } | ||
277 | else | ||
278 | { | ||
279 | return HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc>( *this, &k, nPos, hash ); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | virtual void insert( key k, value v ) | ||
284 | { | ||
285 | uint32_t hash = __calcHashCode( k ); | ||
286 | bool bFill; | ||
287 | uint32_t nPos = probe( hash, k, bFill ); | ||
288 | |||
289 | if( bFill ) | ||
290 | { | ||
291 | va.destroy( &aValues[nPos] ); | ||
292 | va.construct( &aValues[nPos], v ); | ||
293 | onUpdate(); | ||
294 | } | ||
295 | else | ||
296 | { | ||
297 | fill( nPos, k, v, hash ); | ||
298 | onInsert(); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | virtual void erase( key k ) | ||
303 | { | ||
304 | uint32_t hash = __calcHashCode( k ); | ||
305 | bool bFill; | ||
306 | uint32_t nPos = probe( hash, k, bFill ); | ||
307 | |||
308 | if( bFill ) | ||
309 | { | ||
310 | _erase( nPos ); | ||
311 | onDelete(); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | struct iterator; | ||
316 | virtual void erase( struct iterator &i ) | ||
317 | { | ||
318 | if( this != &i.hsh ) | ||
319 | throw HashException("This iterator didn't come from this Hash."); | ||
320 | if( isFilled( i.nPos ) && !isDeleted( i.nPos ) ) | ||
321 | { | ||
322 | _erase( i.nPos ); | ||
323 | onDelete(); | ||
324 | } | ||
325 | } | ||
326 | |||
327 | virtual void clear() | ||
328 | { | ||
329 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
330 | { | ||
331 | if( isFilled( j ) ) | ||
332 | if( !isDeleted( j ) ) | ||
333 | { | ||
334 | va.destroy( &aValues[j] ); | ||
335 | ka.destroy( &aKeys[j] ); | ||
336 | onDelete(); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | clearBits(); | ||
341 | } | ||
342 | |||
343 | virtual value &get( key k ) | ||
344 | { | ||
345 | uint32_t hash = __calcHashCode( k ); | ||
346 | bool bFill; | ||
347 | uint32_t nPos = probe( hash, k, bFill ); | ||
348 | |||
349 | if( bFill ) | ||
350 | { | ||
351 | return aValues[nPos]; | ||
352 | } | ||
353 | else | ||
354 | { | ||
355 | throw HashException( | ||
356 | excodeNotFilled, | ||
357 | "No data assosiated with that key." | ||
358 | ); | ||
359 | } | ||
360 | } | ||
361 | |||
362 | virtual bool has( key k ) | ||
363 | { | ||
364 | bool bFill; | ||
365 | probe( __calcHashCode( k ), k, bFill, false ); | ||
366 | |||
367 | return bFill; | ||
368 | } | ||
369 | |||
370 | typedef struct iterator | ||
371 | { | ||
372 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | ||
373 | private: | ||
374 | iterator( Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &hsh ) : | ||
375 | hsh( hsh ), | ||
376 | nPos( 0 ), | ||
377 | bFinished( false ) | ||
378 | { | ||
379 | nPos = hsh.getFirstPos( bFinished ); | ||
380 | } | ||
381 | |||
382 | iterator( Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &hsh, bool bDone ) : | ||
383 | hsh( hsh ), | ||
384 | nPos( 0 ), | ||
385 | bFinished( bDone ) | ||
386 | { | ||
387 | } | ||
388 | |||
389 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &hsh; | ||
390 | uint32_t nPos; | ||
391 | bool bFinished; | ||
392 | |||
393 | public: | ||
394 | iterator operator++( int ) | ||
395 | { | ||
396 | if( bFinished == false ) | ||
397 | nPos = hsh.getNextPos( nPos, bFinished ); | ||
398 | |||
399 | return *this; | ||
400 | } | ||
401 | |||
402 | iterator operator++() | ||
403 | { | ||
404 | if( bFinished == false ) | ||
405 | nPos = hsh.getNextPos( nPos, bFinished ); | ||
406 | |||
407 | return *this; | ||
408 | } | ||
409 | |||
410 | bool operator==( const iterator &oth ) | ||
411 | { | ||
412 | if( bFinished != oth.bFinished ) | ||
413 | return false; | ||
414 | if( bFinished == true ) | ||
415 | { | ||
416 | return true; | ||
417 | } | ||
418 | else | ||
419 | { | ||
420 | if( oth.nPos == nPos ) | ||
421 | return true; | ||
422 | return false; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | bool operator!=( const iterator &oth ) | ||
427 | { | ||
428 | return !(*this == oth ); | ||
429 | } | ||
430 | |||
431 | iterator operator=( const iterator &oth ) | ||
432 | { | ||
433 | if( &hsh != &oth.hsh ) | ||
434 | throw HashException( | ||
435 | "Cannot mix iterators from different hash objects."); | ||
436 | nPos = oth.nPos; | ||
437 | bFinished = oth.bFinished; | ||
438 | } | ||
439 | |||
440 | std::pair<key,value> operator *() | ||
441 | { | ||
442 | return hsh.getAtPos( nPos ); | ||
443 | } | ||
444 | |||
445 | key &getKey() | ||
446 | { | ||
447 | return hsh.getKeyAtPos( nPos ); | ||
448 | } | ||
449 | |||
450 | value &getValue() | ||
451 | { | ||
452 | return hsh.getValueAtPos( nPos ); | ||
453 | } | ||
454 | }; | ||
455 | |||
456 | iterator begin() | ||
457 | { | ||
458 | return iterator( *this ); | ||
459 | } | ||
460 | |||
461 | iterator end() | ||
462 | { | ||
463 | return iterator( *this, true ); | ||
464 | } | ||
465 | |||
466 | std::list<key> getKeys() | ||
467 | { | ||
468 | std::list<key> lKeys; | ||
469 | |||
470 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
471 | { | ||
472 | if( isFilled( j ) ) | ||
473 | { | ||
474 | if( !isDeleted( j ) ) | ||
475 | { | ||
476 | lKeys.push_back( aKeys[j] ); | ||
477 | } | ||
478 | } | ||
479 | } | ||
480 | |||
481 | return lKeys; | ||
482 | } | ||
483 | |||
484 | protected: | ||
485 | virtual void onInsert() {} | ||
486 | virtual void onUpdate() {} | ||
487 | virtual void onDelete() {} | ||
488 | virtual void onReHash() {} | ||
489 | |||
490 | virtual void clearBits() | ||
491 | { | ||
492 | for( uint32_t j = 0; j < nKeysSize; j++ ) | ||
493 | { | ||
494 | bFilled[j] = bDeleted[j] = 0; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | virtual void fill( uint32_t loc, key &k, value &v, uint32_t hash ) | ||
499 | { | ||
500 | bFilled[loc/32] |= (1<<(loc%32)); | ||
501 | va.construct( &aValues[loc], v ); | ||
502 | ka.construct( &aKeys[loc], k ); | ||
503 | aHashCodes[loc] = hash; | ||
504 | nFilled++; | ||
505 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | ||
506 | // nFilled, nDeleted, nCapacity ); | ||
507 | } | ||
508 | |||
509 | virtual void _erase( uint32_t loc ) | ||
510 | { | ||
511 | bDeleted[loc/32] |= (1<<(loc%32)); | ||
512 | va.destroy( &aValues[loc] ); | ||
513 | ka.destroy( &aKeys[loc] ); | ||
514 | nDeleted++; | ||
515 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | ||
516 | // nFilled, nDeleted, nCapacity ); | ||
517 | } | ||
518 | |||
519 | virtual std::pair<key,value> getAtPos( uint32_t nPos ) | ||
520 | { | ||
521 | return std::pair<key,value>(aKeys[nPos],aValues[nPos]); | ||
522 | } | ||
523 | |||
524 | virtual key &getKeyAtPos( uint32_t nPos ) | ||
525 | { | ||
526 | return aKeys[nPos]; | ||
527 | } | ||
528 | |||
529 | virtual value &getValueAtPos( uint32_t nPos ) | ||
530 | { | ||
531 | return aValues[nPos]; | ||
532 | } | ||
533 | |||
534 | virtual uint32_t getFirstPos( bool &bFinished ) | ||
535 | { | ||
536 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
537 | { | ||
538 | if( isFilled( j ) ) | ||
539 | if( !isDeleted( j ) ) | ||
540 | return j; | ||
541 | } | ||
542 | |||
543 | bFinished = true; | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | virtual uint32_t getNextPos( uint32_t nPos, bool &bFinished ) | ||
548 | { | ||
549 | for( uint32_t j = nPos+1; j < nCapacity; j++ ) | ||
550 | { | ||
551 | if( isFilled( j ) ) | ||
552 | if( !isDeleted( j ) ) | ||
553 | return j; | ||
554 | } | ||
555 | |||
556 | bFinished = true; | ||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | uint32_t probe( uint32_t hash, key k, bool &bFill, bool rehash=true ) | ||
561 | { | ||
562 | uint32_t nCur = hash%nCapacity; | ||
563 | |||
564 | // First we scan to see if the key is already there, abort if we | ||
565 | // run out of probing room, or we find a non-filled entry | ||
566 | for( int8_t j = 0; | ||
567 | isFilled( nCur ) && j < 32; | ||
568 | nCur = (nCur + (1<<j))%nCapacity, j++ | ||
569 | ) | ||
570 | { | ||
571 | // Is this the same hash code we were looking for? | ||
572 | if( hash == aHashCodes[nCur] ) | ||
573 | { | ||
574 | // Skip over deleted entries. Deleted entries are also filled, | ||
575 | // so we only have to do this check here. | ||
576 | if( isDeleted( nCur ) ) | ||
577 | continue; | ||
578 | |||
579 | // Is it really the same key? (for safety) | ||
580 | if( __cmpHashKeys( aKeys[nCur], k ) == true ) | ||
581 | { | ||
582 | bFill = true; | ||
583 | return nCur; | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | // This is our insurance, if the table is full, then go ahead and | ||
589 | // rehash, then try again. | ||
590 | if( isFilled( nCur ) && rehash == true ) | ||
591 | { | ||
592 | reHash( szCalc(getCapacity(), getFill(), getDeleted()) ); | ||
593 | |||
594 | // This is potentially dangerous, and could cause an infinite loop. | ||
595 | // Be careful writing probe, eh? | ||
596 | return probe( hash, k, bFill ); | ||
597 | } | ||
598 | |||
599 | bFill = false; | ||
600 | return nCur; | ||
601 | } | ||
602 | |||
603 | void reHash( uint32_t nNewSize ) | ||
604 | { | ||
605 | //printf("---REHASH---"); | ||
606 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | ||
607 | // nFilled, nDeleted, nCapacity ); | ||
608 | |||
609 | // Save all the old data | ||
610 | uint32_t nOldCapacity = nCapacity; | ||
611 | uint32_t *bOldFilled = bFilled; | ||
612 | uint32_t *aOldHashCodes = aHashCodes; | ||
613 | uint32_t nOldKeysSize = nKeysSize; | ||
614 | uint32_t *bOldDeleted = bDeleted; | ||
615 | value *aOldValues = aValues; | ||
616 | key *aOldKeys = aKeys; | ||
617 | |||
618 | // Calculate new sizes | ||
619 | nCapacity = nNewSize; | ||
620 | nKeysSize = bitsToBytes( nCapacity ); | ||
621 | |||
622 | // Allocate new memory + prep | ||
623 | bFilled = ca.allocate( nKeysSize ); | ||
624 | bDeleted = ca.allocate( nKeysSize ); | ||
625 | clearBits(); | ||
626 | |||
627 | aHashCodes = ca.allocate( nCapacity ); | ||
628 | aKeys = ka.allocate( nCapacity ); | ||
629 | aValues = va.allocate( nCapacity ); | ||
630 | |||
631 | nDeleted = nFilled = 0; | ||
632 | |||
633 | // Re-insert all of the old data (except deleted items) | ||
634 | for( uint32_t j = 0; j < nOldCapacity; j++ ) | ||
635 | { | ||
636 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && | ||
637 | (bOldDeleted[j/32]&(1<<(j%32)))==0 ) | ||
638 | { | ||
639 | insert( aOldKeys[j], aOldValues[j] ); | ||
640 | } | ||
641 | } | ||
642 | |||
643 | // Delete all of the old data | ||
644 | for( uint32_t j = 0; j < nOldCapacity; j++ ) | ||
645 | { | ||
646 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 ) | ||
647 | { | ||
648 | va.destroy( &aOldValues[j] ); | ||
649 | ka.destroy( &aOldKeys[j] ); | ||
650 | } | ||
651 | } | ||
652 | va.deallocate( aOldValues, nOldCapacity ); | ||
653 | ka.deallocate( aOldKeys, nOldCapacity ); | ||
654 | ca.deallocate( bOldFilled, nOldKeysSize ); | ||
655 | ca.deallocate( bOldDeleted, nOldKeysSize ); | ||
656 | ca.deallocate( aOldHashCodes, nOldCapacity ); | ||
657 | } | ||
658 | |||
659 | virtual bool isFilled( uint32_t loc ) const | ||
660 | { | ||
661 | return (bFilled[loc/32]&(1<<(loc%32)))!=0; | ||
662 | } | ||
663 | |||
664 | virtual bool isDeleted( uint32_t loc ) | ||
665 | { | ||
666 | return (bDeleted[loc/32]&(1<<(loc%32)))!=0; | ||
667 | } | ||
668 | |||
669 | protected: | ||
670 | uint32_t nCapacity; | ||
671 | uint32_t nFilled; | ||
672 | uint32_t nDeleted; | ||
673 | uint32_t *bFilled; | ||
674 | uint32_t *bDeleted; | ||
675 | uint32_t nKeysSize; | ||
676 | key *aKeys; | ||
677 | value *aValues; | ||
678 | uint32_t *aHashCodes; | ||
679 | valuealloc va; | ||
680 | keyalloc ka; | ||
681 | challoc ca; | ||
682 | sizecalc szCalc; | ||
683 | }; | ||
684 | |||
685 | template<> uint32_t __calcHashCode<int>( const int &k ); | ||
686 | template<> bool __cmpHashKeys<int>( const int &a, const int &b ); | ||
687 | |||
688 | template<> uint32_t __calcHashCode<unsigned int>( const unsigned int &k ); | ||
689 | template<> bool __cmpHashKeys<unsigned int>( const unsigned int &a, const unsigned int &b ); | ||
690 | |||
691 | template<> uint32_t __calcHashCode<const char *>( const char * const &k ); | ||
692 | template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b ); | ||
693 | |||
694 | template<> uint32_t __calcHashCode<char *>( char * const &k ); | ||
695 | template<> bool __cmpHashKeys<char *>( char * const &a, char * const &b ); | ||
696 | |||
697 | template<> uint32_t __calcHashCode<std::string>( const std::string &k ); | ||
698 | template<> bool __cmpHashKeys<std::string>( const std::string &a, const std::string &b ); | ||
699 | |||
700 | template<typename key, typename value> | ||
701 | Archive &operator<<( Archive &ar, Hash<key,value> &h ) | ||
702 | { | ||
703 | ar << h.size(); | ||
704 | for( typename Hash<key,value>::iterator i = h.begin(); i != h.end(); i++ ) | ||
705 | { | ||
706 | std::pair<key,value> p = *i; | ||
707 | ar << p.first << p.second; | ||
708 | } | ||
709 | |||
710 | return ar; | ||
711 | } | ||
712 | |||
713 | template<typename key, typename value> | ||
714 | Archive &operator>>( Archive &ar, Hash<key,value> &h ) | ||
715 | { | ||
716 | h.clear(); | ||
717 | uint32_t nSize; | ||
718 | ar >> nSize; | ||
719 | |||
720 | for( uint32_t j = 0; j < nSize; j++ ) | ||
721 | { | ||
722 | key k; value v; | ||
723 | ar >> k >> v; | ||
724 | h.insert( k, v ); | ||
725 | } | ||
726 | |||
727 | return ar; | ||
728 | } | ||
729 | |||
730 | /* | ||
731 | template<typename key, typename value> | ||
732 | Serializer &operator&&( Serializer &ar, Hash<key,value> &h ) | ||
733 | { | ||
734 | if( ar.isLoading() ) | ||
735 | { | ||
736 | return ar >> h; | ||
737 | } | ||
738 | else | ||
739 | { | ||
740 | return ar << h; | ||
741 | } | ||
742 | }*/ | ||
743 | } | ||
744 | |||
745 | #endif | ||
diff --git a/src/old/exceptionbase.h b/src/old/exceptionbase.h deleted file mode 100644 index 6f1eca7..0000000 --- a/src/old/exceptionbase.h +++ /dev/null | |||
@@ -1,105 +0,0 @@ | |||
1 | #ifndef EXCEPTION_BASE_H | ||
2 | #define EXCEPTION_BASE_H | ||
3 | |||
4 | #include <string> | ||
5 | #include <exception> | ||
6 | #include <stdarg.h> | ||
7 | |||
8 | /** | ||
9 | * A generalized Exception base class. This is nice for making general and | ||
10 | * flexible child classes that can create new error code classes. | ||
11 | */ | ||
12 | class ExceptionBase : public std::exception | ||
13 | { | ||
14 | public: | ||
15 | /** | ||
16 | * Construct an exception with an error code of zero, but with a | ||
17 | * description. The use of this is not reccomended most of the time, it's | ||
18 | * generally best to include an error code with the exception so your | ||
19 | * program can handle the exception in a better way. | ||
20 | * @param sFormat The format of the text. See printf for more info. | ||
21 | */ | ||
22 | ExceptionBase( const char *sFormat, ... ) throw(); | ||
23 | |||
24 | /** | ||
25 | * | ||
26 | * @param nCode | ||
27 | * @param sFormat | ||
28 | */ | ||
29 | ExceptionBase( int nCode, const char *sFormat, ... ) throw(); | ||
30 | |||
31 | /** | ||
32 | * | ||
33 | * @param nCode | ||
34 | * @return | ||
35 | */ | ||
36 | ExceptionBase( int nCode=0 ) throw(); | ||
37 | |||
38 | /** | ||
39 | * | ||
40 | * @return | ||
41 | */ | ||
42 | virtual ~ExceptionBase() throw(); | ||
43 | |||
44 | /** | ||
45 | * | ||
46 | * @return | ||
47 | */ | ||
48 | virtual const char *what() const throw(); | ||
49 | |||
50 | /** | ||
51 | * | ||
52 | * @return | ||
53 | */ | ||
54 | int getErrorCode(); | ||
55 | |||
56 | /** | ||
57 | * | ||
58 | * @param lpFormat | ||
59 | * @param vargs | ||
60 | */ | ||
61 | void setWhat( const char *lpFormat, va_list &vargs ); | ||
62 | |||
63 | /** | ||
64 | * | ||
65 | * @param lpText | ||
66 | */ | ||
67 | void setWhat( const char *lpText ); | ||
68 | |||
69 | private: | ||
70 | int nErrorCode; /**< The code for the error that occured. */ | ||
71 | char *sWhat; /**< The text string telling people what went wrong. */ | ||
72 | }; | ||
73 | |||
74 | #define subExceptionDecl( name ) \ | ||
75 | class name : public ExceptionBase \ | ||
76 | { \ | ||
77 | public: \ | ||
78 | name( const char *sFormat, ... ) throw (); \ | ||
79 | name( int nCode, const char *sFormat, ... ) throw(); \ | ||
80 | name( int nCode=0 ) throw (); \ | ||
81 | }; | ||
82 | |||
83 | #define subExceptionDef( name ) \ | ||
84 | name::name( const char *lpFormat, ... ) throw() : \ | ||
85 | ExceptionBase( 0 ) \ | ||
86 | { \ | ||
87 | va_list ap; \ | ||
88 | va_start( ap, lpFormat ); \ | ||
89 | setWhat( lpFormat, ap ); \ | ||
90 | va_end( ap ); \ | ||
91 | } \ | ||
92 | name::name( int nCode, const char *lpFormat, ... ) throw() : \ | ||
93 | ExceptionBase( nCode ) \ | ||
94 | { \ | ||
95 | va_list ap; \ | ||
96 | va_start( ap, lpFormat ); \ | ||
97 | setWhat( lpFormat, ap ); \ | ||
98 | va_end( ap ); \ | ||
99 | } \ | ||
100 | name::name( int nCode ) throw() : \ | ||
101 | ExceptionBase( nCode ) \ | ||
102 | { \ | ||
103 | } | ||
104 | |||
105 | #endif | ||
diff --git a/src/old/exceptions.cpp b/src/old/exceptions.cpp deleted file mode 100644 index ce79a5e..0000000 --- a/src/old/exceptions.cpp +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | #include "exceptions.h" | ||
2 | #include <stdarg.h> | ||
3 | |||
4 | subExceptionDef( XmlException ) | ||
5 | subExceptionDef( FileException ) | ||
6 | subExceptionDef( ConnectionException ) | ||
7 | subExceptionDef( PluginException ) | ||
8 | |||
diff --git a/src/old/exceptions.h b/src/old/exceptions.h deleted file mode 100644 index 0ab2b15..0000000 --- a/src/old/exceptions.h +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | #ifndef EXCEPTIONS_H | ||
2 | #define EXCEPTIONS_H | ||
3 | |||
4 | #include "exceptionbase.h" | ||
5 | #include <stdarg.h> | ||
6 | |||
7 | subExceptionDecl( XmlException ) | ||
8 | subExceptionDecl( FileException ) | ||
9 | subExceptionDecl( ConnectionException ) | ||
10 | subExceptionDecl( PluginException ) | ||
11 | |||
12 | enum eFileException | ||
13 | { | ||
14 | excodeEOF | ||
15 | }; | ||
16 | |||
17 | enum eConnectionException | ||
18 | { | ||
19 | excodeReadError, | ||
20 | excodeBadReadError, | ||
21 | excodeConnectionClosed, | ||
22 | excodeSocketTimeout | ||
23 | }; | ||
24 | |||
25 | #endif | ||
diff --git a/src/old/fstring.cpp b/src/old/fstring.cpp deleted file mode 100644 index 82d024d..0000000 --- a/src/old/fstring.cpp +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | #include "fstring.h" | ||
2 | #include "hash.h" | ||
3 | |||
4 | template<> uint32_t __calcHashCode<FString>( const FString &k ) | ||
5 | { | ||
6 | return __calcHashCode( k.c_str() ); | ||
7 | } | ||
8 | |||
9 | template<> bool __cmpHashKeys<FString>( const FString &a, const FString &b ) | ||
10 | { | ||
11 | return a == b; | ||
12 | } | ||
13 | |||
diff --git a/src/old/fstring.h b/src/old/fstring.h deleted file mode 100644 index c5397cc..0000000 --- a/src/old/fstring.h +++ /dev/null | |||
@@ -1,651 +0,0 @@ | |||
1 | #ifndef F_STRING_H | ||
2 | #define F_STRING_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <memory> | ||
6 | #include "serializable.h" | ||
7 | #include "serializer.h" | ||
8 | |||
9 | template< typename chr > | ||
10 | struct FStringChunk | ||
11 | { | ||
12 | long nLength; | ||
13 | chr *pData; | ||
14 | FStringChunk *pNext; | ||
15 | }; | ||
16 | |||
17 | /** | ||
18 | * Flexible String class. This class was designed with string passing and | ||
19 | * generation in mind. Like the standard string class you can specify what | ||
20 | * datatype to use for each character. Unlike the standard string class, | ||
21 | * collection of appended and prepended terms is done lazily, making long | ||
22 | * operations that involve many appends very inexpensive. In addition internal | ||
23 | * ref-counting means that if you pass strings around between functions there's | ||
24 | * almost no overhead in time or memory since a reference is created and no | ||
25 | * data is actually copied. This also means that you never need to put any | ||
26 | * FBasicString into a ref-counting container class. | ||
27 | */ | ||
28 | template< typename chr, typename chralloc=std::allocator<chr>, typename chunkalloc=std::allocator<struct FStringChunk<chr> > > | ||
29 | class FBasicString : public Serializable | ||
30 | { | ||
31 | #ifndef VALTEST | ||
32 | #define cpy( dest, src, size ) memcpy( dest, src, size*sizeof(chr) ) | ||
33 | #endif | ||
34 | private: | ||
35 | typedef struct FStringChunk<chr> Chunk; | ||
36 | typedef struct FBasicString<chr, chralloc, chunkalloc> MyType; | ||
37 | |||
38 | public: | ||
39 | FBasicString() : | ||
40 | nLength( 0 ), | ||
41 | pnRefs( NULL ), | ||
42 | pFirst( NULL ), | ||
43 | pLast( NULL ) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | FBasicString( const chr *pData ) : | ||
48 | nLength( 0 ), | ||
49 | pnRefs( NULL ), | ||
50 | pFirst( NULL ), | ||
51 | pLast( NULL ) | ||
52 | { | ||
53 | append( pData ); | ||
54 | } | ||
55 | |||
56 | FBasicString( const chr *pData, long nLength ) : | ||
57 | nLength( 0 ), | ||
58 | pnRefs( NULL ), | ||
59 | pFirst( NULL ), | ||
60 | pLast( NULL ) | ||
61 | { | ||
62 | append( pData, nLength ); | ||
63 | } | ||
64 | |||
65 | FBasicString( const MyType &rSrc ) : | ||
66 | nLength( 0 ), | ||
67 | pnRefs( NULL ), | ||
68 | pFirst( NULL ), | ||
69 | pLast( NULL ) | ||
70 | { | ||
71 | // Here we have no choice but to copy, since the other guy is a const. | ||
72 | // In the case that the source were flat, we could get a reference, it | ||
73 | // would make some things faster, but not matter in many other cases. | ||
74 | |||
75 | joinShare( rSrc ); | ||
76 | //copyFrom( rSrc ); | ||
77 | } | ||
78 | |||
79 | FBasicString( const MyType &rSrc, long nLength ) : | ||
80 | nLength( 0 ), | ||
81 | pnRefs( NULL ), | ||
82 | pFirst( NULL ), | ||
83 | pLast( NULL ) | ||
84 | { | ||
85 | append( rSrc.pFirst->pData, nLength ); | ||
86 | } | ||
87 | |||
88 | FBasicString( const MyType &rSrc, long nStart, long nLength ) : | ||
89 | nLength( 0 ), | ||
90 | pnRefs( NULL ), | ||
91 | pFirst( NULL ), | ||
92 | pLast( NULL ) | ||
93 | { | ||
94 | append( rSrc.pFirst->pData+nStart, nLength ); | ||
95 | } | ||
96 | |||
97 | FBasicString( long nSize ) : | ||
98 | nLength( nSize ), | ||
99 | pnRefs( NULL ), | ||
100 | pFirst( NULL ), | ||
101 | pLast( NULL ) | ||
102 | { | ||
103 | pFirst = pLast = newChunk( nSize ); | ||
104 | } | ||
105 | |||
106 | virtual ~FBasicString() | ||
107 | { | ||
108 | clear(); | ||
109 | } | ||
110 | |||
111 | void append( const chr *pData ) | ||
112 | { | ||
113 | long nLen; | ||
114 | for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); | ||
115 | |||
116 | Chunk *pNew = newChunk( nLen ); | ||
117 | cpy( pNew->pData, pData, nLen ); | ||
118 | |||
119 | appendChunk( pNew ); | ||
120 | } | ||
121 | |||
122 | void append( const chr *pData, long nLen ) | ||
123 | { | ||
124 | Chunk *pNew = newChunk( nLen ); | ||
125 | |||
126 | cpy( pNew->pData, pData, nLen ); | ||
127 | |||
128 | appendChunk( pNew ); | ||
129 | } | ||
130 | |||
131 | void prepend( const chr *pData ) | ||
132 | { | ||
133 | long nLen; | ||
134 | for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); | ||
135 | |||
136 | Chunk *pNew = newChunk( nLen ); | ||
137 | cpy( pNew->pData, pData, nLen ); | ||
138 | |||
139 | prependChunk( pNew ); | ||
140 | } | ||
141 | |||
142 | void prepend( const chr *pData, long nLen ) | ||
143 | { | ||
144 | Chunk *pNew = newChunk( nLen ); | ||
145 | |||
146 | cpy( pNew->pData, pData, nLen ); | ||
147 | |||
148 | prependChunk( pNew ); | ||
149 | } | ||
150 | |||
151 | void clear() | ||
152 | { | ||
153 | realClear(); | ||
154 | } | ||
155 | |||
156 | void resize( long nNewSize ) | ||
157 | { | ||
158 | if( nLength == nNewSize ) | ||
159 | return; | ||
160 | |||
161 | flatten(); | ||
162 | |||
163 | Chunk *pNew = newChunk( nNewSize ); | ||
164 | long nNewLen = (nNewSize<nLength)?(nNewSize):(nLength); | ||
165 | cpy( pNew->pData, pFirst->pData, nNewLen ); | ||
166 | pNew->pData[nNewLen] = (chr)0; | ||
167 | aChr.deallocate( pFirst->pData, pFirst->nLength+1 ); | ||
168 | aChunk.deallocate( pFirst, 1 ); | ||
169 | pFirst = pLast = pNew; | ||
170 | nLength = nNewSize; | ||
171 | } | ||
172 | |||
173 | long getSize() const | ||
174 | { | ||
175 | return nLength; | ||
176 | } | ||
177 | |||
178 | chr *getStr() | ||
179 | { | ||
180 | if( pFirst == NULL ) | ||
181 | return NULL; | ||
182 | |||
183 | flatten(); | ||
184 | return pFirst->pData; | ||
185 | } | ||
186 | |||
187 | const chr *getStr() const | ||
188 | { | ||
189 | if( pFirst == NULL ) | ||
190 | return NULL; | ||
191 | |||
192 | flatten(); | ||
193 | return pFirst->pData; | ||
194 | } | ||
195 | |||
196 | chr *c_str() | ||
197 | { | ||
198 | if( pFirst == NULL ) | ||
199 | return NULL; | ||
200 | |||
201 | flatten(); | ||
202 | return pFirst->pData; | ||
203 | } | ||
204 | |||
205 | const chr *c_str() const | ||
206 | { | ||
207 | if( pFirst == NULL ) | ||
208 | return NULL; | ||
209 | |||
210 | flatten(); | ||
211 | return pFirst->pData; | ||
212 | } | ||
213 | |||
214 | MyType &operator +=( const chr *pData ) | ||
215 | { | ||
216 | append( pData ); | ||
217 | |||
218 | return (*this); | ||
219 | } | ||
220 | |||
221 | MyType &operator +=( const MyType &rSrc ) | ||
222 | { | ||
223 | rSrc.flatten(); | ||
224 | append( rSrc.pFirst->pData, rSrc.nLength ); | ||
225 | |||
226 | return (*this); | ||
227 | } | ||
228 | |||
229 | MyType &operator +=( const chr pData ) | ||
230 | { | ||
231 | chr tmp[2] = { pData, (chr)0 }; | ||
232 | append( tmp ); | ||
233 | |||
234 | return (*this); | ||
235 | } | ||
236 | |||
237 | MyType &operator =( const chr *pData ) | ||
238 | { | ||
239 | clear(); | ||
240 | append( pData ); | ||
241 | |||
242 | return (*this); | ||
243 | } | ||
244 | |||
245 | MyType &operator =( const MyType &rSrc ) | ||
246 | { | ||
247 | //if( rSrc.isFlat() ) | ||
248 | //{ | ||
249 | joinShare( rSrc ); | ||
250 | //} | ||
251 | //else | ||
252 | //{ | ||
253 | // copyFrom( rSrc ); | ||
254 | //} | ||
255 | // | ||
256 | |||
257 | return (*this); | ||
258 | } | ||
259 | |||
260 | bool operator ==( const chr *pData ) const | ||
261 | { | ||
262 | if( pFirst == NULL ) { | ||
263 | if( pData == NULL ) | ||
264 | return true; | ||
265 | return false; | ||
266 | } | ||
267 | |||
268 | flatten(); | ||
269 | const chr *a = pData; | ||
270 | chr *b = pFirst->pData; | ||
271 | for( ; *a!=(chr)0; a++, b++ ) | ||
272 | { | ||
273 | if( *a != *b ) | ||
274 | return false; | ||
275 | } | ||
276 | |||
277 | return true; | ||
278 | } | ||
279 | |||
280 | bool operator ==( const MyType &pData ) const | ||
281 | { | ||
282 | if( pFirst == pData.pFirst ) | ||
283 | return true; | ||
284 | if( pFirst == NULL ) | ||
285 | return false; | ||
286 | |||
287 | flatten(); | ||
288 | pData.flatten(); | ||
289 | const chr *a = pData.pFirst->pData; | ||
290 | chr *b = pFirst->pData; | ||
291 | for( ; *a!=(chr)0; a++, b++ ) | ||
292 | { | ||
293 | if( *a != *b ) | ||
294 | return false; | ||
295 | } | ||
296 | |||
297 | return true; | ||
298 | } | ||
299 | |||
300 | bool operator !=(const chr *pData ) const | ||
301 | { | ||
302 | return !(*this == pData); | ||
303 | } | ||
304 | |||
305 | bool operator !=(const MyType &pData ) const | ||
306 | { | ||
307 | return !(*this == pData); | ||
308 | } | ||
309 | |||
310 | chr &operator[]( long nIndex ) | ||
311 | { | ||
312 | flatten(); | ||
313 | |||
314 | return pFirst->pData[nIndex]; | ||
315 | } | ||
316 | |||
317 | const chr &operator[]( long nIndex ) const | ||
318 | { | ||
319 | flatten(); | ||
320 | |||
321 | return pFirst->pData[nIndex]; | ||
322 | } | ||
323 | |||
324 | bool isWS( long nIndex ) const | ||
325 | { | ||
326 | flatten(); | ||
327 | |||
328 | return pFirst->pData[nIndex]==' ' || pFirst->pData[nIndex]=='\t' | ||
329 | || pFirst->pData[nIndex]=='\r' || pFirst->pData[nIndex]=='\n'; | ||
330 | } | ||
331 | |||
332 | bool isAlpha( long nIndex ) const | ||
333 | { | ||
334 | flatten(); | ||
335 | |||
336 | return (pFirst->pData[nIndex] >= 'a' && pFirst->pData[nIndex] <= 'z') | ||
337 | || (pFirst->pData[nIndex] >= 'A' && pFirst->pData[nIndex] <= 'Z'); | ||
338 | } | ||
339 | |||
340 | void toLower() | ||
341 | { | ||
342 | flatten(); | ||
343 | unShare(); | ||
344 | |||
345 | for( long j = 0; j < nLength; j++ ) | ||
346 | { | ||
347 | if( pFirst->pData[j] >= 'A' && pFirst->pData[j] <= 'Z' ) | ||
348 | pFirst->pData[j] -= 'A'-'a'; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | void toUpper() | ||
353 | { | ||
354 | flatten(); | ||
355 | unShare(); | ||
356 | |||
357 | for( long j = 0; j < nLength; j++ ) | ||
358 | { | ||
359 | if( pFirst->pData[j] >= 'a' && pFirst->pData[j] <= 'z' ) | ||
360 | pFirst->pData[j] += 'A'-'a'; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | void serialize( class Serializer &ar ) | ||
365 | { | ||
366 | if( ar.isLoading() ) | ||
367 | { | ||
368 | clear(); | ||
369 | long nLen; | ||
370 | ar >> nLen; | ||
371 | |||
372 | Chunk *pNew = newChunk( nLen ); | ||
373 | ar.read( pNew->pData, nLen*sizeof(chr) ); | ||
374 | appendChunk( pNew ); | ||
375 | } | ||
376 | else | ||
377 | { | ||
378 | flatten(); | ||
379 | |||
380 | ar << nLength; | ||
381 | ar.write( pFirst->pData, nLength*sizeof(chr) ); | ||
382 | } | ||
383 | } | ||
384 | |||
385 | private: | ||
386 | void flatten() const | ||
387 | { | ||
388 | if( isFlat() ) | ||
389 | return; | ||
390 | |||
391 | if( pFirst == NULL ) | ||
392 | return; | ||
393 | |||
394 | unShare(); | ||
395 | |||
396 | Chunk *pNew = newChunk( nLength ); | ||
397 | chr *pos = pNew->pData; | ||
398 | Chunk *i = pFirst; | ||
399 | for(;;) | ||
400 | { | ||
401 | cpy( pos, i->pData, i->nLength ); | ||
402 | pos += i->nLength; | ||
403 | i = i->pNext; | ||
404 | if( i == NULL ) | ||
405 | break; | ||
406 | } | ||
407 | realClear(); | ||
408 | |||
409 | pLast = pFirst = pNew; | ||
410 | nLength = pNew->nLength; | ||
411 | } | ||
412 | |||
413 | void realClear() const | ||
414 | { | ||
415 | if( pFirst == NULL ) | ||
416 | return; | ||
417 | |||
418 | if( isShared() ) | ||
419 | { | ||
420 | decRefs(); | ||
421 | } | ||
422 | else | ||
423 | { | ||
424 | Chunk *i = pFirst; | ||
425 | for(;;) | ||
426 | { | ||
427 | Chunk *n = i->pNext; | ||
428 | aChr.deallocate( i->pData, i->nLength+1 ); | ||
429 | aChunk.deallocate( i, 1 ); | ||
430 | if( n == NULL ) | ||
431 | break; | ||
432 | i = n; | ||
433 | } | ||
434 | pFirst = pLast = NULL; | ||
435 | nLength = 0; | ||
436 | } | ||
437 | } | ||
438 | |||
439 | void copyFrom( const FBasicString<chr, chralloc, chunkalloc> &rSrc ) | ||
440 | { | ||
441 | if( rSrc.pFirst == NULL ) | ||
442 | return; | ||
443 | |||
444 | decRefs(); | ||
445 | |||
446 | Chunk *pNew = newChunk( rSrc.nLength ); | ||
447 | chr *pos = pNew->pData; | ||
448 | Chunk *i = rSrc.pFirst; | ||
449 | for(;;) | ||
450 | { | ||
451 | cpy( pos, i->pData, i->nLength ); | ||
452 | pos += i->nLength; | ||
453 | i = i->pNext; | ||
454 | if( i == NULL ) | ||
455 | break; | ||
456 | } | ||
457 | clear(); | ||
458 | |||
459 | appendChunk( pNew ); | ||
460 | } | ||
461 | |||
462 | bool isFlat() const | ||
463 | { | ||
464 | return (pFirst == pLast); | ||
465 | } | ||
466 | |||
467 | bool isShared() const | ||
468 | { | ||
469 | return (pnRefs != NULL); | ||
470 | } | ||
471 | |||
472 | Chunk *newChunk() const | ||
473 | { | ||
474 | Chunk *pNew = aChunk.allocate( 1 ); | ||
475 | pNew->pNext = NULL; | ||
476 | return pNew; | ||
477 | } | ||
478 | |||
479 | Chunk *newChunk( long nLen ) const | ||
480 | { | ||
481 | Chunk *pNew = aChunk.allocate( 1 ); | ||
482 | pNew->pNext = NULL; | ||
483 | pNew->nLength = nLen; | ||
484 | pNew->pData = aChr.allocate( nLen+1 ); | ||
485 | pNew->pData[nLen] = (chr)0; | ||
486 | return pNew; | ||
487 | } | ||
488 | |||
489 | void appendChunk( Chunk *pNewChunk ) | ||
490 | { | ||
491 | unShare(); | ||
492 | |||
493 | if( pFirst == NULL ) | ||
494 | pLast = pFirst = pNewChunk; | ||
495 | else | ||
496 | { | ||
497 | pLast->pNext = pNewChunk; | ||
498 | pLast = pNewChunk; | ||
499 | } | ||
500 | |||
501 | nLength += pNewChunk->nLength; | ||
502 | } | ||
503 | |||
504 | void prependChunk( Chunk *pNewChunk ) | ||
505 | { | ||
506 | unShare(); | ||
507 | |||
508 | if( pFirst == NULL ) | ||
509 | pLast = pFirst = pNewChunk; | ||
510 | else | ||
511 | { | ||
512 | pNewChunk->pNext = pFirst; | ||
513 | pFirst = pNewChunk; | ||
514 | } | ||
515 | |||
516 | nLength += pNewChunk->nLength; | ||
517 | } | ||
518 | |||
519 | void joinShare( MyType &rSrc ) | ||
520 | { | ||
521 | clear(); | ||
522 | |||
523 | if( !rSrc.isFlat() ) | ||
524 | rSrc.flatten(); | ||
525 | |||
526 | rSrc.initCount(); | ||
527 | pnRefs = rSrc.pnRefs; | ||
528 | (*pnRefs)++; | ||
529 | nLength = rSrc.nLength; | ||
530 | pFirst = rSrc.pFirst; | ||
531 | pLast = rSrc.pLast; | ||
532 | } | ||
533 | |||
534 | void joinShare( const MyType &rSrc ) | ||
535 | { | ||
536 | clear(); | ||
537 | |||
538 | rSrc.flatten(); | ||
539 | |||
540 | if( !rSrc.isShared() ) | ||
541 | { | ||
542 | rSrc.pnRefs = new uint32_t; | ||
543 | (*rSrc.pnRefs) = 1; | ||
544 | } | ||
545 | pnRefs = rSrc.pnRefs; | ||
546 | (*pnRefs)++; | ||
547 | nLength = rSrc.nLength; | ||
548 | pFirst = rSrc.pFirst; | ||
549 | pLast = rSrc.pLast; | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * This takes an object that was shared and makes a copy of the base data | ||
554 | * that was being shared so that this copy can be changed. This should be | ||
555 | * added before any call that will change this object; | ||
556 | */ | ||
557 | void unShare() const | ||
558 | { | ||
559 | if( isShared() == false ) | ||
560 | return; | ||
561 | |||
562 | Chunk *pNew = newChunk( nLength ); | ||
563 | chr *pos = pNew->pData; | ||
564 | Chunk *i = pFirst; | ||
565 | for(;;) | ||
566 | { | ||
567 | cpy( pos, i->pData, i->nLength ); | ||
568 | pos += i->nLength; | ||
569 | i = i->pNext; | ||
570 | if( i == NULL ) | ||
571 | break; | ||
572 | } | ||
573 | decRefs(); | ||
574 | pLast = pFirst = pNew; | ||
575 | nLength = pNew->nLength; | ||
576 | } | ||
577 | |||
578 | /** | ||
579 | * This decrements our ref count and pulls us out of the share. If the ref | ||
580 | * count hits zero because of this, it destroys the share. This is not | ||
581 | * safe to call on it's own, it's much better to call unShare. | ||
582 | */ | ||
583 | void decRefs() const | ||
584 | { | ||
585 | if( isShared() ) | ||
586 | { | ||
587 | (*pnRefs)--; | ||
588 | if( (*pnRefs) == 0 ) | ||
589 | destroyShare(); | ||
590 | else | ||
591 | { | ||
592 | pnRefs = NULL; | ||
593 | pFirst = NULL; | ||
594 | pLast = NULL; | ||
595 | nLength = 0; | ||
596 | } | ||
597 | } | ||
598 | } | ||
599 | |||
600 | /** | ||
601 | * While the unShare function removes an instance from a share, this | ||
602 | * function destroys the data that was in the share, removing the share | ||
603 | * itself. This should only be called when the refcount for the share has | ||
604 | * or is about to reach zero. | ||
605 | */ | ||
606 | void destroyShare() const | ||
607 | { | ||
608 | delete pnRefs; | ||
609 | pnRefs = NULL; | ||
610 | realClear(); | ||
611 | } | ||
612 | |||
613 | #ifdef VALTEST | ||
614 | void cpy( chr *dest, const chr *src, long count ) const | ||
615 | { | ||
616 | for( int j = 0; j < count; j++ ) | ||
617 | { | ||
618 | *dest = *src; | ||
619 | dest++; | ||
620 | src++; | ||
621 | } | ||
622 | } | ||
623 | #endif | ||
624 | |||
625 | void initCount() const | ||
626 | { | ||
627 | if( !isShared() ) | ||
628 | { | ||
629 | pnRefs = new uint32_t; | ||
630 | (*pnRefs) = 1; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | private: | ||
635 | mutable long nLength; | ||
636 | mutable uint32_t *pnRefs; | ||
637 | mutable Chunk *pFirst; | ||
638 | mutable Chunk *pLast; | ||
639 | |||
640 | mutable chralloc aChr; | ||
641 | mutable chunkalloc aChunk; | ||
642 | }; | ||
643 | |||
644 | typedef FBasicString<char> FString; | ||
645 | |||
646 | #include "hash.h" | ||
647 | template<> uint32_t __calcHashCode<FString>( const FString &k ); | ||
648 | template<> bool __cmpHashKeys<FString>( const FString &a, const FString &b ); | ||
649 | |||
650 | |||
651 | #endif | ||
diff --git a/src/old/hash.cpp b/src/old/hash.cpp deleted file mode 100644 index c52e6b1..0000000 --- a/src/old/hash.cpp +++ /dev/null | |||
@@ -1,113 +0,0 @@ | |||
1 | #include "hash.h" | ||
2 | |||
3 | subExceptionDef( HashException ) | ||
4 | |||
5 | template<> uint32_t __calcHashCode<int>( const int &k ) | ||
6 | { | ||
7 | return k; | ||
8 | } | ||
9 | |||
10 | template<> bool __cmpHashKeys<int>( const int &a, const int &b ) | ||
11 | { | ||
12 | return a == b; | ||
13 | } | ||
14 | |||
15 | template<> uint32_t __calcHashCode<unsigned int>( const unsigned int &k ) | ||
16 | { | ||
17 | return k; | ||
18 | } | ||
19 | |||
20 | template<> bool __cmpHashKeys<unsigned int>( const unsigned int &a, const unsigned int &b ) | ||
21 | { | ||
22 | return a == b; | ||
23 | } | ||
24 | |||
25 | template<> | ||
26 | uint32_t __calcHashCode<const char *>( const char * const &k ) | ||
27 | { | ||
28 | if (k == NULL) | ||
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 | } | ||
38 | |||
39 | return nPos; | ||
40 | } | ||
41 | |||
42 | template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b ) | ||
43 | { | ||
44 | if( a == b ) | ||
45 | return true; | ||
46 | |||
47 | for(int j=0; a[j] == b[j]; j++ ) | ||
48 | if( a[j] == '\0' ) | ||
49 | return true; | ||
50 | |||
51 | return false; | ||
52 | } | ||
53 | |||
54 | template<> | ||
55 | uint32_t __calcHashCode<char *>( char * const &k ) | ||
56 | { | ||
57 | if (k == NULL) | ||
58 | { | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | unsigned long int nPos = 0; | ||
63 | for( const char *s = k; *s; s++ ) | ||
64 | { | ||
65 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | ||
66 | } | ||
67 | |||
68 | return nPos; | ||
69 | } | ||
70 | |||
71 | template<> bool __cmpHashKeys<char *>( char * const &a, char * const &b ) | ||
72 | { | ||
73 | if( a == b ) | ||
74 | return true; | ||
75 | |||
76 | for(int j=0; a[j] == b[j]; j++ ) | ||
77 | if( a[j] == '\0' ) | ||
78 | return true; | ||
79 | |||
80 | return false; | ||
81 | } | ||
82 | |||
83 | template<> uint32_t __calcHashCode<std::string>( const std::string &k ) | ||
84 | { | ||
85 | std::string::size_type j, sz = k.size(); | ||
86 | const char *s = k.c_str(); | ||
87 | |||
88 | unsigned long int nPos = 0; | ||
89 | for( j = 0; j < sz; j++, s++ ) | ||
90 | { | ||
91 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | ||
92 | } | ||
93 | |||
94 | return nPos; | ||
95 | } | ||
96 | |||
97 | template<> bool __cmpHashKeys<std::string>( const std::string &a, const std::string &b ) | ||
98 | { | ||
99 | return a == b; | ||
100 | } | ||
101 | |||
102 | template<> uint32_t __calcHashCode<Hashable>( const Hashable &k ) | ||
103 | { | ||
104 | return 0; | ||
105 | //return k.getHashCode(); | ||
106 | } | ||
107 | |||
108 | template<> bool __cmpHashKeys<Hashable>( const Hashable &a, const Hashable &b ) | ||
109 | { | ||
110 | return false; | ||
111 | //return a.compareForHash( b ); | ||
112 | } | ||
113 | |||
diff --git a/src/old/hash.h b/src/old/hash.h deleted file mode 100644 index e819379..0000000 --- a/src/old/hash.h +++ /dev/null | |||
@@ -1,744 +0,0 @@ | |||
1 | #ifndef HASH_H | ||
2 | #define HASH_H | ||
3 | |||
4 | #include <stddef.h> | ||
5 | #include <string.h> | ||
6 | #include <memory> | ||
7 | #include <iostream> | ||
8 | #include <list> | ||
9 | #include "exceptionbase.h" | ||
10 | #include "hashable.h" | ||
11 | #include "serializable.h" | ||
12 | #include "serializer.h" | ||
13 | |||
14 | #define bitsToBytes( n ) (n/32+(n%32>0 ? 1 : 0)) | ||
15 | |||
16 | subExceptionDecl( HashException ) | ||
17 | |||
18 | enum eHashException | ||
19 | { | ||
20 | excodeNotFilled | ||
21 | }; | ||
22 | |||
23 | template<typename T> | ||
24 | uint32_t __calcHashCode( const T &k ); | ||
25 | |||
26 | template<typename T> | ||
27 | bool __cmpHashKeys( const T &a, const T &b ); | ||
28 | |||
29 | struct __calcNextTSize_fast | ||
30 | { | ||
31 | uint32_t operator()( uint32_t nCapacity, uint32_t nFill, uint32_t nDeleted ) const | ||
32 | { | ||
33 | if( nDeleted >= nCapacity/2 ) | ||
34 | return nCapacity; | ||
35 | return nCapacity*2+1; | ||
36 | } | ||
37 | }; | ||
38 | |||
39 | 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> > | ||
40 | class Hash; | ||
41 | |||
42 | 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> > | ||
43 | struct HashProxy | ||
44 | { | ||
45 | friend class Hash<key, _value, sizecalc, keyalloc, valuealloc, challoc>; | ||
46 | private: | ||
47 | HashProxy( Hash<key, _value, sizecalc, keyalloc, valuealloc, challoc> &h, key *k, uint32_t nPos, uint32_t hash ) : | ||
48 | hsh( h ), | ||
49 | pKey( k ), | ||
50 | nPos( nPos ), | ||
51 | hash( hash ), | ||
52 | bFilled( false ) | ||
53 | { | ||
54 | } | ||
55 | |||
56 | HashProxy( Hash<key, _value, sizecalc, keyalloc, valuealloc, challoc> &h, uint32_t nPos, _value *pValue ) : | ||
57 | hsh( h ), | ||
58 | nPos( nPos ), | ||
59 | pValue( pValue ), | ||
60 | bFilled( true ) | ||
61 | { | ||
62 | } | ||
63 | |||
64 | Hash<key, _value, sizecalc, keyalloc, valuealloc, challoc> &hsh; | ||
65 | key *pKey; | ||
66 | uint32_t nPos; | ||
67 | _value *pValue; | ||
68 | uint32_t hash; | ||
69 | bool bFilled; | ||
70 | |||
71 | public: | ||
72 | operator _value &() | ||
73 | { | ||
74 | if( bFilled == false ) | ||
75 | throw HashException( | ||
76 | excodeNotFilled, | ||
77 | "No data assosiated with that key." | ||
78 | ); | ||
79 | return *pValue; | ||
80 | } | ||
81 | |||
82 | _value &value() | ||
83 | { | ||
84 | if( bFilled == false ) | ||
85 | throw HashException( | ||
86 | excodeNotFilled, | ||
87 | "No data assosiated with that key." | ||
88 | ); | ||
89 | return *pValue; | ||
90 | } | ||
91 | |||
92 | bool isFilled() | ||
93 | { | ||
94 | return bFilled; | ||
95 | } | ||
96 | |||
97 | void erase() | ||
98 | { | ||
99 | if( bFilled ) | ||
100 | { | ||
101 | hsh._erase( nPos ); | ||
102 | hsh.onDelete(); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | _value operator=( _value nval ) | ||
107 | { | ||
108 | if( bFilled ) | ||
109 | { | ||
110 | hsh.va.destroy( pValue ); | ||
111 | hsh.va.construct( pValue, nval ); | ||
112 | hsh.onUpdate(); | ||
113 | } | ||
114 | else | ||
115 | { | ||
116 | hsh.fill( nPos, *pKey, nval, hash ); | ||
117 | hsh.onInsert(); | ||
118 | } | ||
119 | |||
120 | return nval; | ||
121 | } | ||
122 | |||
123 | _value *operator->() | ||
124 | { | ||
125 | if( bFilled == false ) | ||
126 | throw HashException( | ||
127 | excodeNotFilled, | ||
128 | "No data assosiated with that key." | ||
129 | ); | ||
130 | return pValue; | ||
131 | } | ||
132 | }; | ||
133 | |||
134 | template<typename key, typename value, typename sizecalc, typename keyalloc, typename valuealloc, typename challoc > | ||
135 | class Hash | ||
136 | { | ||
137 | friend struct HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc>; | ||
138 | public: | ||
139 | Hash() : | ||
140 | nCapacity( 11 ), | ||
141 | nFilled( 0 ), | ||
142 | nDeleted( 0 ), | ||
143 | bFilled( NULL ), | ||
144 | bDeleted( NULL ), | ||
145 | aKeys( NULL ), | ||
146 | aValues( NULL ), | ||
147 | aHashCodes( NULL ) | ||
148 | { | ||
149 | nKeysSize = bitsToBytes( nCapacity ); | ||
150 | bFilled = ca.allocate( nKeysSize ); | ||
151 | bDeleted = ca.allocate( nKeysSize ); | ||
152 | clearBits(); | ||
153 | |||
154 | aHashCodes = ca.allocate( nCapacity ); | ||
155 | aKeys = ka.allocate( nCapacity ); | ||
156 | aValues = va.allocate( nCapacity ); | ||
157 | } | ||
158 | |||
159 | Hash( const Hash &src ) : | ||
160 | nCapacity( src.nCapacity ), | ||
161 | nFilled( 0 ), | ||
162 | nDeleted( 0 ), | ||
163 | bFilled( NULL ), | ||
164 | bDeleted( NULL ), | ||
165 | aKeys( NULL ), | ||
166 | aValues( NULL ), | ||
167 | aHashCodes( NULL ) | ||
168 | { | ||
169 | nKeysSize = bitsToBytes( nCapacity ); | ||
170 | bFilled = ca.allocate( nKeysSize ); | ||
171 | bDeleted = ca.allocate( nKeysSize ); | ||
172 | clearBits(); | ||
173 | |||
174 | aHashCodes = ca.allocate( nCapacity ); | ||
175 | aKeys = ka.allocate( nCapacity ); | ||
176 | aValues = va.allocate( nCapacity ); | ||
177 | |||
178 | for( uint32_t j = 0; j < src.nCapacity; j++ ) | ||
179 | { | ||
180 | if( src.isFilled( j ) ) | ||
181 | { | ||
182 | insert( src.aKeys[j], src.aValues[j] ); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | Hash &operator=( const Hash &src ) | ||
188 | { | ||
189 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
190 | { | ||
191 | if( isFilled( j ) ) | ||
192 | if( !isDeleted( j ) ) | ||
193 | { | ||
194 | va.destroy( &aValues[j] ); | ||
195 | ka.destroy( &aKeys[j] ); | ||
196 | } | ||
197 | } | ||
198 | va.deallocate( aValues, nCapacity ); | ||
199 | ka.deallocate( aKeys, nCapacity ); | ||
200 | ca.deallocate( bFilled, nKeysSize ); | ||
201 | ca.deallocate( bDeleted, nKeysSize ); | ||
202 | ca.deallocate( aHashCodes, nCapacity ); | ||
203 | |||
204 | nFilled = 0; | ||
205 | nDeleted = 0; | ||
206 | nCapacity = src.nCapacity; | ||
207 | nKeysSize = bitsToBytes( nCapacity ); | ||
208 | bFilled = ca.allocate( nKeysSize ); | ||
209 | bDeleted = ca.allocate( nKeysSize ); | ||
210 | clearBits(); | ||
211 | |||
212 | aHashCodes = ca.allocate( nCapacity ); | ||
213 | aKeys = ka.allocate( nCapacity ); | ||
214 | aValues = va.allocate( nCapacity ); | ||
215 | |||
216 | for( uint32_t j = 0; j < src.nCapacity; j++ ) | ||
217 | { | ||
218 | if( src.isFilled( j ) ) | ||
219 | { | ||
220 | insert( src.aKeys[j], src.aValues[j] ); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | return *this; | ||
225 | } | ||
226 | |||
227 | virtual ~Hash() | ||
228 | { | ||
229 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
230 | { | ||
231 | if( isFilled( j ) ) | ||
232 | if( !isDeleted( j ) ) | ||
233 | { | ||
234 | va.destroy( &aValues[j] ); | ||
235 | ka.destroy( &aKeys[j] ); | ||
236 | } | ||
237 | } | ||
238 | va.deallocate( aValues, nCapacity ); | ||
239 | ka.deallocate( aKeys, nCapacity ); | ||
240 | ca.deallocate( bFilled, nKeysSize ); | ||
241 | ca.deallocate( bDeleted, nKeysSize ); | ||
242 | ca.deallocate( aHashCodes, nCapacity ); | ||
243 | } | ||
244 | |||
245 | uint32_t getCapacity() | ||
246 | { | ||
247 | return nCapacity; | ||
248 | } | ||
249 | |||
250 | uint32_t getFill() | ||
251 | { | ||
252 | return nFilled; | ||
253 | } | ||
254 | |||
255 | uint32_t size() | ||
256 | { | ||
257 | return nFilled-nDeleted; | ||
258 | } | ||
259 | |||
260 | uint32_t getDeleted() | ||
261 | { | ||
262 | return nDeleted; | ||
263 | } | ||
264 | |||
265 | virtual HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc> operator[]( key k ) | ||
266 | { | ||
267 | uint32_t hash = __calcHashCode( k ); | ||
268 | bool bFill; | ||
269 | uint32_t nPos = probe( hash, k, bFill ); | ||
270 | |||
271 | if( bFill ) | ||
272 | { | ||
273 | return HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc>( *this, nPos, &aValues[nPos] ); | ||
274 | } | ||
275 | else | ||
276 | { | ||
277 | return HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc>( *this, &k, nPos, hash ); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | virtual void insert( key k, value v ) | ||
282 | { | ||
283 | uint32_t hash = __calcHashCode( k ); | ||
284 | bool bFill; | ||
285 | uint32_t nPos = probe( hash, k, bFill ); | ||
286 | |||
287 | if( bFill ) | ||
288 | { | ||
289 | va.destroy( &aValues[nPos] ); | ||
290 | va.construct( &aValues[nPos], v ); | ||
291 | onUpdate(); | ||
292 | } | ||
293 | else | ||
294 | { | ||
295 | fill( nPos, k, v, hash ); | ||
296 | onInsert(); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | virtual void erase( key k ) | ||
301 | { | ||
302 | uint32_t hash = __calcHashCode( k ); | ||
303 | bool bFill; | ||
304 | uint32_t nPos = probe( hash, k, bFill ); | ||
305 | |||
306 | if( bFill ) | ||
307 | { | ||
308 | _erase( nPos ); | ||
309 | onDelete(); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | struct iterator; | ||
314 | virtual void erase( struct iterator &i ) | ||
315 | { | ||
316 | if( this != &i.hsh ) | ||
317 | throw HashException("This iterator didn't come from this Hash."); | ||
318 | if( isFilled( i.nPos ) && !isDeleted( i.nPos ) ) | ||
319 | { | ||
320 | _erase( i.nPos ); | ||
321 | onDelete(); | ||
322 | } | ||
323 | } | ||
324 | |||
325 | virtual void clear() | ||
326 | { | ||
327 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
328 | { | ||
329 | if( isFilled( j ) ) | ||
330 | if( !isDeleted( j ) ) | ||
331 | { | ||
332 | va.destroy( &aValues[j] ); | ||
333 | ka.destroy( &aKeys[j] ); | ||
334 | onDelete(); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | clearBits(); | ||
339 | } | ||
340 | |||
341 | virtual value &get( key k ) | ||
342 | { | ||
343 | uint32_t hash = __calcHashCode( k ); | ||
344 | bool bFill; | ||
345 | uint32_t nPos = probe( hash, k, bFill ); | ||
346 | |||
347 | if( bFill ) | ||
348 | { | ||
349 | return aValues[nPos]; | ||
350 | } | ||
351 | else | ||
352 | { | ||
353 | throw HashException( | ||
354 | excodeNotFilled, | ||
355 | "No data assosiated with that key." | ||
356 | ); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | virtual bool has( key k ) | ||
361 | { | ||
362 | bool bFill; | ||
363 | probe( __calcHashCode( k ), k, bFill, false ); | ||
364 | |||
365 | return bFill; | ||
366 | } | ||
367 | |||
368 | typedef struct iterator | ||
369 | { | ||
370 | friend class Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>; | ||
371 | private: | ||
372 | iterator( Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &hsh ) : | ||
373 | hsh( hsh ), | ||
374 | nPos( 0 ), | ||
375 | bFinished( false ) | ||
376 | { | ||
377 | nPos = hsh.getFirstPos( bFinished ); | ||
378 | } | ||
379 | |||
380 | iterator( Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &hsh, bool bDone ) : | ||
381 | hsh( hsh ), | ||
382 | nPos( 0 ), | ||
383 | bFinished( bDone ) | ||
384 | { | ||
385 | } | ||
386 | |||
387 | Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> &hsh; | ||
388 | uint32_t nPos; | ||
389 | bool bFinished; | ||
390 | |||
391 | public: | ||
392 | iterator operator++( int ) | ||
393 | { | ||
394 | if( bFinished == false ) | ||
395 | nPos = hsh.getNextPos( nPos, bFinished ); | ||
396 | |||
397 | return *this; | ||
398 | } | ||
399 | |||
400 | iterator operator++() | ||
401 | { | ||
402 | if( bFinished == false ) | ||
403 | nPos = hsh.getNextPos( nPos, bFinished ); | ||
404 | |||
405 | return *this; | ||
406 | } | ||
407 | |||
408 | bool operator==( const iterator &oth ) | ||
409 | { | ||
410 | if( bFinished != oth.bFinished ) | ||
411 | return false; | ||
412 | if( bFinished == true ) | ||
413 | { | ||
414 | return true; | ||
415 | } | ||
416 | else | ||
417 | { | ||
418 | if( oth.nPos == nPos ) | ||
419 | return true; | ||
420 | return false; | ||
421 | } | ||
422 | } | ||
423 | |||
424 | bool operator!=( const iterator &oth ) | ||
425 | { | ||
426 | return !(*this == oth ); | ||
427 | } | ||
428 | |||
429 | iterator operator=( const iterator &oth ) | ||
430 | { | ||
431 | if( &hsh != &oth.hsh ) | ||
432 | throw HashException( | ||
433 | "Cannot mix iterators from different hash objects."); | ||
434 | nPos = oth.nPos; | ||
435 | bFinished = oth.bFinished; | ||
436 | } | ||
437 | |||
438 | std::pair<key,value> operator *() | ||
439 | { | ||
440 | return hsh.getAtPos( nPos ); | ||
441 | } | ||
442 | |||
443 | key &getKey() | ||
444 | { | ||
445 | return hsh.getKeyAtPos( nPos ); | ||
446 | } | ||
447 | |||
448 | value &getValue() | ||
449 | { | ||
450 | return hsh.getValueAtPos( nPos ); | ||
451 | } | ||
452 | }; | ||
453 | |||
454 | iterator begin() | ||
455 | { | ||
456 | return iterator( *this ); | ||
457 | } | ||
458 | |||
459 | iterator end() | ||
460 | { | ||
461 | return iterator( *this, true ); | ||
462 | } | ||
463 | |||
464 | std::list<key> getKeys() | ||
465 | { | ||
466 | std::list<key> lKeys; | ||
467 | |||
468 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
469 | { | ||
470 | if( isFilled( j ) ) | ||
471 | { | ||
472 | if( !isDeleted( j ) ) | ||
473 | { | ||
474 | lKeys.push_back( aKeys[j] ); | ||
475 | } | ||
476 | } | ||
477 | } | ||
478 | |||
479 | return lKeys; | ||
480 | } | ||
481 | |||
482 | protected: | ||
483 | virtual void onInsert() {} | ||
484 | virtual void onUpdate() {} | ||
485 | virtual void onDelete() {} | ||
486 | virtual void onReHash() {} | ||
487 | |||
488 | virtual void clearBits() | ||
489 | { | ||
490 | for( uint32_t j = 0; j < nKeysSize; j++ ) | ||
491 | { | ||
492 | bFilled[j] = bDeleted[j] = 0; | ||
493 | } | ||
494 | } | ||
495 | |||
496 | virtual void fill( uint32_t loc, key &k, value &v, uint32_t hash ) | ||
497 | { | ||
498 | bFilled[loc/32] |= (1<<(loc%32)); | ||
499 | va.construct( &aValues[loc], v ); | ||
500 | ka.construct( &aKeys[loc], k ); | ||
501 | aHashCodes[loc] = hash; | ||
502 | nFilled++; | ||
503 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | ||
504 | // nFilled, nDeleted, nCapacity ); | ||
505 | } | ||
506 | |||
507 | virtual void _erase( uint32_t loc ) | ||
508 | { | ||
509 | bDeleted[loc/32] |= (1<<(loc%32)); | ||
510 | va.destroy( &aValues[loc] ); | ||
511 | ka.destroy( &aKeys[loc] ); | ||
512 | nDeleted++; | ||
513 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | ||
514 | // nFilled, nDeleted, nCapacity ); | ||
515 | } | ||
516 | |||
517 | virtual std::pair<key,value> getAtPos( uint32_t nPos ) | ||
518 | { | ||
519 | return std::pair<key,value>(aKeys[nPos],aValues[nPos]); | ||
520 | } | ||
521 | |||
522 | virtual key &getKeyAtPos( uint32_t nPos ) | ||
523 | { | ||
524 | return aKeys[nPos]; | ||
525 | } | ||
526 | |||
527 | virtual value &getValueAtPos( uint32_t nPos ) | ||
528 | { | ||
529 | return aValues[nPos]; | ||
530 | } | ||
531 | |||
532 | virtual uint32_t getFirstPos( bool &bFinished ) | ||
533 | { | ||
534 | for( uint32_t j = 0; j < nCapacity; j++ ) | ||
535 | { | ||
536 | if( isFilled( j ) ) | ||
537 | if( !isDeleted( j ) ) | ||
538 | return j; | ||
539 | } | ||
540 | |||
541 | bFinished = true; | ||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | virtual uint32_t getNextPos( uint32_t nPos, bool &bFinished ) | ||
546 | { | ||
547 | for( uint32_t j = nPos+1; j < nCapacity; j++ ) | ||
548 | { | ||
549 | if( isFilled( j ) ) | ||
550 | if( !isDeleted( j ) ) | ||
551 | return j; | ||
552 | } | ||
553 | |||
554 | bFinished = true; | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | uint32_t probe( uint32_t hash, key k, bool &bFill, bool rehash=true ) | ||
559 | { | ||
560 | uint32_t nCur = hash%nCapacity; | ||
561 | |||
562 | // First we scan to see if the key is already there, abort if we | ||
563 | // run out of probing room, or we find a non-filled entry | ||
564 | for( int8_t j = 0; | ||
565 | isFilled( nCur ) && j < 32; | ||
566 | nCur = (nCur + (1<<j))%nCapacity, j++ | ||
567 | ) | ||
568 | { | ||
569 | // Is this the same hash code we were looking for? | ||
570 | if( hash == aHashCodes[nCur] ) | ||
571 | { | ||
572 | // Skip over deleted entries. Deleted entries are also filled, | ||
573 | // so we only have to do this check here. | ||
574 | if( isDeleted( nCur ) ) | ||
575 | continue; | ||
576 | |||
577 | // Is it really the same key? (for safety) | ||
578 | if( __cmpHashKeys( aKeys[nCur], k ) == true ) | ||
579 | { | ||
580 | bFill = true; | ||
581 | return nCur; | ||
582 | } | ||
583 | } | ||
584 | } | ||
585 | |||
586 | // This is our insurance, if the table is full, then go ahead and | ||
587 | // rehash, then try again. | ||
588 | if( isFilled( nCur ) && rehash == true ) | ||
589 | { | ||
590 | reHash( szCalc(getCapacity(), getFill(), getDeleted()) ); | ||
591 | |||
592 | // This is potentially dangerous, and could cause an infinite loop. | ||
593 | // Be careful writing probe, eh? | ||
594 | return probe( hash, k, bFill ); | ||
595 | } | ||
596 | |||
597 | bFill = false; | ||
598 | return nCur; | ||
599 | } | ||
600 | |||
601 | void reHash( uint32_t nNewSize ) | ||
602 | { | ||
603 | //printf("---REHASH---"); | ||
604 | //printf("Filled: %d, Deleted: %d, Capacity: %d\n", | ||
605 | // nFilled, nDeleted, nCapacity ); | ||
606 | |||
607 | // Save all the old data | ||
608 | uint32_t nOldCapacity = nCapacity; | ||
609 | uint32_t *bOldFilled = bFilled; | ||
610 | uint32_t *aOldHashCodes = aHashCodes; | ||
611 | uint32_t nOldKeysSize = nKeysSize; | ||
612 | uint32_t *bOldDeleted = bDeleted; | ||
613 | value *aOldValues = aValues; | ||
614 | key *aOldKeys = aKeys; | ||
615 | |||
616 | // Calculate new sizes | ||
617 | nCapacity = nNewSize; | ||
618 | nKeysSize = bitsToBytes( nCapacity ); | ||
619 | |||
620 | // Allocate new memory + prep | ||
621 | bFilled = ca.allocate( nKeysSize ); | ||
622 | bDeleted = ca.allocate( nKeysSize ); | ||
623 | clearBits(); | ||
624 | |||
625 | aHashCodes = ca.allocate( nCapacity ); | ||
626 | aKeys = ka.allocate( nCapacity ); | ||
627 | aValues = va.allocate( nCapacity ); | ||
628 | |||
629 | nDeleted = nFilled = 0; | ||
630 | |||
631 | // Re-insert all of the old data (except deleted items) | ||
632 | for( uint32_t j = 0; j < nOldCapacity; j++ ) | ||
633 | { | ||
634 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 && | ||
635 | (bOldDeleted[j/32]&(1<<(j%32)))==0 ) | ||
636 | { | ||
637 | insert( aOldKeys[j], aOldValues[j] ); | ||
638 | } | ||
639 | } | ||
640 | |||
641 | // Delete all of the old data | ||
642 | for( uint32_t j = 0; j < nOldCapacity; j++ ) | ||
643 | { | ||
644 | if( (bOldFilled[j/32]&(1<<(j%32)))!=0 ) | ||
645 | { | ||
646 | va.destroy( &aOldValues[j] ); | ||
647 | ka.destroy( &aOldKeys[j] ); | ||
648 | } | ||
649 | } | ||
650 | va.deallocate( aOldValues, nOldCapacity ); | ||
651 | ka.deallocate( aOldKeys, nOldCapacity ); | ||
652 | ca.deallocate( bOldFilled, nOldKeysSize ); | ||
653 | ca.deallocate( bOldDeleted, nOldKeysSize ); | ||
654 | ca.deallocate( aOldHashCodes, nOldCapacity ); | ||
655 | } | ||
656 | |||
657 | virtual bool isFilled( uint32_t loc ) const | ||
658 | { | ||
659 | return (bFilled[loc/32]&(1<<(loc%32)))!=0; | ||
660 | } | ||
661 | |||
662 | virtual bool isDeleted( uint32_t loc ) | ||
663 | { | ||
664 | return (bDeleted[loc/32]&(1<<(loc%32)))!=0; | ||
665 | } | ||
666 | |||
667 | protected: | ||
668 | uint32_t nCapacity; | ||
669 | uint32_t nFilled; | ||
670 | uint32_t nDeleted; | ||
671 | uint32_t *bFilled; | ||
672 | uint32_t *bDeleted; | ||
673 | uint32_t nKeysSize; | ||
674 | key *aKeys; | ||
675 | value *aValues; | ||
676 | uint32_t *aHashCodes; | ||
677 | valuealloc va; | ||
678 | keyalloc ka; | ||
679 | challoc ca; | ||
680 | sizecalc szCalc; | ||
681 | }; | ||
682 | |||
683 | template<> uint32_t __calcHashCode<int>( const int &k ); | ||
684 | template<> bool __cmpHashKeys<int>( const int &a, const int &b ); | ||
685 | |||
686 | template<> uint32_t __calcHashCode<unsigned int>( const unsigned int &k ); | ||
687 | template<> bool __cmpHashKeys<unsigned int>( const unsigned int &a, const unsigned int &b ); | ||
688 | |||
689 | template<> uint32_t __calcHashCode<const char *>( const char * const &k ); | ||
690 | template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b ); | ||
691 | |||
692 | template<> uint32_t __calcHashCode<char *>( char * const &k ); | ||
693 | template<> bool __cmpHashKeys<char *>( char * const &a, char * const &b ); | ||
694 | |||
695 | template<> uint32_t __calcHashCode<std::string>( const std::string &k ); | ||
696 | template<> bool __cmpHashKeys<std::string>( const std::string &a, const std::string &b ); | ||
697 | |||
698 | template<> uint32_t __calcHashCode<Hashable>( const Hashable &k ); | ||
699 | template<> bool __cmpHashKeys<Hashable>( const Hashable &a, const Hashable &b ); | ||
700 | |||
701 | template<typename key, typename value> | ||
702 | Serializer &operator<<( Serializer &ar, Hash<key,value> &h ) | ||
703 | { | ||
704 | ar << h.size(); | ||
705 | for( typename Hash<key,value>::iterator i = h.begin(); i != h.end(); i++ ) | ||
706 | { | ||
707 | std::pair<key,value> p = *i; | ||
708 | ar << p.first << p.second; | ||
709 | } | ||
710 | |||
711 | return ar; | ||
712 | } | ||
713 | |||
714 | template<typename key, typename value> | ||
715 | Serializer &operator>>( Serializer &ar, Hash<key,value> &h ) | ||
716 | { | ||
717 | h.clear(); | ||
718 | uint32_t nSize; | ||
719 | ar >> nSize; | ||
720 | |||
721 | for( uint32_t j = 0; j < nSize; j++ ) | ||
722 | { | ||
723 | key k; value v; | ||
724 | ar >> k >> v; | ||
725 | h.insert( k, v ); | ||
726 | } | ||
727 | |||
728 | return ar; | ||
729 | } | ||
730 | |||
731 | template<typename key, typename value> | ||
732 | Serializer &operator&&( Serializer &ar, Hash<key,value> &h ) | ||
733 | { | ||
734 | if( ar.isLoading() ) | ||
735 | { | ||
736 | return ar >> h; | ||
737 | } | ||
738 | else | ||
739 | { | ||
740 | return ar << h; | ||
741 | } | ||
742 | } | ||
743 | |||
744 | #endif | ||
diff --git a/src/old/hashable.cpp b/src/old/hashable.cpp deleted file mode 100644 index 8565956..0000000 --- a/src/old/hashable.cpp +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | #include "hashable.h" | ||
diff --git a/src/old/hashable.h b/src/old/hashable.h deleted file mode 100644 index 98643d5..0000000 --- a/src/old/hashable.h +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | #ifndef HASHABLE_H | ||
2 | #define HASHABLE_H | ||
3 | |||
4 | class Hashable | ||
5 | { | ||
6 | public: | ||
7 | virtual ~Hashable() {}; | ||
8 | virtual unsigned long int getHashCode() = 0; | ||
9 | virtual bool compareForHash( Hashable &other ) = 0; | ||
10 | }; | ||
11 | |||
12 | #endif | ||
diff --git a/src/old/serializable.cpp b/src/old/serializable.cpp deleted file mode 100644 index fd50943..0000000 --- a/src/old/serializable.cpp +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | #include "serializable.h" | ||
2 | |||
3 | Serializable::Serializable() | ||
4 | { | ||
5 | } | ||
6 | Serializable::~Serializable() | ||
7 | { | ||
8 | } | ||
diff --git a/src/old/serializable.h b/src/old/serializable.h deleted file mode 100644 index 06def29..0000000 --- a/src/old/serializable.h +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | #ifndef SERIALIZER_H | ||
2 | #define SERIALIZER_H | ||
3 | |||
4 | //#include "serializer.h" | ||
5 | |||
6 | /** | ||
7 | * The base class for any class you want to serialize. Simply include this as | ||
8 | * a base class, implement the purely virtual serialize function and you've got | ||
9 | * an easily serializable class. | ||
10 | */ | ||
11 | class Serializable | ||
12 | { | ||
13 | public: | ||
14 | /** | ||
15 | * Does nothing, here for completeness. | ||
16 | */ | ||
17 | Serializable(); | ||
18 | |||
19 | /** | ||
20 | * Here to ensure the deconstructor is virtual. | ||
21 | */ | ||
22 | virtual ~Serializable(); | ||
23 | |||
24 | /** | ||
25 | * This is the main workhorse of the serialization system, just override and | ||
26 | * you've got a serializable class. A reference to the Serializer archive | ||
27 | * used is passed in as your only parameter, query it to discover if you are | ||
28 | * loading or saving. | ||
29 | * @param ar A reference to the Serializer object to use. | ||
30 | */ | ||
31 | virtual void serialize( class Serializer &ar )=0; | ||
32 | }; | ||
33 | |||
34 | #endif | ||
diff --git a/src/old/serializer.h b/src/old/serializer.h deleted file mode 100644 index 3af489c..0000000 --- a/src/old/serializer.h +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | #ifndef SERIALIZABLE_H | ||
2 | #define SERIALIZABLE_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <string> | ||
6 | #include <list> | ||
7 | //#include "serializable.h" | ||
8 | |||
9 | class Serializer | ||
10 | { | ||
11 | private: | ||
12 | bool bLoading; | ||
13 | public: | ||
14 | bool isLoading(); | ||
15 | |||
16 | enum | ||
17 | { | ||
18 | load = true, | ||
19 | save = false | ||
20 | }; | ||
21 | |||
22 | Serializer(bool bLoading); | ||
23 | virtual ~Serializer(); | ||
24 | virtual void close()=0; | ||
25 | |||
26 | virtual void write(const void *, int32_t)=0; | ||
27 | virtual void read(void *, int32_t)=0; | ||
28 | |||
29 | virtual Serializer &operator<<(bool); | ||
30 | virtual Serializer &operator<<(int8_t); | ||
31 | virtual Serializer &operator<<(int16_t); | ||
32 | virtual Serializer &operator<<(int32_t); | ||
33 | virtual Serializer &operator<<(int64_t); | ||
34 | virtual Serializer &operator<<(uint8_t); | ||
35 | virtual Serializer &operator<<(uint16_t); | ||
36 | virtual Serializer &operator<<(uint32_t); | ||
37 | virtual Serializer &operator<<(uint64_t); | ||
38 | virtual Serializer &operator<<(long); | ||
39 | virtual Serializer &operator<<(float); | ||
40 | virtual Serializer &operator<<(double); | ||
41 | virtual Serializer &operator<<(long double); | ||
42 | |||
43 | virtual Serializer &operator>>(bool &); | ||
44 | virtual Serializer &operator>>(int8_t &); | ||
45 | virtual Serializer &operator>>(int16_t &); | ||
46 | virtual Serializer &operator>>(int32_t &); | ||
47 | virtual Serializer &operator>>(int64_t &); | ||
48 | virtual Serializer &operator>>(uint8_t &); | ||
49 | virtual Serializer &operator>>(uint16_t &); | ||
50 | virtual Serializer &operator>>(uint32_t &); | ||
51 | virtual Serializer &operator>>(uint64_t &); | ||
52 | virtual Serializer &operator>>(long &); | ||
53 | virtual Serializer &operator>>(float &); | ||
54 | virtual Serializer &operator>>(double &); | ||
55 | virtual Serializer &operator>>(long double &); | ||
56 | |||
57 | virtual Serializer &operator&&(bool &); | ||
58 | virtual Serializer &operator&&(int8_t &); | ||
59 | virtual Serializer &operator&&(int16_t &); | ||
60 | virtual Serializer &operator&&(int32_t &); | ||
61 | virtual Serializer &operator&&(int64_t &); | ||
62 | virtual Serializer &operator&&(uint8_t &); | ||
63 | virtual Serializer &operator&&(uint16_t &); | ||
64 | virtual Serializer &operator&&(uint32_t &); | ||
65 | virtual Serializer &operator&&(uint64_t &); | ||
66 | virtual Serializer &operator&&(float &); | ||
67 | virtual Serializer &operator&&(double &); | ||
68 | virtual Serializer &operator&&(long double &); | ||
69 | |||
70 | //virtual Serializer &operator&(Serializable &); | ||
71 | }; | ||
72 | |||
73 | Serializer &operator<<(Serializer &, class Serializable &); | ||
74 | Serializer &operator>>(Serializer &, class Serializable &); | ||
75 | Serializer &operator&&(Serializer &s, class Serializable &p); | ||
76 | |||
77 | Serializer &operator<<(Serializer &, std::string &); | ||
78 | Serializer &operator>>(Serializer &, std::string &); | ||
79 | |||
80 | #endif | ||
diff --git a/src/old/stream.cpp b/src/old/stream.cpp deleted file mode 100644 index 856a58d..0000000 --- a/src/old/stream.cpp +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | #include "stream.h" | ||
2 | |||
3 | Stream::Stream() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | Stream::~Stream() | ||
8 | { | ||
9 | } | ||
10 | |||
diff --git a/src/old/stream.h b/src/old/stream.h deleted file mode 100644 index e086e28..0000000 --- a/src/old/stream.h +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | #ifndef STREAM_H | ||
2 | #define STREAM_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <stdio.h> | ||
6 | |||
7 | class Stream | ||
8 | { | ||
9 | public: | ||
10 | Stream(); | ||
11 | virtual ~Stream(); | ||
12 | |||
13 | virtual void close() = 0; | ||
14 | virtual size_t read( char *pBuf, size_t nBytes ) = 0; | ||
15 | virtual size_t write( const char *pBuf, size_t nBytes ) = 0; | ||
16 | |||
17 | virtual long tell() = 0; | ||
18 | virtual void seek( long offset ) = 0; | ||
19 | virtual void setPos( long pos ) = 0; | ||
20 | virtual void setPosEnd( long pos ) = 0; | ||
21 | virtual bool isEOS() = 0; | ||
22 | |||
23 | private: | ||
24 | |||
25 | }; | ||
26 | |||
27 | #endif | ||
diff --git a/src/stream.cpp b/src/stream.cpp new file mode 100644 index 0000000..267a7d1 --- /dev/null +++ b/src/stream.cpp | |||
@@ -0,0 +1,10 @@ | |||
1 | #include "stream.h" | ||
2 | |||
3 | Bu::Stream::Stream() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | Bu::Stream::~Stream() | ||
8 | { | ||
9 | } | ||
10 | |||
diff --git a/src/stream.h b/src/stream.h new file mode 100644 index 0000000..274f4fd --- /dev/null +++ b/src/stream.h | |||
@@ -0,0 +1,34 @@ | |||
1 | #ifndef STREAM_H | ||
2 | #define STREAM_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <stdio.h> | ||
6 | |||
7 | namespace Bu | ||
8 | { | ||
9 | class Stream | ||
10 | { | ||
11 | public: | ||
12 | Stream(); | ||
13 | virtual ~Stream(); | ||
14 | |||
15 | virtual void close() = 0; | ||
16 | virtual size_t read( char *pBuf, size_t nBytes ) = 0; | ||
17 | virtual size_t write( const char *pBuf, size_t nBytes ) = 0; | ||
18 | |||
19 | virtual long tell() = 0; | ||
20 | virtual void seek( long offset ) = 0; | ||
21 | virtual void setPos( long pos ) = 0; | ||
22 | virtual void setPosEnd( long pos ) = 0; | ||
23 | virtual bool isEOS() = 0; | ||
24 | |||
25 | virtual bool canRead() = 0; | ||
26 | virtual bool canWrite() = 0; | ||
27 | virtual bool canSeek() = 0; | ||
28 | |||
29 | private: | ||
30 | |||
31 | }; | ||
32 | } | ||
33 | |||
34 | #endif | ||
diff --git a/src/tests/archive.cpp b/src/tests/archive.cpp new file mode 100644 index 0000000..fb0d97c --- /dev/null +++ b/src/tests/archive.cpp | |||
@@ -0,0 +1,7 @@ | |||
1 | #include "archive.h" | ||
2 | |||
3 | int main() | ||
4 | { | ||
5 | //Archive | ||
6 | } | ||
7 | |||
diff --git a/tests/comments.xml b/tests/comments.xml deleted file mode 100644 index df05b3b..0000000 --- a/tests/comments.xml +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | <?xml version="1.0"?> | ||
2 | <test> | ||
3 | <!----><stuff/><guy> | ||
4 | <!-- euntaho esutnaho .rucaho. u | ||
5 | ao.rcuh aor uasrcoh | ||
6 | rohaor | ||
7 | c.uha | ||
8 | orchu | ||
9 | aroch.ua. | ||
10 | -->Aaaugh! | ||
11 | </guy> | ||
12 | </test> | ||
diff --git a/tests/guy.cpp b/tests/guy.cpp deleted file mode 100644 index 6510771..0000000 --- a/tests/guy.cpp +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | #include "stdio.h" | ||
2 | #include "plugin.h" | ||
3 | #include "plugger.h" | ||
4 | |||
5 | class Guy : public Plugin | ||
6 | { | ||
7 | public: | ||
8 | Guy() | ||
9 | { | ||
10 | printf("I'm guy!\n"); | ||
11 | } | ||
12 | |||
13 | virtual ~Guy() | ||
14 | { | ||
15 | printf("Guy is dead...\n"); | ||
16 | } | ||
17 | |||
18 | private: | ||
19 | }; | ||
20 | |||
21 | PluginInterface( Guy, Plugin, "Mike", 0, 1 ) | ||
22 | |||
diff --git a/tests/makeplugin.sh b/tests/makeplugin.sh deleted file mode 100755 index 086fefd..0000000 --- a/tests/makeplugin.sh +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | g++ -fPIC -shared -Wl,-soname,guy.so -o guy.so -I../src -I../src/test/plugin guy.cpp ../src/test/plugin/plugin.cpp | ||