diff options
Diffstat (limited to 'src/old')
166 files changed, 17248 insertions, 0 deletions
diff --git a/src/old/arraylist.cpp b/src/old/arraylist.cpp new file mode 100644 index 0000000..ef21426 --- /dev/null +++ b/src/old/arraylist.cpp | |||
@@ -0,0 +1,100 @@ | |||
1 | #include "arraylist.h" | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | |||
5 | ArrayList::ArrayList( int initSize, int growByFactor ) | ||
6 | { | ||
7 | apData = new void *[initSize]; | ||
8 | nSize = 0; | ||
9 | nCapacity = initSize; | ||
10 | nGrowByFactor = growByFactor; | ||
11 | } | ||
12 | |||
13 | ArrayList::~ArrayList( ) | ||
14 | { | ||
15 | delete[] apData; | ||
16 | } | ||
17 | |||
18 | void *ArrayList::getAt( int index ) | ||
19 | { | ||
20 | if( index < 0 || index > nSize ) | ||
21 | return NULL; | ||
22 | |||
23 | return apData[index]; | ||
24 | } | ||
25 | |||
26 | void ArrayList::append( void *data ) | ||
27 | { | ||
28 | insertBefore( data, nSize ); | ||
29 | } | ||
30 | |||
31 | void ArrayList::insertBefore( void *data, int pos ) | ||
32 | { | ||
33 | if( pos < 0 || pos > nSize ) | ||
34 | return; | ||
35 | |||
36 | checkResize(); | ||
37 | memmove( &apData[pos+1], &apData[pos], (nSize-pos)*sizeof(void*) ); | ||
38 | apData[pos] = data; | ||
39 | nSize++; | ||
40 | } | ||
41 | |||
42 | int ArrayList::getSize( ) | ||
43 | { | ||
44 | return nSize; | ||
45 | } | ||
46 | |||
47 | bool ArrayList::isEmpty( ) | ||
48 | { | ||
49 | return nSize==0; | ||
50 | } | ||
51 | |||
52 | void ArrayList::deleteAt( int index ) | ||
53 | { | ||
54 | if( index < 0 || index >= nSize ) | ||
55 | return; | ||
56 | |||
57 | memmove( &apData[index], &apData[index+1], (nSize-index-1)*sizeof(void *) ); | ||
58 | nSize--; | ||
59 | } | ||
60 | |||
61 | void ArrayList::empty() | ||
62 | { | ||
63 | // Probably the easiest as far as things go. | ||
64 | nSize = 0; | ||
65 | } | ||
66 | |||
67 | void ArrayList::resizeTo( int newSize ) | ||
68 | { | ||
69 | void **apNew = new void *[newSize]; | ||
70 | memmove( apNew, apData, nSize*sizeof(void *) ); | ||
71 | nCapacity = newSize; | ||
72 | delete[] apData; | ||
73 | apData = apNew; | ||
74 | } | ||
75 | |||
76 | void ArrayList::checkResize() | ||
77 | { | ||
78 | if( nSize >= nCapacity ) | ||
79 | { | ||
80 | resizeTo( nCapacity + nGrowByFactor ); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | void ArrayList::setSize( int newSize ) | ||
85 | { | ||
86 | if( newSize < 0 ) | ||
87 | return; | ||
88 | |||
89 | nSize = newSize; | ||
90 | checkResize(); | ||
91 | } | ||
92 | |||
93 | void ArrayList::setAt( int index, void *data ) | ||
94 | { | ||
95 | if( index < 0 || index >= nSize ) | ||
96 | return; | ||
97 | |||
98 | apData[index] = data; | ||
99 | } | ||
100 | |||
diff --git a/src/old/arraylist.h b/src/old/arraylist.h new file mode 100644 index 0000000..0fda34a --- /dev/null +++ b/src/old/arraylist.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /** \file arraylist.h | ||
2 | * Describes the ArrayList class. | ||
3 | *@author Mike Buland | ||
4 | */ | ||
5 | #ifndef ARRAY_LIST_H | ||
6 | #define ARRAY_LIST_H | ||
7 | |||
8 | #include "list.h" | ||
9 | |||
10 | /** A simple list which uses an array. This is a great choice if you won't do | ||
11 | * a lot of adding and deleting and need a fast random access list. Otherwise | ||
12 | * use the LinkedList. | ||
13 | *@author Mike Buland | ||
14 | */ | ||
15 | class ArrayList : public List | ||
16 | { | ||
17 | public: | ||
18 | /** Creates an arraylist with some pre-defined specs spelled out. | ||
19 | *@param initSize the inital number of elements to allocate. | ||
20 | *@param growByFactor How much to increase the size of the array by | ||
21 | * each time we run out of room. | ||
22 | */ | ||
23 | ArrayList( int initSize=100, int growByFactor=10 ); | ||
24 | /** | ||
25 | * Destroy the ArrayList | ||
26 | */ | ||
27 | virtual ~ArrayList(); | ||
28 | |||
29 | void *getAt( int nIndex ); | ||
30 | void append( void *pData ); | ||
31 | void insertBefore( void *pData, int nPos = 0 ); | ||
32 | int getSize( ); | ||
33 | bool isEmpty( ); | ||
34 | void deleteAt( int nIndex ); | ||
35 | void empty(); | ||
36 | void setSize( int nNewSize ); | ||
37 | void setAt( int nIndex, void *pData ); | ||
38 | |||
39 | private: | ||
40 | /** | ||
41 | * Checks to see if the system needs to be resized, if it does, this will | ||
42 | * automatically resize based on your parameters. | ||
43 | */ | ||
44 | void checkResize(); | ||
45 | |||
46 | /** | ||
47 | * Resize the system to a specified size. If it is larger, then all data | ||
48 | * will be retained, if smaller the elements at the end will be cut off. | ||
49 | *@param newSize The number of elements to include after resizing. | ||
50 | */ | ||
51 | void resizeTo( int newSize ); | ||
52 | |||
53 | /** | ||
54 | * Actual master array of pointers. This is done to follow the List specs. | ||
55 | * All data transactions are performed with pointers or compatable | ||
56 | * primitive data-types. | ||
57 | */ | ||
58 | void **apData; | ||
59 | |||
60 | /** | ||
61 | * The number of filled in elements in the array. This is the practical | ||
62 | * real size of the ArrayList for all userspace applications. | ||
63 | */ | ||
64 | int nSize; | ||
65 | |||
66 | /** | ||
67 | * The number of elements allocated in memory. Not all of these have to be | ||
68 | * filled in, and it is usually larger than nSize so that adding and | ||
69 | * deleting elements is fast and easy. | ||
70 | */ | ||
71 | int nCapacity; | ||
72 | |||
73 | /** | ||
74 | * The amount to grow by whenever the array needs resizing. | ||
75 | */ | ||
76 | int nGrowByFactor; | ||
77 | }; | ||
78 | |||
79 | #endif | ||
80 | |||
diff --git a/src/old/cgi.cpp b/src/old/cgi.cpp new file mode 100644 index 0000000..1fecbbe --- /dev/null +++ b/src/old/cgi.cpp | |||
@@ -0,0 +1,644 @@ | |||
1 | #include <string.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <stdio.h> | ||
4 | #include <stdarg.h> | ||
5 | #include <sys/stat.h> | ||
6 | |||
7 | #include "cgi.h" | ||
8 | |||
9 | Cgi::Cgi( const char *strSource ) : | ||
10 | aContent( new HashFunctionString(), 151, true ) | ||
11 | { | ||
12 | int length, j, k, mode = 0, slen = 0; | ||
13 | char hexbuf[3] = { 0, 0, 0 }; | ||
14 | char *buf, chr; | ||
15 | Item *cur = NULL; | ||
16 | int nCur = 0; | ||
17 | |||
18 | if( strSource != NULL ) | ||
19 | { | ||
20 | loadContent( strSource ); | ||
21 | } | ||
22 | |||
23 | if( ( getenv( "CONTENT_LENGTH" ) ) ) | ||
24 | { | ||
25 | if( !strcmp | ||
26 | ( getenv( "CONTENT_TYPE" ), | ||
27 | "application/x-www-form-urlencoded" ) ) | ||
28 | { | ||
29 | length = atoi( getenv( "CONTENT_LENGTH" ) ); | ||
30 | buf = new char[length + 1]; | ||
31 | fread( buf, 1, length, stdin ); | ||
32 | cur = new Item( ); | ||
33 | aVars.append( cur ); | ||
34 | cur->type = VAR_STDINPUT; | ||
35 | for( j = 0; j < length; j++ ) | ||
36 | { | ||
37 | switch ( buf[j] ) | ||
38 | { | ||
39 | case '=': | ||
40 | cur->name = new char[slen + 1]; | ||
41 | slen = 0; | ||
42 | break; | ||
43 | |||
44 | case '&': | ||
45 | cur->value = new char[slen + 1]; | ||
46 | cur->len = slen; | ||
47 | slen = 0; | ||
48 | cur = new Item( ); | ||
49 | aVars.append( cur ); | ||
50 | cur->type = VAR_STDINPUT; | ||
51 | break; | ||
52 | |||
53 | default: | ||
54 | switch ( buf[j] ) | ||
55 | { | ||
56 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
57 | j += 2; | ||
58 | slen++; | ||
59 | break; | ||
60 | |||
61 | default: /* Nothing special, move along, folks... */ | ||
62 | slen++; | ||
63 | break; | ||
64 | } | ||
65 | break; | ||
66 | } | ||
67 | } | ||
68 | cur->value = new char[slen + 1]; | ||
69 | cur->len = slen; | ||
70 | slen = 0; | ||
71 | mode = 0; | ||
72 | cur = ( Item * ) aVars.getAt( 0 ); | ||
73 | k = 0; | ||
74 | nCur = 0; | ||
75 | for( j = 0; j < length; j++ ) | ||
76 | { | ||
77 | switch ( buf[j] ) | ||
78 | { | ||
79 | case '=': | ||
80 | mode = 1; | ||
81 | k = 0; | ||
82 | break; | ||
83 | |||
84 | case '&': | ||
85 | mode = 0; | ||
86 | k = 0; | ||
87 | nCur++; | ||
88 | cur = ( Item * ) aVars.getAt( nCur ); | ||
89 | break; | ||
90 | |||
91 | default: | ||
92 | switch ( buf[j] ) | ||
93 | { | ||
94 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
95 | hexbuf[0] = buf[++j]; | ||
96 | hexbuf[1] = buf[++j]; | ||
97 | chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); | ||
98 | break; | ||
99 | |||
100 | case '+': /* Pluses mean spaces, odd, I know... */ | ||
101 | chr = ' '; | ||
102 | break; | ||
103 | |||
104 | default: /* Nothing special, move along, folks... */ | ||
105 | chr = buf[j]; | ||
106 | break; | ||
107 | } | ||
108 | if( mode == 0 ) | ||
109 | { | ||
110 | cur->name[k] = chr; | ||
111 | cur->name[++k] = '\0'; | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | cur->value[k] = chr; | ||
116 | cur->value[++k] = '\0'; | ||
117 | } | ||
118 | break; | ||
119 | } | ||
120 | } | ||
121 | delete buf; | ||
122 | } | ||
123 | else if( !strncmp | ||
124 | ( getenv( "CONTENT_TYPE" ), "multipart/form-data;", 20 ) ) | ||
125 | { | ||
126 | char *boundary, *oname; | ||
127 | int blen, j, k, olen; | ||
128 | |||
129 | length = atoi( getenv( "CONTENT_LENGTH" ) ); | ||
130 | buf = new char[length + 1]; | ||
131 | fread( buf, 1, length, stdin ); | ||
132 | for( blen = 0; buf[blen + 1] != '\n'; blen++ ); | ||
133 | boundary = new char[blen + 1]; | ||
134 | memcpy( boundary, buf, blen ); | ||
135 | boundary[blen] = '\0'; | ||
136 | j = blen + 2; | ||
137 | for( ;; ) | ||
138 | { | ||
139 | cur = new Item( ); | ||
140 | aVars.append( cur ); | ||
141 | cur->type = VAR_STDINPUT; | ||
142 | if( !strncmp | ||
143 | ( buf + j, "Content-Disposition: form-data; name=\"", | ||
144 | 38 ) ) | ||
145 | { | ||
146 | j += 38; | ||
147 | for( k = 0; buf[j + k] != '\"'; k++ ); | ||
148 | oname = cur->name = new char[k + 1]; | ||
149 | memcpy( cur->name, buf + j, k ); | ||
150 | olen = k; | ||
151 | cur->name[k] = '\0'; | ||
152 | j += k + 1; | ||
153 | if( !strncmp( buf + j, "; filename=\"", 12 ) ) /* Must be a file */ | ||
154 | { | ||
155 | /* Acquire file name */ | ||
156 | j += 12; | ||
157 | for( k = 0; buf[j + k] != '\"'; k++ ); | ||
158 | cur->value = new char[k + 1]; | ||
159 | memcpy( cur->value, buf + j, k ); | ||
160 | cur->value[k] = '\0'; | ||
161 | cur->len = k; | ||
162 | j += k + 3; | ||
163 | |||
164 | /* Acquire content type */ | ||
165 | if( !strncmp( "Content-Type: ", buf + j, 14 ) ) | ||
166 | { | ||
167 | j += 14; | ||
168 | cur = new Item( ); | ||
169 | aVars.append( cur ); | ||
170 | cur->type = VAR_STDINPUT; | ||
171 | cur->name = new char[olen + 1]; | ||
172 | memcpy( cur->name, oname, olen + 1 ); | ||
173 | for( k = 0; buf[j + k + 1] != '\n'; k++ ); | ||
174 | cur->value = new char[k + 1]; | ||
175 | memcpy( cur->value, buf + j, k ); | ||
176 | cur->value[k] = '\0'; | ||
177 | cur->len = k; | ||
178 | j += k; | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | cur = new Item( ); | ||
183 | aVars.append( cur ); | ||
184 | cur->type = VAR_STDINPUT; | ||
185 | cur->name = new char[olen + 1]; | ||
186 | memcpy( cur->name, oname, olen + 1 ); | ||
187 | cur->value = new char[1]; | ||
188 | cur->value[0] = '\0'; | ||
189 | cur->len = 0; | ||
190 | } | ||
191 | j += 4; | ||
192 | |||
193 | /* Acquire content */ | ||
194 | cur = new Item( ); | ||
195 | aVars.append( cur ); | ||
196 | cur->type = VAR_STDINPUT; | ||
197 | cur->name = new char[olen + 1]; | ||
198 | memcpy( cur->name, oname, olen + 1 ); | ||
199 | if( !strncmp( buf + j + k, boundary, blen ) ) | ||
200 | { | ||
201 | cur->value = new char[1]; | ||
202 | cur->value[0] = '\0'; | ||
203 | j += blen + 4; | ||
204 | } | ||
205 | else if( !strncmp( buf + j + k + 1, boundary, blen ) ) | ||
206 | { | ||
207 | cur->value = new char[1]; | ||
208 | cur->value[0] = '\0'; | ||
209 | j += blen + 5; | ||
210 | } | ||
211 | else | ||
212 | { | ||
213 | for( k = 0; | ||
214 | strncmp( buf + j + k + 2, boundary, blen ); | ||
215 | k++ ); | ||
216 | cur->value = new char[k + 1]; | ||
217 | memcpy( cur->value, buf + j, k ); | ||
218 | cur->value[k] = '\0'; | ||
219 | cur->len = k; | ||
220 | j += k + blen + 4; | ||
221 | } | ||
222 | } | ||
223 | else | ||
224 | { | ||
225 | j += 4; | ||
226 | for( k = 0; | ||
227 | strncmp( buf + j + k + 2, boundary, blen ); | ||
228 | k++ ); | ||
229 | cur->value = new char[k + 1]; | ||
230 | memcpy( cur->value, buf + j, k ); | ||
231 | cur->value[k] = '\0'; | ||
232 | cur->len = k; | ||
233 | j += k + blen + 4; | ||
234 | } | ||
235 | if( buf[j + 1] == '\n' ) | ||
236 | j += 2; | ||
237 | if( j >= length ) | ||
238 | break; | ||
239 | } | ||
240 | else | ||
241 | { | ||
242 | cur->name = ( char * ) "ERROR"; | ||
243 | cur->value = ( char * ) "Error here"; | ||
244 | } | ||
245 | } | ||
246 | } | ||
247 | delete buf; | ||
248 | } | ||
249 | |||
250 | if( ( buf = getenv( "HTTP_COOKIE" ) ) ) | ||
251 | { | ||
252 | int lbase = aVars.getSize( ); | ||
253 | length = strlen( buf ); | ||
254 | cur = new Item( ); | ||
255 | aVars.append( cur ); | ||
256 | cur->type = VAR_COOKIE; | ||
257 | for( j = 0; j < length; j++ ) | ||
258 | { | ||
259 | switch ( buf[j] ) | ||
260 | { | ||
261 | case '=': | ||
262 | cur->name = new char[slen + 1]; | ||
263 | slen = 0; | ||
264 | break; | ||
265 | |||
266 | case ';': | ||
267 | cur->value = new char[slen + 1]; | ||
268 | cur->len = slen; | ||
269 | slen = 0; | ||
270 | cur = new Item( ); | ||
271 | aVars.append( cur ); | ||
272 | cur->type = VAR_COOKIE; | ||
273 | break; | ||
274 | |||
275 | default: | ||
276 | switch ( buf[j] ) | ||
277 | { | ||
278 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
279 | j += 2; | ||
280 | slen++; | ||
281 | break; | ||
282 | |||
283 | default: /* Nothing special, move along, folks... */ | ||
284 | slen++; | ||
285 | break; | ||
286 | } | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | cur->value = new char[slen + 1]; | ||
291 | cur->len = slen; | ||
292 | slen = 0; | ||
293 | cur = ( Item * ) aVars.getAt( lbase ); | ||
294 | mode = 0; | ||
295 | k = 0; | ||
296 | nCur = lbase; | ||
297 | for( j = 0; j < length; j++ ) | ||
298 | { | ||
299 | switch ( buf[j] ) | ||
300 | { | ||
301 | case '=': | ||
302 | mode = 1; | ||
303 | k = 0; | ||
304 | break; | ||
305 | |||
306 | case ';': | ||
307 | mode = 0; | ||
308 | k = 0; | ||
309 | nCur++; | ||
310 | cur = ( Item * ) aVars.getAt( nCur ); | ||
311 | break; | ||
312 | |||
313 | default: | ||
314 | switch ( buf[j] ) | ||
315 | { | ||
316 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
317 | hexbuf[0] = buf[++j]; | ||
318 | hexbuf[1] = buf[++j]; | ||
319 | chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); | ||
320 | break; | ||
321 | |||
322 | case '+': /* Pluses mean spaces, odd, I know... */ | ||
323 | chr = ' '; | ||
324 | break; | ||
325 | |||
326 | case ' ': | ||
327 | continue; | ||
328 | break; | ||
329 | |||
330 | default: /* Nothing special, move along, folks... */ | ||
331 | chr = buf[j]; | ||
332 | break; | ||
333 | } | ||
334 | if( mode == 0 ) | ||
335 | { | ||
336 | cur->name[k] = chr; | ||
337 | cur->name[++k] = '\0'; | ||
338 | } | ||
339 | else | ||
340 | { | ||
341 | cur->value[k] = chr; | ||
342 | cur->value[++k] = '\0'; | ||
343 | } | ||
344 | break; | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | |||
349 | if( ( buf = getenv( "QUERY_STRING" ) ) ) | ||
350 | { | ||
351 | if( strlen( buf ) > 0 ) | ||
352 | { | ||
353 | int lbase = aVars.getSize( ); | ||
354 | length = strlen( buf ); | ||
355 | cur = new Item( ); | ||
356 | aVars.append( cur ); | ||
357 | cur->type = VAR_CMDLINE; | ||
358 | for( j = 0; j < length; j++ ) | ||
359 | { | ||
360 | switch ( buf[j] ) | ||
361 | { | ||
362 | case '=': | ||
363 | cur->name = new char[slen + 1]; | ||
364 | slen = 0; | ||
365 | break; | ||
366 | |||
367 | case '&': | ||
368 | cur->value = new char[slen + 1]; | ||
369 | cur->len = slen; | ||
370 | slen = 0; | ||
371 | cur = new Item( ); | ||
372 | aVars.append( cur ); | ||
373 | cur->type = VAR_CMDLINE; | ||
374 | break; | ||
375 | |||
376 | default: | ||
377 | switch ( buf[j] ) | ||
378 | { | ||
379 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
380 | j += 2; | ||
381 | slen++; | ||
382 | break; | ||
383 | |||
384 | default: /* Nothing special, move along, folks... */ | ||
385 | slen++; | ||
386 | break; | ||
387 | } | ||
388 | break; | ||
389 | } | ||
390 | } | ||
391 | cur->value = new char[slen + 1]; | ||
392 | cur->len = slen; | ||
393 | slen = 0; | ||
394 | cur = ( Item * ) aVars.getAt( lbase ); | ||
395 | nCur = lbase; | ||
396 | mode = 0; | ||
397 | k = 0; | ||
398 | for( j = 0; j < length; j++ ) | ||
399 | { | ||
400 | switch ( buf[j] ) | ||
401 | { | ||
402 | case '=': | ||
403 | mode = 1; | ||
404 | k = 0; | ||
405 | break; | ||
406 | |||
407 | case '&': | ||
408 | mode = 0; | ||
409 | k = 0; | ||
410 | nCur++; | ||
411 | cur = ( Item * ) aVars.getAt( nCur ); | ||
412 | break; | ||
413 | |||
414 | default: | ||
415 | switch ( buf[j] ) | ||
416 | { | ||
417 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
418 | hexbuf[0] = buf[++j]; | ||
419 | hexbuf[1] = buf[++j]; | ||
420 | chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); | ||
421 | break; | ||
422 | |||
423 | case '+': /* Pluses mean spaces, odd, I know... */ | ||
424 | chr = ' '; | ||
425 | break; | ||
426 | |||
427 | default: /* Nothing special, move along, folks... */ | ||
428 | chr = buf[j]; | ||
429 | break; | ||
430 | } | ||
431 | if( mode == 0 ) | ||
432 | { | ||
433 | cur->name[k] = chr; | ||
434 | cur->name[++k] = '\0'; | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | cur->value[k] = chr; | ||
439 | cur->value[++k] = '\0'; | ||
440 | } | ||
441 | break; | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | } | ||
447 | |||
448 | Cgi::~Cgi( ) | ||
449 | { | ||
450 | } | ||
451 | |||
452 | char *Cgi::getVarValue( const char *name, int skip, unsigned char type ) | ||
453 | { | ||
454 | for( int j = 0; j < aVars.getSize( ); j++ ) | ||
455 | { | ||
456 | Item *cur = ( Item * ) aVars.getAt( j ); | ||
457 | if( !strcmp( cur->name, name ) ) | ||
458 | { | ||
459 | if( ( cur->type & type ) ) | ||
460 | { | ||
461 | if( skip <= 0 ) | ||
462 | { | ||
463 | return cur->value; | ||
464 | } | ||
465 | else | ||
466 | { | ||
467 | skip--; | ||
468 | } | ||
469 | } | ||
470 | } | ||
471 | } | ||
472 | return NULL; | ||
473 | } | ||
474 | |||
475 | int Cgi::getVarLength( const char *name, int skip, unsigned char type ) | ||
476 | { | ||
477 | for( int j = 0; j < aVars.getSize( ); j++ ) | ||
478 | { | ||
479 | Item *cur = ( Item * ) aVars.getAt( j ); | ||
480 | if( !strcmp( cur->name, name ) ) | ||
481 | { | ||
482 | if( ( cur->type & type ) ) | ||
483 | { | ||
484 | if( skip <= 0 ) | ||
485 | { | ||
486 | return cur->len; | ||
487 | } | ||
488 | else | ||
489 | { | ||
490 | skip--; | ||
491 | } | ||
492 | } | ||
493 | } | ||
494 | } | ||
495 | return -1; | ||
496 | } | ||
497 | |||
498 | void Cgi::writeDebugInfo() | ||
499 | { | ||
500 | printf( "<pre>\n" ); | ||
501 | printf( "0x%02X - stdInput | 0x%02X - cookie | 0x%02X - cmdLine\n\n", | ||
502 | VAR_STDINPUT, VAR_COOKIE, VAR_CMDLINE ); | ||
503 | for( int j = 0; j < aVars.getSize( ); j++ ) | ||
504 | { | ||
505 | Item *item = ( Item * ) aVars.getAt( j ); | ||
506 | printf("[%s] = \"%s\" [0x%02X]\n", item->name, | ||
507 | item->value, item->type ); | ||
508 | } | ||
509 | printf( "</pre>\n" ); | ||
510 | } | ||
511 | |||
512 | void Cgi::writeContentHeader( int type ) | ||
513 | { | ||
514 | switch( type ) | ||
515 | { | ||
516 | case headerHTML: | ||
517 | printf("Content-type: text/html\n\n"); | ||
518 | break; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | void Cgi::writeContent( const char *name, ...) | ||
523 | { | ||
524 | char *templ = (char *)aContent.get(name); | ||
525 | |||
526 | if( templ ) | ||
527 | { | ||
528 | va_list ap; | ||
529 | |||
530 | va_start (ap, name); | ||
531 | vprintf (templ, ap); | ||
532 | va_end (ap); | ||
533 | } | ||
534 | else | ||
535 | { | ||
536 | printf("Error finding content labeled \"%s\"\n", name ); | ||
537 | } | ||
538 | } | ||
539 | |||
540 | void Cgi::loadContent( const char *strSource ) | ||
541 | { | ||
542 | FILE *fh = NULL; | ||
543 | if( strSource == NULL ) | ||
544 | { | ||
545 | extern char *program_invocation_short_name; | ||
546 | char *tmpName = new char[strlen(program_invocation_short_name)+10]; | ||
547 | memset( tmpName, 0, strlen(program_invocation_short_name)+10 ); | ||
548 | strcpy( tmpName, program_invocation_short_name ); | ||
549 | strcat( tmpName, ".content" ); | ||
550 | fh = fopen( tmpName, "rt" ); | ||
551 | delete tmpName; | ||
552 | } | ||
553 | else | ||
554 | { | ||
555 | fh = fopen( strSource, "rt" ); | ||
556 | } | ||
557 | |||
558 | if( fh == NULL ) return; | ||
559 | |||
560 | struct stat xStats; | ||
561 | |||
562 | fstat( fileno( fh ), &xStats ); | ||
563 | |||
564 | char *bigBuf = new char[xStats.st_size+1]; | ||
565 | memset( bigBuf, 0, xStats.st_size+1 ); | ||
566 | fread( bigBuf, 1, xStats.st_size, fh ); | ||
567 | fclose( fh ); | ||
568 | |||
569 | // Now we can actually load stuff from the file, first we need to make us up a format... | ||
570 | int lSize=0; | ||
571 | struct Content | ||
572 | { | ||
573 | char *name; | ||
574 | char *value; | ||
575 | } xCont; | ||
576 | int j = 0; | ||
577 | while( j < xStats.st_size ) | ||
578 | { | ||
579 | // We're looking for a content-block init statement | ||
580 | for( ; j < xStats.st_size; j++ ) | ||
581 | { | ||
582 | if( bigBuf[j] == '#' ) | ||
583 | { | ||
584 | if( bigBuf[j+1] == '{' ) | ||
585 | { | ||
586 | break; | ||
587 | } | ||
588 | } | ||
589 | } | ||
590 | j=j+2; | ||
591 | if( j >= xStats.st_size ) break; | ||
592 | for( ; bigBuf[j] == ' ' || bigBuf[j] == '\t'; j++ ); | ||
593 | for( lSize = 0; lSize+j < xStats.st_size && bigBuf[lSize+j] != '\n' && bigBuf[lSize+j] != '\r'; lSize++ ); | ||
594 | xCont.name = new char[lSize+1]; | ||
595 | memset( xCont.name, 0, lSize+1 ); | ||
596 | memcpy( xCont.name, &bigBuf[j], lSize ); | ||
597 | j += lSize+1; | ||
598 | |||
599 | for( lSize = 0; lSize+j < xStats.st_size; lSize++ ) | ||
600 | { | ||
601 | if( bigBuf[lSize+j] == '#' ) | ||
602 | { | ||
603 | if( bigBuf[lSize+j+1] == '}' ) | ||
604 | { | ||
605 | break; | ||
606 | } | ||
607 | } | ||
608 | } | ||
609 | xCont.value = new char[lSize+1]; | ||
610 | memset( xCont.value, 0, lSize+1 ); | ||
611 | memcpy( xCont.value, &bigBuf[j], lSize ); | ||
612 | |||
613 | aContent.insert( xCont.name, xCont.value ); | ||
614 | |||
615 | j += lSize + 2; | ||
616 | } | ||
617 | } | ||
618 | |||
619 | void Cgi::writeCookie( char const *name, char const *value, char const *expires, char const *path, char const *domain, bool secure ) | ||
620 | { | ||
621 | printf("Set-Cookie: %s=%s", name, value ); | ||
622 | |||
623 | if( expires != NULL ) | ||
624 | { | ||
625 | printf("; expires=%s", expires ); | ||
626 | } | ||
627 | |||
628 | if( path != NULL ) | ||
629 | { | ||
630 | printf("; path=%s", path ); | ||
631 | } | ||
632 | |||
633 | if( domain != NULL ) | ||
634 | { | ||
635 | printf("; domain=%s", domain ); | ||
636 | } | ||
637 | |||
638 | if( secure ) | ||
639 | { | ||
640 | printf("; secure"); | ||
641 | } | ||
642 | |||
643 | printf("\n"); | ||
644 | } | ||
diff --git a/src/old/cgi.h b/src/old/cgi.h new file mode 100644 index 0000000..01142b5 --- /dev/null +++ b/src/old/cgi.h | |||
@@ -0,0 +1,196 @@ | |||
1 | /**\file cgi.h | ||
2 | * Describes extra params needed to use the Cgi class as well as the class | ||
3 | * itself. | ||
4 | *@author Mike Buland | ||
5 | */ | ||
6 | |||
7 | #include "linkedlist.h" | ||
8 | #include "hashtable.h" | ||
9 | #include "hashfunctionstring.h" | ||
10 | |||
11 | #define VAR_STDINPUT 0x01 /**< Variable came from stdinput, web form */ | ||
12 | #define VAR_COOKIE 0x02 /**< Variable came from a cookie */ | ||
13 | #define VAR_CMDLINE 0x04 /**< Variable came from commandline / uri */ | ||
14 | #define VAR_ANY 0xFF /**< Mask including all other types */ | ||
15 | |||
16 | /** | ||
17 | * Cgi header processor originally designed for apache cgi programs. When used | ||
18 | * from apache with what I beleive are some sort of standard set of command | ||
19 | * line parameters and environment variables. This always worked for all of my | ||
20 | * purposes. This class will automatically extract all data from the system | ||
21 | * that you need and places it into tables and things for easy access. | ||
22 | * There are three types of input that data can come from, StandardInput, | ||
23 | * CommandLine, and Cookies. StandardInput is when you get formdata in | ||
24 | * multi-part forms, Cookies should usually be cookies that you set, and | ||
25 | * command line is everything after the question mark in the URL. | ||
26 | * This also contains some simple helpers for putting templated data into the | ||
27 | * HTTP data feed. | ||
28 | *@author Mike Buland | ||
29 | */ | ||
30 | class Cgi | ||
31 | { | ||
32 | public: | ||
33 | /** | ||
34 | * Create a complete CGI object, this object will automatically read data | ||
35 | * from all available sources and be ready for use on the very next line! | ||
36 | * If strSource is filled in it will also automatically read in a content | ||
37 | * file, which is a simple file format containing named blocks of reusable | ||
38 | * templates. | ||
39 | *@param strSource Set to a filename in order to load up a content file. | ||
40 | */ | ||
41 | Cgi( const char *strSource = NULL ); | ||
42 | |||
43 | /** | ||
44 | * Destroy the cgi object. | ||
45 | */ | ||
46 | virtual ~Cgi( ); | ||
47 | |||
48 | /** | ||
49 | * Get's the value for a variable as a character string. The name is the | ||
50 | * name that was given on the URL or in the form or cookie. Skip can be | ||
51 | * set to any value above zero to retreive subsequent variables with the | ||
52 | * same name. The most obvious use of this is when dealing with file | ||
53 | * uploads, each file upload sends you three variables with the same name | ||
54 | * and different content. Finally the variable type determines where you | ||
55 | * will accept this variable from. This is generally a bit of a security | ||
56 | * thing, if you store login info in a cookie and don't want people getting | ||
57 | * in by faking the appropriate URL. | ||
58 | *@param name The name of the variable you wish to retreive. | ||
59 | *@param skip THe number of variables with the given name to skip before | ||
60 | * returning something meaningful. The only way to determine how many | ||
61 | * variables with the same name there are is to skip until you get a NULL | ||
62 | * value returned. | ||
63 | *@param type Can be set to any combination of VAR_STDINPUT, VAR_COOKIE, | ||
64 | * VAR_CMDLINE, or just VAR_ANY. This takes bitflags, so you can or the | ||
65 | * values together. If a variable is found but came from the wrong source | ||
66 | * it won't match any other criteria and will be treated as though it | ||
67 | * doesn't exist. | ||
68 | *@returns A null-terminated string representing the value of the requested | ||
69 | * variable, or NULL if the variable did not exist. If a variable does | ||
70 | * exist but has no value the string returned will start with a NULL char, | ||
71 | * but be a valid string. | ||
72 | */ | ||
73 | char *getVarValue( const char *name, int skip=0, unsigned char type=VAR_ANY ); | ||
74 | |||
75 | /** | ||
76 | * This functions identically in every way to getVarValue, except that | ||
77 | * instead of returning a pointer to the variable's value, it returns the | ||
78 | * length of the variable's value string. The params are the same and so | ||
79 | * a call to both functions with the same params should yeild a value and | ||
80 | * a corresponding length. | ||
81 | *@param name The name of the variable you wish to retreive. | ||
82 | *@param skip THe number of variables with the given name to skip before | ||
83 | * returning something meaningful. The only way to determine how many | ||
84 | * variables with the same name there are is to skip until you get a NULL | ||
85 | * value returned. | ||
86 | *@param type Can be set to any combination of VAR_STDINPUT, VAR_COOKIE, | ||
87 | * VAR_CMDLINE, or just VAR_ANY. This takes bitflags, so you can or the | ||
88 | * values together. If a variable is found but came from the wrong source | ||
89 | * it won't match any other criteria and will be treated as though it | ||
90 | * doesn't exist. | ||
91 | *@returns The length of the value-string of the requested variable. If | ||
92 | * the requested variable is not found, -1 is returned. | ||
93 | */ | ||
94 | int getVarLength( const char *name, int skip=0, unsigned char type=VAR_ANY ); | ||
95 | |||
96 | /** | ||
97 | * A handy little function that writes a load of debug info related to | ||
98 | * parsing CGI params to the standard output in html. This is generally | ||
99 | * best used at the end of a page. | ||
100 | */ | ||
101 | void writeDebugInfo(); | ||
102 | |||
103 | /** | ||
104 | * Write a content header to the standard output. This should also be the | ||
105 | * first thing that you do (except for writing cookies) after initializing | ||
106 | * the Cgi class. You can select a type of header or content from the | ||
107 | * header enum, and a properly formatted header will show up on the | ||
108 | * standard output. | ||
109 | *@param type Any value from the header enum in this class. The default is | ||
110 | * to write an html header, probably the most common as well. | ||
111 | */ | ||
112 | void writeContentHeader( int type=headerHTML ); | ||
113 | |||
114 | /** | ||
115 | * Write content to the stnadard output. The content variable should have | ||
116 | * been loaded during construction of the Cgi object or with the | ||
117 | * loadContent function. The content variable should be formatted just like | ||
118 | * a printf string, so that anything you want to put into it will have a % | ||
119 | * symbol replacement code, like %s, %d, etc. Since this actually uses a | ||
120 | * type of printf function everything from those docs work here. | ||
121 | *@param name The name of the content variable to format and write to | ||
122 | * stnadard output. | ||
123 | *@param ... As many params as you want to include, ala printf. | ||
124 | */ | ||
125 | void writeContent( const char *name, ...); | ||
126 | |||
127 | /** | ||
128 | * Load a content file. I don't want to describe the format here, you can | ||
129 | * just read the code or find an example for now. Sorry. | ||
130 | *@param strSource The name of the file to open and read in to get the | ||
131 | * content loaded. | ||
132 | */ | ||
133 | void loadContent( const char *strSource = NULL ); | ||
134 | |||
135 | /** | ||
136 | * Write a cookie-set header to the output stream. This should be done | ||
137 | * before any other content-headers are written. The specifics of this | ||
138 | * function are very simple, since I rely on the user's understanding of | ||
139 | * how standard HTTP/1.1 or HTTP/1.0 cookie syntax works. If you don't | ||
140 | * care then just use the name and value and the defaults should keep you | ||
141 | * in good stead for a long time. | ||
142 | *@param name The name of the cookie variable to set. | ||
143 | *@param value The value to set to that variable. | ||
144 | *@param expires The formatted string value for the date and time this | ||
145 | * cookie should expire. A NULL here will put a "until the browser closes" | ||
146 | * tag in. | ||
147 | *@param path The path (URL) that this cookie belongs to. If you run a lot | ||
148 | * of hosted servers or sub-sites that may have some shared URL bits then | ||
149 | * you may want to set this. The cookie should only be sent to URL's that | ||
150 | * match this as their first part. | ||
151 | *@param domain The domain that is allowed to read this, if not set, it's | ||
152 | * the domain the web browser contacted when they got the cookie. | ||
153 | *@param secure I'm not sure, I think it's something to tell if the cookie | ||
154 | * is safe to keep because any potentially valuable data is encypted or | ||
155 | * otherwise unusable. I could be wrong. | ||
156 | */ | ||
157 | void writeCookie( char const *name, char const *value, char const *expires=NULL, char const *path=NULL, char const *domain=NULL, bool secure=false ); | ||
158 | |||
159 | /** | ||
160 | * A simple helper class to contain variable data. | ||
161 | */ | ||
162 | class Item | ||
163 | { | ||
164 | public: | ||
165 | /** | ||
166 | * Build an empty Item. | ||
167 | */ | ||
168 | Item( ) | ||
169 | { | ||
170 | name = NULL; | ||
171 | value = NULL; | ||
172 | len = 0; | ||
173 | type = 0; | ||
174 | } | ||
175 | /** The name of the item. */ | ||
176 | char *name; | ||
177 | /** The value of the item. */ | ||
178 | char *value; | ||
179 | /** The length of the item's value. */ | ||
180 | unsigned long len; | ||
181 | /** The type of the item (where it came from). */ | ||
182 | unsigned char type; | ||
183 | }; | ||
184 | |||
185 | /** Header values */ | ||
186 | enum | ||
187 | { | ||
188 | headerHTML | ||
189 | }; | ||
190 | |||
191 | private: | ||
192 | /** Keeps track of all contained variables. */ | ||
193 | LinkedList aVars; | ||
194 | /** Keeps track of all content variables. */ | ||
195 | HashTable aContent; | ||
196 | }; | ||
diff --git a/src/old/configmanagerbase.cpp b/src/old/configmanagerbase.cpp new file mode 100644 index 0000000..ac55fe0 --- /dev/null +++ b/src/old/configmanagerbase.cpp | |||
@@ -0,0 +1,63 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <string.h> | ||
3 | #include "xmlnode.h" | ||
4 | #include "xmlfilereader.h" | ||
5 | #include "configmanagerbase.h" | ||
6 | |||
7 | ConfigManagerBase::ConfigManagerBase() | ||
8 | { | ||
9 | } | ||
10 | |||
11 | ConfigManagerBase::~ConfigManagerBase() | ||
12 | { | ||
13 | } | ||
14 | |||
15 | void ConfigManagerBase::addSearchPath( const std::string &sPath ) | ||
16 | { | ||
17 | lSearchPath.push_back( sPath ); | ||
18 | } | ||
19 | |||
20 | void ConfigManagerBase::loadConfig( const std::string &sFileName, const char *lpProfile ) | ||
21 | { | ||
22 | // Try a few locations... | ||
23 | std::list<std::string>::const_iterator i; | ||
24 | for( i = lSearchPath.begin(); i != lSearchPath.end(); i++ ) | ||
25 | { | ||
26 | if( parseConfig( (*i + sFileName).c_str(), lpProfile ) ) | ||
27 | { | ||
28 | break; | ||
29 | } | ||
30 | } | ||
31 | } | ||
32 | |||
33 | bool ConfigManagerBase::parseConfig( const char *lpFileName, const char *lpProfile ) | ||
34 | { | ||
35 | XmlNode *pRoot, *pCur; | ||
36 | XmlFileReader doc( lpFileName ); | ||
37 | |||
38 | pRoot = doc.getRoot(); | ||
39 | if( pRoot == NULL ) | ||
40 | { | ||
41 | return false; | ||
42 | } | ||
43 | |||
44 | if( strcmp("config", pRoot->getName() ) ) | ||
45 | { | ||
46 | return false; | ||
47 | } | ||
48 | |||
49 | for( int j = 0;; j++ ) | ||
50 | { | ||
51 | pCur = pRoot->getChild( "profile", j ); | ||
52 | if( pCur == NULL ) | ||
53 | return false; | ||
54 | |||
55 | if( !strcmp( pCur->getProperty("id"), lpProfile ) ) | ||
56 | { | ||
57 | return processProfile( pCur ); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | return false; | ||
62 | } | ||
63 | |||
diff --git a/src/old/configmanagerbase.h b/src/old/configmanagerbase.h new file mode 100644 index 0000000..381cc1f --- /dev/null +++ b/src/old/configmanagerbase.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef CONFIG_MANAGER_BASE_H | ||
2 | #define CONFIG_MANAGER_BASE_H | ||
3 | |||
4 | #include <string> | ||
5 | #include <list> | ||
6 | |||
7 | class ConfigManagerBase | ||
8 | { | ||
9 | public: | ||
10 | ConfigManagerBase(); | ||
11 | virtual ~ConfigManagerBase(); | ||
12 | |||
13 | public: | ||
14 | void addSearchPath( const std::string &sPath ); | ||
15 | void loadConfig( const std::string &sFileName, const char *lpProfile="default" ); | ||
16 | |||
17 | private: | ||
18 | bool parseConfig( const char *lpFileName, const char *lpProfile ); | ||
19 | virtual bool processProfile( class XmlNode *pBase )=0; | ||
20 | |||
21 | std::list<std::string> lSearchPath; | ||
22 | }; | ||
23 | |||
24 | #endif | ||
diff --git a/src/old/confpair.cpp b/src/old/confpair.cpp new file mode 100644 index 0000000..4741401 --- /dev/null +++ b/src/old/confpair.cpp | |||
@@ -0,0 +1,2 @@ | |||
1 | #include "confpair.h" | ||
2 | |||
diff --git a/src/old/confpair.h b/src/old/confpair.h new file mode 100644 index 0000000..56eb06e --- /dev/null +++ b/src/old/confpair.h | |||
@@ -0,0 +1,81 @@ | |||
1 | #ifndef CONF_PAIR_H | ||
2 | #define CONF_PAIR_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <string> | ||
6 | #include <sstream> | ||
7 | #include "confpairbase.h" | ||
8 | |||
9 | /** | ||
10 | * | ||
11 | */ | ||
12 | template<class T> | ||
13 | class ConfPair : public ConfPairBase | ||
14 | { | ||
15 | public: | ||
16 | ConfPair( const std::string &sName ) : | ||
17 | sName( sName ) | ||
18 | { } | ||
19 | |||
20 | virtual ~ConfPair() | ||
21 | { } | ||
22 | |||
23 | T &value() | ||
24 | { | ||
25 | return tValue; | ||
26 | } | ||
27 | |||
28 | const std::string &name() | ||
29 | { | ||
30 | return sName; | ||
31 | } | ||
32 | |||
33 | virtual void setFromString( const std::string &sStr ) | ||
34 | { | ||
35 | std::stringstream(sStr) >> tValue; | ||
36 | } | ||
37 | |||
38 | virtual std::string getAsString() | ||
39 | { | ||
40 | std::stringstream tmp; | ||
41 | tmp << tValue; | ||
42 | return tmp.str(); | ||
43 | } | ||
44 | |||
45 | private: | ||
46 | std::string sName; | ||
47 | T tValue; | ||
48 | }; | ||
49 | |||
50 | template<> | ||
51 | void ConfPair<std::string>::setFromString( const std::string &sStr ) | ||
52 | { | ||
53 | tValue = sStr; | ||
54 | } | ||
55 | |||
56 | template<> | ||
57 | std::string ConfPair<std::string>::getAsString() | ||
58 | { | ||
59 | return tValue; | ||
60 | } | ||
61 | |||
62 | template<> | ||
63 | void ConfPair<bool>::setFromString( const std::string &sStr ) | ||
64 | { | ||
65 | if( !strcasecmp( sStr.c_str(), "true" ) || | ||
66 | !strcasecmp( sStr.c_str(), "yes" ) || | ||
67 | !strcasecmp( sStr.c_str(), "on" ) ) | ||
68 | tValue = true; | ||
69 | else | ||
70 | tValue = false; | ||
71 | } | ||
72 | |||
73 | template<> | ||
74 | std::string ConfPair<bool>::getAsString() | ||
75 | { | ||
76 | if( tValue == true ) | ||
77 | return "True"; | ||
78 | return "False"; | ||
79 | } | ||
80 | |||
81 | #endif | ||
diff --git a/src/old/confpairbase.cpp b/src/old/confpairbase.cpp new file mode 100644 index 0000000..1203dc0 --- /dev/null +++ b/src/old/confpairbase.cpp | |||
@@ -0,0 +1,17 @@ | |||
1 | #include "confpairbase.h" | ||
2 | |||
3 | ConfPairBase::ConfPairBase() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | ConfPairBase::~ConfPairBase() | ||
8 | { | ||
9 | } | ||
10 | |||
11 | ConfPairBase &ConfPairBase::operator=( const std::string &s ) | ||
12 | { | ||
13 | setFromString( s ); | ||
14 | |||
15 | return *this; | ||
16 | } | ||
17 | |||
diff --git a/src/old/confpairbase.h b/src/old/confpairbase.h new file mode 100644 index 0000000..2530756 --- /dev/null +++ b/src/old/confpairbase.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef CONF_PAIR_BASE_H | ||
2 | #define CONF_PAIR_BASE_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <string> | ||
6 | #include <ostream> | ||
7 | #include <istream> | ||
8 | |||
9 | class ConfPairBase | ||
10 | { | ||
11 | public: | ||
12 | ConfPairBase(); | ||
13 | virtual ~ConfPairBase(); | ||
14 | |||
15 | virtual void setFromString( const std::string &sStr )=0; | ||
16 | virtual std::string getAsString()=0; | ||
17 | |||
18 | ConfPairBase &operator=( const std::string &s ); | ||
19 | |||
20 | private: | ||
21 | |||
22 | }; | ||
23 | |||
24 | #endif | ||
diff --git a/src/old/conftree.cpp b/src/old/conftree.cpp new file mode 100644 index 0000000..d9a3a3f --- /dev/null +++ b/src/old/conftree.cpp | |||
@@ -0,0 +1,9 @@ | |||
1 | #include "conftree.h" | ||
2 | |||
3 | ConfTree::ConfTree() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | ConfTree::~ConfTree() | ||
8 | { | ||
9 | } | ||
diff --git a/src/old/conftree.h b/src/old/conftree.h new file mode 100644 index 0000000..197b1ef --- /dev/null +++ b/src/old/conftree.h | |||
@@ -0,0 +1,19 @@ | |||
1 | #ifndef CONF_TREE_H | ||
2 | #define CONF_TREE_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | |||
6 | /** | ||
7 | * | ||
8 | */ | ||
9 | class ConfTree | ||
10 | { | ||
11 | public: | ||
12 | ConfTree(); | ||
13 | virtual ~ConfTree(); | ||
14 | |||
15 | private: | ||
16 | |||
17 | }; | ||
18 | |||
19 | #endif | ||
diff --git a/src/old/connection.cpp b/src/old/connection.cpp new file mode 100644 index 0000000..efef144 --- /dev/null +++ b/src/old/connection.cpp | |||
@@ -0,0 +1,564 @@ | |||
1 | #include "connection.h" | ||
2 | #include <string.h> | ||
3 | #include <stdio.h> | ||
4 | #include <errno.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <unistd.h> | ||
7 | #include <sys/types.h> | ||
8 | #include <sys/socket.h> | ||
9 | #include <sys/time.h> | ||
10 | #include <netinet/in.h> | ||
11 | #include <netdb.h> | ||
12 | #include <arpa/inet.h> | ||
13 | #include <errno.h> | ||
14 | #include <fcntl.h> | ||
15 | #include "exceptions.h" | ||
16 | |||
17 | // Read buffer size...maybe fix wierd issues... | ||
18 | #define RBS (1024*10) | ||
19 | |||
20 | Connection::Connection() | ||
21 | { | ||
22 | nSocket = -1; | ||
23 | bActive = false; | ||
24 | bDisconnectMe = false; | ||
25 | pProtocol = NULL; | ||
26 | } | ||
27 | |||
28 | Connection::~Connection() | ||
29 | { | ||
30 | if( pProtocol != NULL ) delete pProtocol; | ||
31 | } | ||
32 | |||
33 | void Connection::ensureCapacity( int nSize ) | ||
34 | { | ||
35 | xOutputBuf.ensureCapacity( nSize ); | ||
36 | } | ||
37 | |||
38 | bool Connection::appendOutput( const char *lpOutput, int nSize ) | ||
39 | { | ||
40 | return xOutputBuf.appendData( lpOutput, nSize ); | ||
41 | } | ||
42 | |||
43 | bool Connection::appendOutput( const char lOutput ) | ||
44 | { | ||
45 | return xOutputBuf.appendData( lOutput ); | ||
46 | } | ||
47 | |||
48 | bool Connection::appendOutput( const short lOutput ) | ||
49 | { | ||
50 | return xOutputBuf.appendData( lOutput ); | ||
51 | } | ||
52 | |||
53 | bool Connection::appendOutput( const int lOutput ) | ||
54 | { | ||
55 | return xOutputBuf.appendData( lOutput ); | ||
56 | } | ||
57 | |||
58 | bool Connection::appendOutput( const long lOutput ) | ||
59 | { | ||
60 | return xOutputBuf.appendData( lOutput ); | ||
61 | } | ||
62 | |||
63 | bool Connection::appendOutput( const float lOutput ) | ||
64 | { | ||
65 | return xOutputBuf.appendData( lOutput ); | ||
66 | } | ||
67 | |||
68 | bool Connection::appendOutput( const double lOutput ) | ||
69 | { | ||
70 | return xOutputBuf.appendData( lOutput ); | ||
71 | } | ||
72 | |||
73 | bool Connection::appendOutput( const unsigned char lOutput ) | ||
74 | { | ||
75 | return xOutputBuf.appendData( lOutput ); | ||
76 | } | ||
77 | |||
78 | bool Connection::appendOutput( const unsigned short lOutput ) | ||
79 | { | ||
80 | return xOutputBuf.appendData( lOutput ); | ||
81 | } | ||
82 | |||
83 | bool Connection::appendOutput( const unsigned long lOutput ) | ||
84 | { | ||
85 | return xOutputBuf.appendData( lOutput ); | ||
86 | } | ||
87 | |||
88 | bool Connection::appendOutput( const unsigned int lOutput ) | ||
89 | { | ||
90 | return xOutputBuf.appendData( lOutput ); | ||
91 | } | ||
92 | |||
93 | bool Connection::appendInput( const char *lpInput, int nSize ) | ||
94 | { | ||
95 | return xInputBuf.appendData( lpInput, nSize ); | ||
96 | } | ||
97 | |||
98 | int Connection::scanInputFor( char cTarget ) | ||
99 | { | ||
100 | const char *lpTmp = xInputBuf.getData(); | ||
101 | int jMax = xInputBuf.getLength(); | ||
102 | |||
103 | for( int j = 0; j < jMax; j++ ) | ||
104 | { | ||
105 | if( lpTmp[j] == cTarget ) | ||
106 | { | ||
107 | return j; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | return -1; | ||
112 | } | ||
113 | |||
114 | const char *Connection::getOutput() | ||
115 | { | ||
116 | return xOutputBuf.getData(); | ||
117 | } | ||
118 | |||
119 | const char *Connection::getInput() | ||
120 | { | ||
121 | return xInputBuf.getData(); | ||
122 | } | ||
123 | |||
124 | void Connection::setSocket( int nNewSocket ) | ||
125 | { | ||
126 | nSocket = nNewSocket; | ||
127 | } | ||
128 | |||
129 | int Connection::getSocket() | ||
130 | { | ||
131 | return nSocket; | ||
132 | } | ||
133 | |||
134 | bool Connection::isActive() | ||
135 | { | ||
136 | return bActive; | ||
137 | } | ||
138 | |||
139 | void Connection::close() | ||
140 | { | ||
141 | //printf("Close called, socket is: %s\n", bActive?"Active":"Inactive" ); | ||
142 | if( bActive ) | ||
143 | { | ||
144 | fsync( nSocket ); | ||
145 | ::close( nSocket ); | ||
146 | //printf("Socket closed.\n"); | ||
147 | } | ||
148 | bActive = false; | ||
149 | //nSocket = -1; | ||
150 | xInputBuf.clearData(); | ||
151 | xOutputBuf.clearData(); | ||
152 | if( pProtocol != NULL ) | ||
153 | { | ||
154 | delete pProtocol; | ||
155 | pProtocol = NULL; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | bool Connection::open( int nNewSocket ) | ||
160 | { | ||
161 | bActive = true; | ||
162 | setSocket( nNewSocket ); | ||
163 | bDisconnectMe = false; | ||
164 | |||
165 | return true; | ||
166 | } | ||
167 | |||
168 | bool Connection::open( const char *sAddr, int nPort, int nSec ) | ||
169 | { | ||
170 | struct sockaddr_in xServerName; | ||
171 | bActive = false; | ||
172 | |||
173 | /* Create the socket. */ | ||
174 | nSocket = socket( PF_INET, SOCK_STREAM, 0 ); | ||
175 | |||
176 | if( nSocket < 0 ) | ||
177 | { | ||
178 | bActive = false; | ||
179 | return false; | ||
180 | } | ||
181 | |||
182 | // These lines set the socket to non-blocking, a good thing? | ||
183 | int flags; | ||
184 | flags = fcntl(nSocket, F_GETFL, 0); | ||
185 | flags |= O_NONBLOCK; | ||
186 | if (fcntl(nSocket, F_SETFL, flags) < 0) | ||
187 | { | ||
188 | return false; | ||
189 | } | ||
190 | |||
191 | /* Connect to the server. */ | ||
192 | //printf("Resolving hostname (%s)...\n", sAddr ); | ||
193 | { | ||
194 | struct hostent *hostinfo; | ||
195 | |||
196 | xServerName.sin_family = AF_INET; | ||
197 | xServerName.sin_port = htons( nPort ); | ||
198 | hostinfo = gethostbyname( sAddr ); | ||
199 | if (hostinfo == NULL) | ||
200 | { | ||
201 | return false; | ||
202 | } | ||
203 | xServerName.sin_addr = *(struct in_addr *) hostinfo->h_addr; | ||
204 | } | ||
205 | |||
206 | //printf("Making actual connection..."); | ||
207 | //fflush( stdout ); | ||
208 | connect( | ||
209 | nSocket, | ||
210 | (struct sockaddr *)&xServerName, | ||
211 | sizeof(xServerName) | ||
212 | ); | ||
213 | //printf("Connected.\n"); | ||
214 | |||
215 | bActive = true; | ||
216 | bDisconnectMe = false; | ||
217 | |||
218 | if( nSec > 0 ) | ||
219 | { | ||
220 | fd_set rfds, wfds, efds; | ||
221 | int retval; | ||
222 | |||
223 | FD_ZERO(&rfds); | ||
224 | FD_SET(nSocket, &rfds); | ||
225 | FD_ZERO(&wfds); | ||
226 | FD_SET(nSocket, &wfds); | ||
227 | FD_ZERO(&efds); | ||
228 | FD_SET(nSocket, &efds); | ||
229 | |||
230 | struct timeval tv; | ||
231 | tv.tv_sec = nSec; | ||
232 | tv.tv_usec = 0; | ||
233 | |||
234 | retval = select( nSocket+1, &rfds, &wfds, &efds, &tv ); | ||
235 | |||
236 | if( retval == 0 ) | ||
237 | { | ||
238 | close(); | ||
239 | throw ExceptionBase("Connection timeout.\n"); | ||
240 | } | ||
241 | |||
242 | } | ||
243 | |||
244 | /* | ||
245 | if( ret < 0 ) | ||
246 | { | ||
247 | return false; | ||
248 | }*/ | ||
249 | |||
250 | return true; | ||
251 | } | ||
252 | |||
253 | int Connection::readInput() | ||
254 | { | ||
255 | char buffer[RBS]; | ||
256 | int nbytes; | ||
257 | int nTotalRead=0; | ||
258 | |||
259 | for(;;) | ||
260 | { | ||
261 | //memset( buffer, 0, RBS ); | ||
262 | |||
263 | nbytes = read( nSocket, buffer, RBS ); | ||
264 | if( nbytes < 0 && errno != 0 && errno != EAGAIN ) | ||
265 | { | ||
266 | //printf("errno: %d, %s\n", errno, strerror( errno ) ); | ||
267 | /* Read error. */ | ||
268 | //perror("readInput"); | ||
269 | throw ConnectionException( excodeReadError, "Read error: %s", strerror( errno ) ); | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | if( nbytes <= 0 ) | ||
274 | break; | ||
275 | nTotalRead += nbytes; | ||
276 | appendInput( buffer, nbytes ); | ||
277 | /* Data read. */ | ||
278 | if( nbytes < RBS ) | ||
279 | { | ||
280 | break; | ||
281 | } | ||
282 | |||
283 | /* New test, if data is divisible by RBS bytes on some libs the | ||
284 | * read could block, this keeps it from happening. | ||
285 | */ | ||
286 | { | ||
287 | fd_set rfds; | ||
288 | FD_ZERO(&rfds); | ||
289 | FD_SET(nSocket, &rfds); | ||
290 | struct timeval tv = { 0, 0 }; | ||
291 | int retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); | ||
292 | if( retval == -1 ) | ||
293 | throw ConnectionException( | ||
294 | excodeBadReadError, | ||
295 | "Bad Read error" | ||
296 | ); | ||
297 | if( !FD_ISSET( nSocket, &rfds ) ) | ||
298 | break; | ||
299 | } | ||
300 | |||
301 | } | ||
302 | } | ||
303 | |||
304 | if( pProtocol != NULL && nTotalRead > 0 ) | ||
305 | { | ||
306 | pProtocol->onNewData(); | ||
307 | } | ||
308 | |||
309 | return nTotalRead; | ||
310 | } | ||
311 | |||
312 | bool Connection::readInput( int nSec, int nUSec, int *pnSecBack, int *pnUSecBack ) | ||
313 | { | ||
314 | fd_set rfds, efds; | ||
315 | struct timeval tv, start, end; | ||
316 | struct timezone tz; | ||
317 | int retval; | ||
318 | |||
319 | gettimeofday( &start, &tz ); | ||
320 | |||
321 | FD_ZERO(&rfds); | ||
322 | FD_SET(nSocket, &rfds); | ||
323 | FD_ZERO(&efds); | ||
324 | FD_SET(nSocket, &efds); | ||
325 | |||
326 | tv.tv_sec = nSec; | ||
327 | tv.tv_usec = nUSec; | ||
328 | |||
329 | //printf("Starting at %d %d\n", nSec, nUSec ); | ||
330 | retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); | ||
331 | |||
332 | if( retval == -1 ) | ||
333 | { | ||
334 | // Oh my god!!! some kind of horrible problem!!!! | ||
335 | throw ConnectionException( excodeBadReadError, "Bad Read error"); | ||
336 | return false; | ||
337 | } | ||
338 | else if( retval ) | ||
339 | { | ||
340 | //printf("retval=%d, nSocket=%d,%d, sec=%d, usec=%d\n", retval, nSocket, FD_ISSET( nSocket, &rfds ), tv.tv_sec, tv.tv_usec ); | ||
341 | // None of them have data, but the connection is still active. | ||
342 | if( FD_ISSET( nSocket, &rfds ) ) | ||
343 | { | ||
344 | if( readInput() == 0 ) | ||
345 | { | ||
346 | throw ConnectionException( excodeConnectionClosed, "Connection closed"); } | ||
347 | } | ||
348 | } | ||
349 | |||
350 | gettimeofday( &end, &tz ); | ||
351 | |||
352 | int st, ust; | ||
353 | st = nSec - ( end.tv_sec - start.tv_sec ); | ||
354 | if( ( end.tv_usec - start.tv_usec ) > nUSec ) | ||
355 | { | ||
356 | (st)--; | ||
357 | ust = 1000000 - (end.tv_usec - start.tv_usec); | ||
358 | } | ||
359 | else | ||
360 | { | ||
361 | ust = nUSec - (end.tv_usec - start.tv_usec); | ||
362 | } | ||
363 | |||
364 | if( st < 0 ) | ||
365 | { | ||
366 | st = ust = 0; | ||
367 | } | ||
368 | |||
369 | if( pnSecBack ) | ||
370 | { | ||
371 | *pnSecBack = st; | ||
372 | *pnUSecBack = ust; | ||
373 | } | ||
374 | |||
375 | //printf("New time: %d %d\n", *pnSecBack, *pnUSecBack ); | ||
376 | |||
377 | return true; | ||
378 | } | ||
379 | |||
380 | void Connection::waitForInput( int nBytesIn, int nSec, int nUSec ) | ||
381 | { | ||
382 | int rlen = getInputAmnt(); | ||
383 | |||
384 | if( rlen >= nBytesIn ) | ||
385 | return; | ||
386 | |||
387 | while( rlen < nBytesIn ) | ||
388 | { | ||
389 | if( nSec == 0 && nUSec == 0 ) | ||
390 | { | ||
391 | throw ConnectionException( excodeSocketTimeout, "Timed out while waiting for %d bytes.", nBytesIn ); | ||
392 | } | ||
393 | readInput( nSec, nUSec, &nSec, &nUSec ); | ||
394 | rlen = getInputAmnt(); | ||
395 | } | ||
396 | } | ||
397 | |||
398 | bool Connection::clearOutput() | ||
399 | { | ||
400 | return xOutputBuf.clearData(); | ||
401 | } | ||
402 | |||
403 | bool Connection::clearInput() | ||
404 | { | ||
405 | return xInputBuf.clearData(); | ||
406 | } | ||
407 | |||
408 | #define min( a, b ) ((a<b)?(a):(b)) | ||
409 | |||
410 | bool Connection::writeOutput() | ||
411 | { | ||
412 | //int nBytes = TEMP_FAILURE_RETRY( write( nSocket, xOutputBuf.getData(), min( RBS, xOutputBuf.getLength() ) ) ); | ||
413 | int nBytes = TEMP_FAILURE_RETRY( write( nSocket, xOutputBuf.getData(), xOutputBuf.getLength() ) ); | ||
414 | if( nBytes < 0 ) | ||
415 | { | ||
416 | perror("writeOutput"); | ||
417 | return true; | ||
418 | } | ||
419 | /* | ||
420 | if( nBytes < xOutputBuf.getLength() ) | ||
421 | { | ||
422 | printf("Havn't written all the data (%d/%d/%d%%)\n", nBytes, xOutputBuf.getLength(), nBytes/(xOutputBuf.getLength()*100) ); | ||
423 | } | ||
424 | else | ||
425 | { | ||
426 | printf("Wrote all pending data.\n"); | ||
427 | } | ||
428 | */ | ||
429 | xOutputBuf.usedData( nBytes ); | ||
430 | //clearOutput(); | ||
431 | |||
432 | return true; | ||
433 | } | ||
434 | |||
435 | bool Connection::writeAllOutput() | ||
436 | { | ||
437 | while( hasOutput() ) writeOutput(); | ||
438 | return true; | ||
439 | } | ||
440 | |||
441 | bool Connection::hasOutput() | ||
442 | { | ||
443 | if( xOutputBuf.getLength() == 0 ) | ||
444 | { | ||
445 | return false; | ||
446 | } | ||
447 | else | ||
448 | { | ||
449 | return true; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | bool Connection::hasInput() | ||
454 | { | ||
455 | if( xInputBuf.getLength() == 0 ) | ||
456 | { | ||
457 | return false; | ||
458 | } | ||
459 | else | ||
460 | { | ||
461 | return true; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | bool Connection::usedInput( int nAmount ) | ||
466 | { | ||
467 | return xInputBuf.usedData( nAmount ); | ||
468 | } | ||
469 | |||
470 | bool Connection::needDisconnect() | ||
471 | { | ||
472 | return bDisconnectMe; | ||
473 | } | ||
474 | |||
475 | void Connection::disconnect() | ||
476 | { | ||
477 | bDisconnectMe = true; | ||
478 | } | ||
479 | |||
480 | void Connection::setProtocol( class Protocol *pNewProtocol ) | ||
481 | { | ||
482 | pProtocol = pNewProtocol; | ||
483 | pProtocol->setConnection( this ); | ||
484 | } | ||
485 | |||
486 | int Connection::getInputAmnt() | ||
487 | { | ||
488 | return xInputBuf.getLength(); | ||
489 | } | ||
490 | |||
491 | int Connection::getOutputAmnt() | ||
492 | { | ||
493 | return xOutputBuf.getLength(); | ||
494 | } | ||
495 | |||
496 | class Protocol *Connection::getProtocol() | ||
497 | { | ||
498 | return pProtocol; | ||
499 | } | ||
500 | |||
501 | void Connection::printInputDebug( const char *lpPrefix, FILE *fh, int nBytesMax ) | ||
502 | { | ||
503 | printDataDebug( | ||
504 | (const unsigned char *)xInputBuf.getData(), | ||
505 | xInputBuf.getLength(), | ||
506 | "input", | ||
507 | lpPrefix, | ||
508 | fh, | ||
509 | nBytesMax | ||
510 | ); | ||
511 | } | ||
512 | |||
513 | void Connection::printOutputDebug( const char *lpPrefix, FILE *fh, int nBytesMax ) | ||
514 | { | ||
515 | printDataDebug( | ||
516 | (const unsigned char *)xOutputBuf.getData(), | ||
517 | xOutputBuf.getLength(), | ||
518 | "output", | ||
519 | lpPrefix, | ||
520 | fh, | ||
521 | nBytesMax | ||
522 | ); | ||
523 | } | ||
524 | |||
525 | void Connection::printDataDebug( const unsigned char *pData, long nDataLen, const char *lpName, const char *lpPrefix, FILE *fh, int nBytesMax ) | ||
526 | { | ||
527 | if( nBytesMax > 0 ) | ||
528 | { | ||
529 | nDataLen = (nBytesMax<nDataLen)?(nBytesMax):(nDataLen); | ||
530 | } | ||
531 | |||
532 | fprintf( fh, "%sDisplaying %ld bytes of %s.\n", lpPrefix, nDataLen, lpName ); | ||
533 | int j = 0; | ||
534 | fprintf( fh, lpPrefix ); | ||
535 | for( int l = 0; l < 8*3+2*8+2; l++ ) fprintf( fh, (l!=8*3)?("-"):("+") ); fprintf( fh, "\n"); | ||
536 | for(;;) | ||
537 | { | ||
538 | fprintf( fh, lpPrefix ); | ||
539 | int kmax = 8; | ||
540 | if( nDataLen-j < 8 ) kmax = nDataLen-j; | ||
541 | for(int k = 0; k < 8; k++ ) | ||
542 | { | ||
543 | if( k < kmax ) | ||
544 | { | ||
545 | fprintf( fh, "%02X ", (int)((unsigned char)pData[j+k]) ); | ||
546 | } | ||
547 | else | ||
548 | { | ||
549 | fprintf( fh, "-- "); | ||
550 | } | ||
551 | } | ||
552 | printf("| "); | ||
553 | for(int k = 0; k < kmax; k++ ) | ||
554 | { | ||
555 | fprintf( fh, "%c ", (pData[j+k]>32 && pData[j+k]<=128)?(pData[j+k]):('.') ); | ||
556 | } | ||
557 | fprintf( fh, "\n"); | ||
558 | j += kmax; | ||
559 | if( j >= nDataLen ) break; | ||
560 | } | ||
561 | fprintf( fh, lpPrefix ); | ||
562 | for( int l = 0; l < 8*3+2*8+2; l++ ) fprintf( fh, (l!=8*3)?("-"):("+") ); fprintf( fh, "\n"); | ||
563 | } | ||
564 | |||
diff --git a/src/old/connection.h b/src/old/connection.h new file mode 100644 index 0000000..0e991c7 --- /dev/null +++ b/src/old/connection.h | |||
@@ -0,0 +1,411 @@ | |||
1 | /**\file | ||
2 | * Contains the Connection class. | ||
3 | *@author Mike Buland | ||
4 | */ | ||
5 | |||
6 | #ifndef CONNECTION_H | ||
7 | #define CONNECTION_H | ||
8 | |||
9 | #include "multilog.h" | ||
10 | #include "flexbuf.h" | ||
11 | #include "protocol.h" | ||
12 | |||
13 | /** Represents a single connection on a network. While these connections | ||
14 | * may be treated more or less just like files, occasionally problems arise | ||
15 | * when writing data at any time you feel like. Therefore you run all your | ||
16 | * data through a Connection, which buffers all data and makes sure no | ||
17 | * buffers are exceeded and nothing inappropriate for the recipient of the | ||
18 | * data is sent. | ||
19 | *@author Mike Buland | ||
20 | */ | ||
21 | class Connection | ||
22 | { | ||
23 | public: | ||
24 | /** | ||
25 | * Construct a blank and non-connected Connection. The created object is | ||
26 | * not yet connected to anything, and most of the functions except open are | ||
27 | * unusable. | ||
28 | */ | ||
29 | Connection(); | ||
30 | |||
31 | /** | ||
32 | * Destroy the connection, clean up all pending data requests and close the | ||
33 | * contained socket. This does not send out pending data, especially since | ||
34 | * such an operation could take considerable time, depending on the pending | ||
35 | * data and state of the receiving end. | ||
36 | */ | ||
37 | virtual ~Connection(); | ||
38 | |||
39 | /** | ||
40 | * Open a connection to a remote server. This sets up this connection as | ||
41 | * a client instead of a server and does all of the work that needs to be | ||
42 | * done to actually open an INET_AF connection, which is a lot of work. | ||
43 | *@param sAddr The address to connect to. This can be in any format | ||
44 | * normally understood by your system to be an address, ip, domain name, | ||
45 | * etc. | ||
46 | *@param nPort The port number to connect to on the remote server. | ||
47 | *@returns True if the connection was successful and everything is setup, | ||
48 | * false if there were any of a dozen errors and the connection is not set. | ||
49 | *@todo Make this function add log entries to a standard MultiLog if | ||
50 | * something goes wrong. | ||
51 | */ | ||
52 | bool open( const char *sAddr, int nPort, int nSec=30 ); | ||
53 | |||
54 | void ensureCapacity( int nSize ); | ||
55 | |||
56 | /** Append the given data to the output. The data is presumed to be null | ||
57 | * terminated. To put binary data into the stream, use the other | ||
58 | * appendOutput function. This should be the only method used to | ||
59 | * communicate with the socket. | ||
60 | *@param lpOutput The data to add to the output queue. | ||
61 | *@param nSize How much data is in the lpOutput buffer. If this value | ||
62 | * is -1 then the program treats lpOutput as a null-terminated string. | ||
63 | *@returns True if everything is ok, false otherwise. | ||
64 | */ | ||
65 | bool appendOutput( const char *lpOutput, int nSize=-1 ); | ||
66 | |||
67 | /** | ||
68 | * Append the character to the output. | ||
69 | *@param lOutput The character to add to the output queue. | ||
70 | *@returns True if everything is ok, false otherwise. | ||
71 | */ | ||
72 | bool appendOutput( const char lOutput ); | ||
73 | |||
74 | /** | ||
75 | * Append the short to the output. | ||
76 | *@param lOutput The short to add to the output queue. | ||
77 | *@returns True if everything is ok, false otherwise. | ||
78 | */ | ||
79 | bool appendOutput( const short lOutput ); | ||
80 | |||
81 | /** | ||
82 | * Append the int to the output. | ||
83 | *@param lOutput The int to add to the output queue. | ||
84 | *@returns True if everything is ok, false otherwise. | ||
85 | */ | ||
86 | bool appendOutput( const int lOutput ); | ||
87 | |||
88 | /** | ||
89 | * Append the long to the output. | ||
90 | *@param lOutput The long to add to the output queue. | ||
91 | *@returns True if everything is ok, false otherwise. | ||
92 | */ | ||
93 | bool appendOutput( const long lOutput ); | ||
94 | |||
95 | /** | ||
96 | * Append the float to the output. | ||
97 | *@param lOutput The float to add to the output queue. | ||
98 | *@returns True if everything is ok, false otherwise. | ||
99 | */ | ||
100 | bool appendOutput( const float lOutput ); | ||
101 | |||
102 | /** | ||
103 | * Append the double to the output. | ||
104 | *@param lOutput The double to add to the output queue. | ||
105 | *@returns True if everything is ok, false otherwise. | ||
106 | */ | ||
107 | bool appendOutput( const double lOutput ); | ||
108 | |||
109 | /** | ||
110 | * Append the unsigned char to the output. | ||
111 | *@param lOutput The unsigned char to add to the output queue. | ||
112 | *@returns True if everything is ok, false otherwise. | ||
113 | */ | ||
114 | bool appendOutput( const unsigned char lOutput ); | ||
115 | |||
116 | /** | ||
117 | * Append the unsigned short to the output. | ||
118 | *@param lOutput The unsigned short to add to the output queue. | ||
119 | *@returns True if everything is ok, false otherwise. | ||
120 | */ | ||
121 | bool appendOutput( const unsigned short lOutput ); | ||
122 | |||
123 | /** | ||
124 | * Append the unsigned int to the output. | ||
125 | *@param lOutput The unsigned int to add to the output queue. | ||
126 | *@returns True if everything is ok, false otherwise. | ||
127 | */ | ||
128 | bool appendOutput( const unsigned int lOutput ); | ||
129 | |||
130 | /** | ||
131 | * Append the unsigned long to the output. | ||
132 | *@param lOutput The unsigned long to add to the output queue. | ||
133 | *@returns True if everything is ok, false otherwise. | ||
134 | */ | ||
135 | bool appendOutput( const unsigned long lOutput ); | ||
136 | |||
137 | /** | ||
138 | * Writes all input data in the buffer in a dual-view ascii and hex display | ||
139 | * to a file. There are a number of options that also help with debugging. | ||
140 | *@param lpPrefix Text to be added to the begining of every line written | ||
141 | * out. The default is a blank string. | ||
142 | *@param fh The file to write the data to in text mode. This is stdout by | ||
143 | * default, but could be any already open file handle. | ||
144 | *@param nBytesMax The maximum number of bytes to write to the output. The | ||
145 | * amount of data can be overwhelming sometimes, so you can limit it. The | ||
146 | * default value is -1, which is also unlimited. | ||
147 | */ | ||
148 | void printInputDebug( const char *lpPrefix="", FILE *fh=stdout, int nBytesMax=-1 ); | ||
149 | |||
150 | /** | ||
151 | * Writes all output data in the buffer in a dual-view ascii and hex display | ||
152 | * to a file. There are a number of options that also help with debugging. | ||
153 | *@param lpPrefix Text to be added to the begining of every line written | ||
154 | * out. The default is a blank string. | ||
155 | *@param fh The file to write the data to in text mode. This is stdout by | ||
156 | * default, but could be any already open file handle. | ||
157 | *@param nBytesMax The maximum number of bytes to write to the output. The | ||
158 | * amount of data can be overwhelming sometimes, so you can limit it. The | ||
159 | * default value is -1, which is also unlimited. | ||
160 | */ | ||
161 | void printOutputDebug( const char *lpPrefix="", FILE *fh=stdout, int nBytesMax=-1 ); | ||
162 | |||
163 | /** | ||
164 | * This is the low-level generic function that is called by both | ||
165 | * printInputDebug and printOutputDebug. It works effectively just like | ||
166 | * both of them, except that you can give it a raw pointer to the data to | ||
167 | * print out. This probably doesn't belong in this class, but this was | ||
168 | * where I was when I needed it. | ||
169 | *@param pData A pointer to the data to write. This is not treated as a | ||
170 | * null terminated string, so make sure that the nDataLen param is set | ||
171 | * properly. | ||
172 | *@param nDataLen The number of bytes that are in pData and that you want to | ||
173 | * see. | ||
174 | *@param lpName The name of the data, this is used in the header where it | ||
175 | * says "Displaying nnn bytes of <lpName>." A good example would be input | ||
176 | * or output. | ||
177 | *@param lpPrefix Text to put before every line output. This just makes it | ||
178 | * easier to tell large blocks apart in the output. | ||
179 | *@param fh The file handle to write all data to. | ||
180 | *@param nBytesMax The maximum number of bytes. This parameter is stupid. | ||
181 | * If it is set to -1, then nDataLen is used, otherwise the smaller value is | ||
182 | * used as the number of bytes to output. | ||
183 | *@todo Put this function somewhere more deserving. | ||
184 | *@todo Remove the nBytesMax param, we need that in the other functions, | ||
185 | * not this one! | ||
186 | */ | ||
187 | void printDataDebug( const unsigned char *pData, long nDataLen, const char *lpName, const char *lpPrefix, FILE *fh, int nBytesMax ); | ||
188 | |||
189 | /** Append the given data to the input. The data is presumed to be null | ||
190 | * terminated. To put binary data into the stream, use the other | ||
191 | * appendInput function. This is mainly used by internal routines. | ||
192 | *@param lpInput The data to add to the input queue. | ||
193 | *@param nSize How much data is in the lpInput buffer. If this value | ||
194 | * is -1 then the program treats lpOutput as a null-terminated string. | ||
195 | *@returns True if everything is ok, false otherwise. | ||
196 | */ | ||
197 | bool appendInput( const char *lpInput, int nSize=-1 ); | ||
198 | |||
199 | /** Searches through the current pending input for a certain character. | ||
200 | * This is useful for finding out where exactly the end of a line is, for | ||
201 | * example, to see if a command has been entered yet. | ||
202 | *@param cTarget The character to search for. | ||
203 | *@returns The position of the target relative to the begining of the input | ||
204 | * or -1 if the target wasn't found. | ||
205 | */ | ||
206 | int scanInputFor( char cTarget ); | ||
207 | |||
208 | /** Gets a pointer to the output buffer. This is mainly used by internal | ||
209 | * routines, and is cleared every click when data is sent out again. | ||
210 | *@returns A pointer to the buffer holding the pending output data. | ||
211 | */ | ||
212 | const char *getOutput(); | ||
213 | |||
214 | /** Gets a pointer to the start of the input buffer's active data | ||
215 | * section. Use this to gain access to the input you need to do | ||
216 | * your job. | ||
217 | *@returns A pointer to the data in the input buffer. Do not delete this. | ||
218 | */ | ||
219 | const char *getInput(); | ||
220 | |||
221 | /** Clears all pending output, this is mainly just used internally. | ||
222 | *@returns True if operation was a success, otherwise false. | ||
223 | */ | ||
224 | bool clearOutput(); | ||
225 | |||
226 | /** Clears all pending input, weather it's been used or not. Please | ||
227 | * refrain from calling this during normal operation, use usedInput | ||
228 | * instead, it's much safer. | ||
229 | *@returns True if the operation was a success, false otherwise. | ||
230 | */ | ||
231 | bool clearInput(); | ||
232 | |||
233 | /** Sets the socket that should be used internally. | ||
234 | *@param nNewSocket The new socket to work with. | ||
235 | */ | ||
236 | void setSocket( int nNewSocket ); | ||
237 | |||
238 | /** Gets the handle (number) of the working socket. This can be a | ||
239 | * dangerous function to call, please refrain from calling it directly | ||
240 | * if any alternative can be found. | ||
241 | *@returns The number of the working socket. | ||
242 | */ | ||
243 | int getSocket(); | ||
244 | |||
245 | /** Determines if the connection is still active. | ||
246 | *@returns True if the connection is active, false otherwise. | ||
247 | */ | ||
248 | bool isActive(); | ||
249 | |||
250 | /** Clears all buffers and sets up the connection to be reused. | ||
251 | * Does not actually close the socket, that's handled by the | ||
252 | * ConnectionManager | ||
253 | */ | ||
254 | void close(); | ||
255 | |||
256 | /** Opens a socket. Really just sets up the connection for use since | ||
257 | * the socket itself was created and opened by the ConnectionManager. | ||
258 | * This also calls setSocket so you don't have to. | ||
259 | *@param nNewSocket The socket to assosiate with. | ||
260 | */ | ||
261 | bool open( int nNewSocket ); | ||
262 | |||
263 | /** | ||
264 | * Reads all pending input from the connection. If this is called outside | ||
265 | * of the ConnectionManager it will usually block indefinately waiting for | ||
266 | * new data. The only way to change this behaviour is to modify the socket | ||
267 | * low-level when you connect it manually, or, preferably use the other | ||
268 | * readInput function to control blocking time. | ||
269 | *@returns True socket is still connected, otherwise false. | ||
270 | */ | ||
271 | int readInput(); | ||
272 | |||
273 | /** | ||
274 | * Reads all pending input from the connection, blocking up to nSec | ||
275 | * seconds and nUSec micro-seconds for the data. This uses select to | ||
276 | * simulate blocking, but has the same effect as standard io blocking. | ||
277 | * If you don't want to block, just set both values to zero. The back | ||
278 | * parameters are optional, set to null to not use them. The variables | ||
279 | * you pass in through the back parameters will contain the remaining | ||
280 | * time if data arrived before the max timeout was reached. | ||
281 | *@param nSec Max seconds to wait. | ||
282 | *@param nUSec Max micro-seconds to wait. | ||
283 | *@param pnSecBack The number of seconds remaining. | ||
284 | *@param pnUSecBack The number of micro-seconds remaining. | ||
285 | */ | ||
286 | bool readInput( int nSec, int nUSec, int *pnSecBack=NULL, int *pnUSecBack=NULL ); | ||
287 | |||
288 | /** | ||
289 | * Waits until at least nBytesIn are read into the input buffer and ready | ||
290 | * to be used. Wait at most nSec seconds plus nUSec micro seconds. | ||
291 | * If the timeout is exceeded, this function throws an exception. If this | ||
292 | * function returns normally, you are guranteed to have at least nBytesIn | ||
293 | * bytes in your input buffer. | ||
294 | *@param nBytesIn Number of bytes to read. | ||
295 | *@param nSec The max seconds to wait. | ||
296 | *@param sUSec The max microseconds to wait. | ||
297 | */ | ||
298 | void waitForInput( int nBytesIn, int nSec, int nUSec ); | ||
299 | |||
300 | /** Writes some data that is pending to the socket. | ||
301 | *@returns True if all data was written succesfully, false otherwise. | ||
302 | */ | ||
303 | bool writeOutput(); | ||
304 | |||
305 | /** | ||
306 | * Writes all data that is pending on the socekt. | ||
307 | */ | ||
308 | bool writeAllOutput(); | ||
309 | |||
310 | /** Determines if the connection has output waiting to go out. | ||
311 | *@returns true if there is pending output, otherwise false. | ||
312 | */ | ||
313 | bool hasOutput(); | ||
314 | |||
315 | /** Sets internal flags so that this connection will be deleted next | ||
316 | * time through the ConnectionManager. | ||
317 | */ | ||
318 | void disconnect(); | ||
319 | |||
320 | /** Determines if this connection is ready to be disconnected or not. | ||
321 | *@returns True if it is time to disconnect, false if it isn't. | ||
322 | */ | ||
323 | bool needDisconnect(); | ||
324 | |||
325 | /** Tells the caller if there is pending input waiting to be processed. | ||
326 | *@returns True if there is pending input that has not been used, returns | ||
327 | * false if there isn't. | ||
328 | */ | ||
329 | bool hasInput(); | ||
330 | |||
331 | /** Removes bytes from the begining of the input queue. Use this after | ||
332 | * getting the input and processing as much as you need to. | ||
333 | *@param nAmount The number of bytes used. | ||
334 | *@returns true if the update was successful, otherwise false. | ||
335 | */ | ||
336 | bool usedInput( int nAmount ); | ||
337 | |||
338 | /** Sets the protocol to be used by this connection. All data in and out | ||
339 | * passes through the protocol object, which may process that data to | ||
340 | * filter out and process any special messages that may have been | ||
341 | * included. Everything that isn't processed can be accessed in the | ||
342 | * standard method. | ||
343 | *@param pNewProtocol A pointer to a protocol object that you want to | ||
344 | * use. | ||
345 | */ | ||
346 | void setProtocol( class Protocol *pNewProtocol ); | ||
347 | |||
348 | /** Gets the number of bytes that are waiting in the input queue, the data | ||
349 | * that has yet to be processed. | ||
350 | *@returns The number of bytes in the input queue. | ||
351 | */ | ||
352 | int getInputAmnt(); | ||
353 | |||
354 | /** Gets the number of bytes that are waiting in the output queue, the data | ||
355 | * that has yet to be sent to the connected socket. | ||
356 | *@returns The number of bytes in the input queue. | ||
357 | */ | ||
358 | int getOutputAmnt(); | ||
359 | |||
360 | /** Gets a pointer to the protocol that is attatched to this connection | ||
361 | * object. This is useful to set modes, and send special commands in | ||
362 | * addition to the standard raw data reads and writes that are normally | ||
363 | * permitted. In fact, in everything besides a raw telnet protocol all | ||
364 | * data should be sent through the protocol and not the connection object. | ||
365 | *@returns A pointer to the Protocol assosiated with this connection. | ||
366 | */ | ||
367 | class Protocol *getProtocol(); | ||
368 | |||
369 | private: | ||
370 | /** | ||
371 | * A buffer to keep data read from the socket in. This is filled in by | ||
372 | * the function readInput, which is automatically called by the | ||
373 | * ConnectionManager whenever new data is ready. | ||
374 | */ | ||
375 | FlexBuf xInputBuf; | ||
376 | |||
377 | /** | ||
378 | * A buffer to keep data that should be sent to the socket. This is filled | ||
379 | * in by using the AppendOutput functions and is sent to the socket using | ||
380 | * the writeOutput function, which is automatically called every cycle by | ||
381 | * the ConnectionManager when there is pending data. | ||
382 | */ | ||
383 | FlexBuf xOutputBuf; | ||
384 | |||
385 | /** | ||
386 | * The socket that the user is connected to. This is not the same as the | ||
387 | * socket number of the listening socket, this is the unique socket on the | ||
388 | * system that the data is coming to. | ||
389 | */ | ||
390 | int nSocket; | ||
391 | |||
392 | /** | ||
393 | * True=active connection, False=connection lost | ||
394 | */ | ||
395 | bool bActive; | ||
396 | |||
397 | /** | ||
398 | * True=disconnect next cycle (after data is transmitted), Flse=keep going. | ||
399 | */ | ||
400 | bool bDisconnectMe; | ||
401 | |||
402 | /** | ||
403 | * A pointer to a protocol handler that can automatically process the data | ||
404 | * in the buffers. This is optional if you use the connections on your own | ||
405 | * but reccomended if you use this with the rest of the ConnectionManager | ||
406 | * system. | ||
407 | */ | ||
408 | class Protocol *pProtocol; | ||
409 | }; | ||
410 | |||
411 | #endif | ||
diff --git a/src/old/connectionmanager.cpp b/src/old/connectionmanager.cpp new file mode 100644 index 0000000..ea60b2b --- /dev/null +++ b/src/old/connectionmanager.cpp | |||
@@ -0,0 +1,397 @@ | |||
1 | #include <time.h> | ||
2 | #include <string.h> | ||
3 | #include <stdio.h> | ||
4 | #include <errno.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <unistd.h> | ||
7 | #include <sys/types.h> | ||
8 | #include <sys/socket.h> | ||
9 | #include <termios.h> | ||
10 | #include <netinet/in.h> | ||
11 | #include <netdb.h> | ||
12 | #include <arpa/inet.h> | ||
13 | #include "connectionmanager.h" | ||
14 | #include <fcntl.h> | ||
15 | |||
16 | ConnectionManager::ConnectionManager( int nInitPool ) : | ||
17 | xLog( MultiLog::getInstance() ) | ||
18 | { | ||
19 | //nMasterSocket = -1; | ||
20 | pMonitor = NULL; | ||
21 | for( int j = 0; j < nInitPool; j++ ) | ||
22 | { | ||
23 | lInactive.insert( lInactive.begin(), new Connection() ); | ||
24 | } | ||
25 | FD_ZERO (&fdActive); | ||
26 | FD_ZERO (&fdRead); | ||
27 | FD_ZERO (&fdWrite); | ||
28 | FD_ZERO (&fdException); | ||
29 | } | ||
30 | |||
31 | ConnectionManager::~ConnectionManager() | ||
32 | { | ||
33 | std::list<Connection *>::const_iterator i; | ||
34 | for( i = lActive.begin(); i != lActive.end(); i++ ) | ||
35 | { | ||
36 | delete (*i); | ||
37 | } | ||
38 | for( i = lInactive.begin(); i != lInactive.end(); i++ ) | ||
39 | { | ||
40 | delete (*i); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | bool ConnectionManager::startServer( int nPort ) | ||
45 | { | ||
46 | /* Create the socket and set it up to accept connections. */ | ||
47 | struct sockaddr_in name; | ||
48 | |||
49 | /* Give the socket a name. */ | ||
50 | name.sin_family = AF_INET; | ||
51 | name.sin_port = htons( nPort ); | ||
52 | |||
53 | // I think this specifies who we will accept connections from, | ||
54 | // a good thing to make configurable later on | ||
55 | name.sin_addr.s_addr = htonl( INADDR_ANY ); | ||
56 | |||
57 | return startServer( name ); | ||
58 | } | ||
59 | |||
60 | bool ConnectionManager::startServer( const char *sAddr, int nPort ) | ||
61 | { | ||
62 | /* Create the socket and set it up to accept connections. */ | ||
63 | struct sockaddr_in name; | ||
64 | |||
65 | /* Give the socket a name. */ | ||
66 | name.sin_family = AF_INET; | ||
67 | name.sin_port = htons( nPort ); | ||
68 | |||
69 | inet_aton( sAddr, &name.sin_addr ); | ||
70 | |||
71 | return startServer( name ); | ||
72 | } | ||
73 | |||
74 | bool ConnectionManager::startServer( struct sockaddr_in &name ) | ||
75 | { | ||
76 | /* Create the socket. */ | ||
77 | int nMasterSocket = socket (PF_INET, SOCK_STREAM, 0); | ||
78 | if (nMasterSocket < 0) | ||
79 | { | ||
80 | xLog.LineLog( MultiLog::LError, "Couldn't create a listen socket."); | ||
81 | return false; | ||
82 | } | ||
83 | |||
84 | int opt = 1; | ||
85 | setsockopt( | ||
86 | nMasterSocket, | ||
87 | SOL_SOCKET, | ||
88 | SO_REUSEADDR, | ||
89 | (char *)&opt, | ||
90 | sizeof(opt) | ||
91 | ); | ||
92 | |||
93 | if (bind (nMasterSocket, (struct sockaddr *) &name, sizeof (name)) < 0) | ||
94 | { | ||
95 | xLog.LineLog( MultiLog::LError, "Couldn't bind to the listen socket."); | ||
96 | return false; | ||
97 | } | ||
98 | |||
99 | if (listen (nMasterSocket, 40) < 0) | ||
100 | { | ||
101 | xLog.LineLog( MultiLog::LError, "Couldn't begin listening to the server socket."); | ||
102 | return false; | ||
103 | } | ||
104 | |||
105 | /* Initialize the set of active sockets. */ | ||
106 | FD_SET (nMasterSocket, &fdActive); | ||
107 | |||
108 | sMasterSocket[nMasterSocket] = name.sin_port; | ||
109 | |||
110 | return true; | ||
111 | } | ||
112 | |||
113 | bool ConnectionManager::startServer( int nPort, int nNumTries, int nTimeout ) | ||
114 | { | ||
115 | struct timeval xTimeout; | ||
116 | |||
117 | for( int j = 0; j < nNumTries; j++ ) | ||
118 | { | ||
119 | xLog.LineLog( MultiLog::LStatus, "Attempting to create server socket (attempt [%d/%d])...", j+1, nNumTries ); | ||
120 | if( startServer( nPort ) == true ) | ||
121 | { | ||
122 | return true; | ||
123 | } | ||
124 | else if( j < nNumTries-1 ) | ||
125 | { | ||
126 | xLog.LineLog( MultiLog::LStatus, "Waiting for %d secconds to allow port to clear...", nTimeout ); | ||
127 | xTimeout.tv_sec = nTimeout; | ||
128 | xTimeout.tv_usec = 0; | ||
129 | if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { | ||
130 | xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while."); | ||
131 | } | ||
132 | usleep( nTimeout ); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | return false; | ||
137 | } | ||
138 | |||
139 | bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout ) | ||
140 | { | ||
141 | struct timeval xTimeout; | ||
142 | |||
143 | xTimeout.tv_sec = nTimeout / 1000000; | ||
144 | xTimeout.tv_usec = nTimeout % 1000000; | ||
145 | |||
146 | /* Block until input arrives on one or more active sockets. */ | ||
147 | fdRead = fdActive; | ||
148 | fdWrite = fdActive; | ||
149 | fdException = fdActive; | ||
150 | |||
151 | // We removed the write checking because it just checks to see if you *can* | ||
152 | // write...that's stupid, they're all open, so it always exits immediately | ||
153 | // if there are ANY connections there... | ||
154 | if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, (fd_set *)0/*&fdWrite*/, &fdException, &xTimeout ) ) < 0 ) | ||
155 | { | ||
156 | xLog.LineLog( MultiLog::LError, "Error attempting to scan open connections."); | ||
157 | perror("ConnectionManager"); | ||
158 | return false; | ||
159 | } | ||
160 | // Now we use select to sleep as well as to scan for connections, now we | ||
161 | // just need to fix the fact that if there are no connections, the seccond | ||
162 | // select call doesn't return until there is a connection... | ||
163 | if( bForceTimeout ) | ||
164 | { | ||
165 | if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { | ||
166 | xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while."); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | /* Service all the sockets with input pending. */ | ||
171 | for( int i = 0; i < FD_SETSIZE; ++i ) | ||
172 | { | ||
173 | if( FD_ISSET( i, &fdRead ) ) | ||
174 | { | ||
175 | if( sMasterSocket.find( i ) != sMasterSocket.end() ) | ||
176 | { | ||
177 | addConnection( i ); | ||
178 | } | ||
179 | else | ||
180 | { | ||
181 | Connection *pCon = findActiveConnection( i ); | ||
182 | if( pCon == NULL ) | ||
183 | { | ||
184 | xLog.LineLog( MultiLog::LError, "A connection object was lost, or never created!"); | ||
185 | return false; | ||
186 | } | ||
187 | |||
188 | /* Data arriving on an already-connected socket. */ | ||
189 | if( pCon->readInput() == 0 ) | ||
190 | { | ||
191 | xLog.LineLog( MultiLog::LStatus, "Closing connection due to disconnect."); | ||
192 | close( i ); | ||
193 | FD_CLR( i, &fdActive ); | ||
194 | pMonitor->onClosedConnection( pCon ); | ||
195 | pCon->close(); | ||
196 | } | ||
197 | else | ||
198 | { | ||
199 | // We actually read something...but the connection handles | ||
200 | // protocol notification, so we don't need to do anything | ||
201 | // here... | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | std::list<Connection *>::iterator i; | ||
207 | for( i = lActive.begin(); i != lActive.end(); i++ ) | ||
208 | { | ||
209 | if( (*i)->isActive() == false ) | ||
210 | { | ||
211 | std::list<Connection *>::iterator l = i; | ||
212 | i--; | ||
213 | lInactive.insert( lInactive.end(), *l ); | ||
214 | lActive.erase( l ); | ||
215 | continue; | ||
216 | } | ||
217 | (*i)->getProtocol()->poll(); | ||
218 | if( (*i)->hasOutput() ) | ||
219 | { | ||
220 | (*i)->writeOutput(); | ||
221 | } | ||
222 | if( (*i)->needDisconnect() && !(*i)->hasOutput() ) | ||
223 | { | ||
224 | int prt = (*i)->getSocket(); | ||
225 | close( prt ); | ||
226 | FD_CLR( prt, &fdActive ); | ||
227 | pMonitor->onClosedConnection( *i ); | ||
228 | (*i)->close(); | ||
229 | lInactive.insert( lInactive.end(), *i ); | ||
230 | std::list<Connection *>::iterator l = i; | ||
231 | i--; | ||
232 | lActive.erase( l ); | ||
233 | xLog.LineLog( MultiLog::LStatus, "Closing connection due to server request."); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | return true; | ||
238 | } | ||
239 | |||
240 | bool ConnectionManager::shutdownServer() | ||
241 | { | ||
242 | while( !lActive.empty() ) | ||
243 | { | ||
244 | Connection *i = *(lActive.begin()); | ||
245 | if( i->isActive() ) | ||
246 | { | ||
247 | pMonitor->onClosedConnection( i ); | ||
248 | i->close(); | ||
249 | lInactive.insert( lInactive.end(), i ); | ||
250 | lActive.erase( lActive.begin() ); | ||
251 | } | ||
252 | } | ||
253 | /* | ||
254 | for( int i = 0; i < nPoolSize; i++ ) | ||
255 | { | ||
256 | |||
257 | int prt = axConPool[i].getSocket(); | ||
258 | close( prt ); | ||
259 | // FD_CLR( prt, &fdActive ); | ||
260 | pMonitor->onClosedConnection( &axConPool[i] ); | ||
261 | axConPool[i].close(); | ||
262 | } | ||
263 | */ | ||
264 | std::map<int,int>::iterator i; | ||
265 | for( i = sMasterSocket.begin(); i != sMasterSocket.end(); i++ ) | ||
266 | { | ||
267 | int nSocket = (*i).first; | ||
268 | shutdown( nSocket, SHUT_RDWR ); | ||
269 | close( nSocket ); | ||
270 | } | ||
271 | |||
272 | return true; | ||
273 | } | ||
274 | |||
275 | bool ConnectionManager::broadcastMessage( const char *lpData, int nExcludeSocket ) | ||
276 | { | ||
277 | std::list<Connection *>::const_iterator i; | ||
278 | for( i = lActive.begin(); i != lActive.end(); i++ ) | ||
279 | { | ||
280 | if( (*i)->isActive() && | ||
281 | (*i)->getSocket() != nExcludeSocket ) | ||
282 | { | ||
283 | (*i)->appendOutput( lpData ); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | return true; | ||
288 | } | ||
289 | |||
290 | bool ConnectionManager::addConnection( int nSocket ) | ||
291 | { | ||
292 | struct sockaddr_in clientname; | ||
293 | size_t size; | ||
294 | int newSocket; | ||
295 | |||
296 | size = sizeof( clientname ); | ||
297 | #ifdef __CYGWIN__ | ||
298 | newSocket = accept( nSocket, (struct sockaddr *) &clientname, (int *)&size ); | ||
299 | #else | ||
300 | newSocket = accept( nSocket, (struct sockaddr *) &clientname, &size ); | ||
301 | #endif | ||
302 | if( newSocket < 0 ) | ||
303 | { | ||
304 | xLog.LineLog( MultiLog::LError, "Error accepting a new connection!" ); | ||
305 | return false; | ||
306 | } | ||
307 | // char *tmpa = inet_ntoa(clientname.sin_addr); | ||
308 | char tmpa[20]; | ||
309 | inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); | ||
310 | xLog.LineLog( MultiLog::LStatus, "New connection from host %s, port %hd.", tmpa, ntohs (clientname.sin_port) ); | ||
311 | /* | ||
312 | int nCnt = 0; | ||
313 | for( int j = 0; j < nPoolSize; j++ ) | ||
314 | { | ||
315 | if( axConPool[j].isActive() ) | ||
316 | { | ||
317 | nCnt++; | ||
318 | } | ||
319 | } | ||
320 | xLog.LineLog( MultiLog::LStatus, "Connections %d/%d.", nCnt, nPoolSize ); | ||
321 | */ | ||
322 | // free( tmpa ); | ||
323 | FD_SET( newSocket, &fdActive ); | ||
324 | |||
325 | //void nonblock(socket_t s) | ||
326 | { | ||
327 | int flags; | ||
328 | |||
329 | flags = fcntl(newSocket, F_GETFL, 0); | ||
330 | flags |= O_NONBLOCK; | ||
331 | if (fcntl(newSocket, F_SETFL, flags) < 0) | ||
332 | { | ||
333 | return false; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | Connection *pCon = getInactiveConnection(); | ||
338 | pCon->open( newSocket ); | ||
339 | |||
340 | pMonitor->onNewConnection( pCon, (*sMasterSocket.find(nSocket)).second ); | ||
341 | if( pCon->getProtocol() ) | ||
342 | pCon->getProtocol()->onNewConnection(); | ||
343 | |||
344 | lActive.insert( lActive.end(), pCon ); | ||
345 | |||
346 | return true; | ||
347 | } | ||
348 | |||
349 | void ConnectionManager::connect( | ||
350 | const char *lpAddress, | ||
351 | int nPort, | ||
352 | int nProtocolPort, | ||
353 | Protocol *pNewProto | ||
354 | ) | ||
355 | { | ||
356 | Connection *pCon = getInactiveConnection(); | ||
357 | pCon->open( lpAddress, nPort ); | ||
358 | int nSocket = pCon->getSocket(); | ||
359 | FD_SET( nSocket, &fdActive ); | ||
360 | |||
361 | pCon->setProtocol( pNewProto ); | ||
362 | pMonitor->onNewClientConnection( pCon, nProtocolPort ); | ||
363 | if( pCon->getProtocol() ) | ||
364 | pCon->getProtocol()->onNewClientConnection(); | ||
365 | |||
366 | lActive.insert( lActive.end(), pCon ); | ||
367 | } | ||
368 | |||
369 | Connection *ConnectionManager::getInactiveConnection() | ||
370 | { | ||
371 | if( lInactive.empty() ) | ||
372 | { | ||
373 | return new Connection(); | ||
374 | } | ||
375 | Connection *pCon = *(lInactive.begin()); | ||
376 | lInactive.erase( lInactive.begin() ); | ||
377 | return pCon; | ||
378 | } | ||
379 | |||
380 | Connection *ConnectionManager::findActiveConnection( int nSocket ) | ||
381 | { | ||
382 | std::list<Connection *>::const_iterator i; | ||
383 | for( i = lActive.begin(); i != lActive.end(); i++ ) | ||
384 | { | ||
385 | if( (*i)->getSocket() == nSocket ) | ||
386 | { | ||
387 | return *i; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | return NULL; | ||
392 | } | ||
393 | |||
394 | void ConnectionManager::setConnectionMonitor( ConnectionMonitor *pNewMonitor ) | ||
395 | { | ||
396 | pMonitor = pNewMonitor; | ||
397 | } | ||
diff --git a/src/old/connectionmanager.h b/src/old/connectionmanager.h new file mode 100644 index 0000000..cff036b --- /dev/null +++ b/src/old/connectionmanager.h | |||
@@ -0,0 +1,169 @@ | |||
1 | /** | ||
2 | *@file | ||
3 | * Contains the ConnectionManager. | ||
4 | *@author Mike Buland | ||
5 | */ | ||
6 | |||
7 | #ifndef CONNECTIONMANAGER_H | ||
8 | #define CONNECTIONMANAGER_H | ||
9 | |||
10 | #include "multilog.h" | ||
11 | #include "connection.h" | ||
12 | #include "connectionmonitor.h" | ||
13 | #include <sys/types.h> | ||
14 | #include <list> | ||
15 | #include <map> | ||
16 | |||
17 | /** Manges incoming network connections as a server. Creates and works with | ||
18 | * Connection objects. All operations are performed on TCP/IP v4 right now, | ||
19 | * and on a single port, although any number of connections can be handled. | ||
20 | *@author Mike Buland | ||
21 | */ | ||
22 | class ConnectionManager | ||
23 | { | ||
24 | public: | ||
25 | /** | ||
26 | * Sets up the basics, like storage for the pool, and so on. This does not | ||
27 | * actually start a server, bind to a port, or create a connection pool. | ||
28 | * That's all handled by startServer(). | ||
29 | */ | ||
30 | ConnectionManager( int nInitPool=40 ); | ||
31 | |||
32 | /** | ||
33 | * Cleans up everything, and even clears out all still-connected Connection | ||
34 | * objects. | ||
35 | */ | ||
36 | virtual ~ConnectionManager(); | ||
37 | |||
38 | /** | ||
39 | * Starts a server socket and binds to it, listening for new connections. | ||
40 | * Unlike the version of this that takes two parameters, this listens on | ||
41 | * all local addresses, or the virtual 0.0.0.0 address if available, which | ||
42 | * is mapped to all active local addresses. | ||
43 | *@param nPort The port to listen on. | ||
44 | *@returns True if the socket was bound to the port and serving was | ||
45 | * started. False if there was a problem connecting to the port. | ||
46 | */ | ||
47 | bool startServer( int nPort ); | ||
48 | |||
49 | /** | ||
50 | * Starts a server socket and binds to it, listening only on the address | ||
51 | * specified. If you want to listen to all local addresses you can enter | ||
52 | * "0.0.0.0" for the address, but the version of this with one parameter | ||
53 | * is more universal. | ||
54 | *@param sAddr The local ip address to bind to | ||
55 | *@param nPort The port to listen on. | ||
56 | *@returns True if the socket was bound to the port and serving was | ||
57 | * started. False if there was a problem connecting to the port. | ||
58 | */ | ||
59 | bool startServer( const char *sAddr, int nPort ); | ||
60 | |||
61 | /** | ||
62 | * I recomend probably not using this function on your own too much, it | ||
63 | * does the real work of setting up a socket, but requires a properly | ||
64 | * prepared sackaddr_in structure. This isn't too hard, but it's easier | ||
65 | * to use the other startServer functions. They call this function after | ||
66 | * some prepwork. | ||
67 | *@param name A properly formed sockaddr_in structure that will not be | ||
68 | * modified, but describes how to listen and to what to listen. | ||
69 | *@returns True on success. | ||
70 | */ | ||
71 | bool startServer( struct sockaddr_in &name ); | ||
72 | |||
73 | /** | ||
74 | * This is identicle to the simpler startServer function except that it | ||
75 | * will automatically try to connect multiple times in case the first | ||
76 | * attempt or two doesn't work for some reason. Initially this was | ||
77 | * written to compensate for server sockets staying locked after they were | ||
78 | * closed for a while. | ||
79 | *@param nPort The port to listen on. | ||
80 | *@param nInitPool The size of the initial connection pool. This will | ||
81 | * grow automatically if necesarry. | ||
82 | *@param nNumTries The maximum number of times to try to connect. | ||
83 | *@param nTimeout The amount of time to wait in-between connection | ||
84 | * attempts. | ||
85 | *@returns True if the socket was bound to the port and serving was | ||
86 | * started. False if there was a problem connecting to the port. | ||
87 | */ | ||
88 | bool startServer( int nPort, int nNumTries, int nTimeout ); | ||
89 | |||
90 | /** | ||
91 | * Scans all open connections, halting the calling processes until data | ||
92 | * is received or nTimeout ms have gone by. While waiting for the timeout | ||
93 | * to complete the process is placed into an idle mode. | ||
94 | *@param nTimeout The number of millisecconds to wait if there is nothing | ||
95 | * to actually do. | ||
96 | *@param bForceTimeout If set to true, this will force the scanner to wait | ||
97 | * for the timout to complete before returning, even if there was pending | ||
98 | * data. | ||
99 | */ | ||
100 | bool scanConnections( int nTimeout, bool bForceTimeout ); | ||
101 | |||
102 | /** Shutdown the server and all assosiated sockets. | ||
103 | *@returns True if every socket was closed without problem. | ||
104 | */ | ||
105 | bool shutdownServer(); | ||
106 | |||
107 | /** Sends a message directly to every connected port. | ||
108 | *@param lpData A null-terminated string of data to send. | ||
109 | *@param nExcludeSocket An optional socket to exclude from the broadcast. | ||
110 | *@returns True if every socket that should have gotten the message did. | ||
111 | */ | ||
112 | bool broadcastMessage( const char *lpData, int nExcludeSocket=-1 ); | ||
113 | |||
114 | /** Sets a monitor for the manager. The monitor is sent notifications | ||
115 | * whenever a socket is connected, disconnected, or whenever an error | ||
116 | * occurs. | ||
117 | *@param pNewMonitor A pointer to a preconstructed ConnectionMonitor | ||
118 | */ | ||
119 | void setConnectionMonitor( ConnectionMonitor *pNewMonitor ); | ||
120 | |||
121 | void connect( const char *lpAddress, int nPort, int nProtocolPort, Protocol *pNewProto ); | ||
122 | |||
123 | private: | ||
124 | /** | ||
125 | * Take care of the work of actually accepting a connection. This will | ||
126 | * accept the connection, set the initial modes, and add it to the master | ||
127 | * list of active connections, as well as fire off any messages that need | ||
128 | * to be handled by anything else. | ||
129 | *@param nSocket The handle of the listening socket that had an incoming | ||
130 | * connection. | ||
131 | *@returns True if everything worked, False otherwise. | ||
132 | */ | ||
133 | bool addConnection( int nSocket ); | ||
134 | |||
135 | /** | ||
136 | * Seraches the internal lists of connections for one with a specific | ||
137 | * socket. | ||
138 | *@param nSocket The socket the connection is using for communication. | ||
139 | * This is the unique socket and not the one that the connection was | ||
140 | * initially to. | ||
141 | *@returns NULL if no connection was found, otherwise a pointer to a live | ||
142 | * Connection object. | ||
143 | */ | ||
144 | Connection *findActiveConnection( int nSocket ); | ||
145 | |||
146 | /** | ||
147 | * Searches the connection pool for an object that isn't in use yet, and | ||
148 | * returns it, ready to be filled in and used. | ||
149 | *@returns An unused connection object ready for use. | ||
150 | *@todo Check this code over to insure that the pool grows appropriately | ||
151 | * when enough extra connections are detected. | ||
152 | */ | ||
153 | Connection *getInactiveConnection(); | ||
154 | |||
155 | std::map<int,int> sMasterSocket; | ||
156 | //int nMasterSocket; /**< The listening or server socket. */ | ||
157 | fd_set fdActive; /**< The active socket set. */ | ||
158 | fd_set fdRead; /**< The sockets ready for a read. */ | ||
159 | fd_set fdWrite; /**< The sockets ready for a write. */ | ||
160 | fd_set fdException; /**< The sockets that have gotten errors. */ | ||
161 | std::list<Connection *> lInactive; /**< The pool of inactive Connections */ | ||
162 | std::list<Connection *> lActive; /**< The pool of active Connections */ | ||
163 | MultiLog &xLog; /**< A handle to the active multilog. */ | ||
164 | |||
165 | /** The ConnectionMonitor to notify of new connections. */ | ||
166 | ConnectionMonitor *pMonitor; | ||
167 | }; | ||
168 | |||
169 | #endif | ||
diff --git a/src/old/connectionmonitor.cpp b/src/old/connectionmonitor.cpp new file mode 100644 index 0000000..4f90ee6 --- /dev/null +++ b/src/old/connectionmonitor.cpp | |||
@@ -0,0 +1,10 @@ | |||
1 | #include "connectionmonitor.h" | ||
2 | |||
3 | ConnectionMonitor::ConnectionMonitor() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | ConnectionMonitor::~ConnectionMonitor() | ||
8 | { | ||
9 | } | ||
10 | |||
diff --git a/src/old/connectionmonitor.h b/src/old/connectionmonitor.h new file mode 100644 index 0000000..9910556 --- /dev/null +++ b/src/old/connectionmonitor.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /**@file | ||
2 | * Describes the ConnectionMonitor class. | ||
3 | */ | ||
4 | #ifndef CONNECTIONMONITOR_H | ||
5 | #define CONNECTIONMONITOR_H | ||
6 | |||
7 | #include "connection.h" | ||
8 | |||
9 | /** Connection Monitor defines the base class of the objects that will be | ||
10 | * notified whenever a connection is created or destroyed. | ||
11 | *@author Mike Buland | ||
12 | */ | ||
13 | class ConnectionMonitor | ||
14 | { | ||
15 | public: | ||
16 | /** | ||
17 | * This is only here for completeness. It does nothing. | ||
18 | */ | ||
19 | ConnectionMonitor(); | ||
20 | |||
21 | /** | ||
22 | * This is only here for completeness. It does nothing. | ||
23 | */ | ||
24 | virtual ~ConnectionMonitor(); | ||
25 | |||
26 | /** Receives the notification that new connection was received. | ||
27 | *@param pCon The connection that was created. | ||
28 | *@param nSocket The socket that the client connected to, used to determine | ||
29 | * which protocol to apply. | ||
30 | *@returns Should return a true value if everything is OK, a false to | ||
31 | * force a shutdown. | ||
32 | */ | ||
33 | virtual bool onNewConnection( Connection *pCon, int nPort ) = 0; | ||
34 | virtual bool onNewClientConnection( Connection *pCon, int nPort ) | ||
35 | { | ||
36 | return onNewConnection( pCon, nPort ); | ||
37 | }; | ||
38 | |||
39 | /** Receives the notification that a connection was closed. | ||
40 | *@param pCon The connection that was closed. | ||
41 | *@returns Should return a true value if everything is OK, a false to | ||
42 | * force a shutdown. | ||
43 | */ | ||
44 | virtual bool onClosedConnection( Connection *pCon ) = 0; | ||
45 | }; | ||
46 | |||
47 | #endif | ||
diff --git a/src/old/exceptionbase.cpp b/src/old/exceptionbase.cpp new file mode 100644 index 0000000..f3d22da --- /dev/null +++ b/src/old/exceptionbase.cpp | |||
@@ -0,0 +1,70 @@ | |||
1 | #include "exceptionbase.h" | ||
2 | #include <stdarg.h> | ||
3 | |||
4 | ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : | ||
5 | nErrorCode( 0 ), | ||
6 | sWhat( NULL ) | ||
7 | { | ||
8 | va_list ap; | ||
9 | |||
10 | va_start(ap, lpFormat); | ||
11 | setWhat( lpFormat, ap ); | ||
12 | va_end(ap); | ||
13 | } | ||
14 | |||
15 | ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : | ||
16 | nErrorCode( nCode ), | ||
17 | sWhat( NULL ) | ||
18 | { | ||
19 | va_list ap; | ||
20 | |||
21 | va_start(ap, lpFormat); | ||
22 | setWhat( lpFormat, ap ); | ||
23 | va_end(ap); | ||
24 | } | ||
25 | |||
26 | ExceptionBase::ExceptionBase( int nCode ) throw() : | ||
27 | nErrorCode( nCode ), | ||
28 | sWhat( NULL ) | ||
29 | { | ||
30 | } | ||
31 | |||
32 | ExceptionBase::~ExceptionBase() throw() | ||
33 | { | ||
34 | if( sWhat ) | ||
35 | { | ||
36 | delete[] sWhat; | ||
37 | sWhat = NULL; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | void ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) | ||
42 | { | ||
43 | if( sWhat ) delete[] sWhat; | ||
44 | int nSize; | ||
45 | |||
46 | nSize = vsnprintf( NULL, 0, lpFormat, vargs ); | ||
47 | sWhat = new char[nSize+1]; | ||
48 | vsnprintf( sWhat, nSize+1, lpFormat, vargs ); | ||
49 | } | ||
50 | |||
51 | void ExceptionBase::setWhat( const char *lpText ) | ||
52 | { | ||
53 | if( sWhat ) delete[] sWhat; | ||
54 | int nSize; | ||
55 | |||
56 | nSize = strlen( lpText ); | ||
57 | sWhat = new char[nSize+1]; | ||
58 | strcpy( sWhat, lpText ); | ||
59 | } | ||
60 | |||
61 | const char *ExceptionBase::what() const throw() | ||
62 | { | ||
63 | return sWhat; | ||
64 | } | ||
65 | |||
66 | int ExceptionBase::getErrorCode() | ||
67 | { | ||
68 | return nErrorCode; | ||
69 | } | ||
70 | |||
diff --git a/src/old/exceptionbase.h b/src/old/exceptionbase.h new file mode 100644 index 0000000..6f1eca7 --- /dev/null +++ b/src/old/exceptionbase.h | |||
@@ -0,0 +1,105 @@ | |||
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 new file mode 100644 index 0000000..ce79a5e --- /dev/null +++ b/src/old/exceptions.cpp | |||
@@ -0,0 +1,8 @@ | |||
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 new file mode 100644 index 0000000..0ab2b15 --- /dev/null +++ b/src/old/exceptions.h | |||
@@ -0,0 +1,25 @@ | |||
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/flexbuf.cpp b/src/old/flexbuf.cpp new file mode 100644 index 0000000..6d55294 --- /dev/null +++ b/src/old/flexbuf.cpp | |||
@@ -0,0 +1,229 @@ | |||
1 | #include "flexbuf.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | FlexBuf::FlexBuf() | ||
5 | { | ||
6 | lpBuf = new char[1024]; | ||
7 | nLastChar = 0; | ||
8 | nFirstChar = 0; | ||
9 | nSize = 1024; | ||
10 | nFill = 0; | ||
11 | clearData(); | ||
12 | } | ||
13 | |||
14 | FlexBuf::~FlexBuf() | ||
15 | { | ||
16 | delete[] lpBuf; | ||
17 | } | ||
18 | |||
19 | bool FlexBuf::appendData( const char *lpData, int nDSize ) | ||
20 | { | ||
21 | int nStrLen; | ||
22 | if( nDSize < 0 ) | ||
23 | { | ||
24 | nStrLen = strlen( lpData ); | ||
25 | } | ||
26 | else | ||
27 | { | ||
28 | nStrLen = nDSize; | ||
29 | } | ||
30 | |||
31 | if( nLastChar + nStrLen + 1 > nSize ) | ||
32 | { | ||
33 | if( nFill + nStrLen + 1 < nSize ) | ||
34 | { | ||
35 | memcpy( lpBuf, lpBuf+nFirstChar, nFill ); | ||
36 | nLastChar -= nFirstChar; | ||
37 | nFirstChar = 0; | ||
38 | } | ||
39 | else | ||
40 | { | ||
41 | nSize += nStrLen+1; | ||
42 | char *lpNewBuf = new char[nSize]; | ||
43 | memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); | ||
44 | delete[] lpBuf; | ||
45 | lpBuf = lpNewBuf; | ||
46 | nLastChar -= nFirstChar; | ||
47 | nFirstChar = 0; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | memcpy( &lpBuf[nLastChar], lpData, nStrLen ); | ||
52 | nLastChar += nStrLen; | ||
53 | nFill += nStrLen; | ||
54 | lpBuf[nLastChar] = '\0'; | ||
55 | |||
56 | return true; | ||
57 | } | ||
58 | |||
59 | bool FlexBuf::appendData( const char lData ) | ||
60 | { | ||
61 | if( nLastChar + 2 > nSize ) | ||
62 | { | ||
63 | if( nFill+2 < nSize ) | ||
64 | { | ||
65 | memcpy( lpBuf, lpBuf+nFirstChar, nFill ); | ||
66 | nLastChar -= nFirstChar; | ||
67 | nFirstChar = 0; | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | nSize += 1024; | ||
72 | char *lpNewBuf = new char[nSize]; | ||
73 | memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); | ||
74 | delete[] lpBuf; | ||
75 | lpBuf = lpNewBuf; | ||
76 | nLastChar -= nFirstChar; | ||
77 | nFirstChar = 0; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | lpBuf[nLastChar] = lData; | ||
82 | nLastChar++; | ||
83 | nFill++; | ||
84 | lpBuf[nLastChar] = '\0'; | ||
85 | |||
86 | return true; | ||
87 | } | ||
88 | |||
89 | bool FlexBuf::appendData( const short lData ) | ||
90 | { | ||
91 | return appendData( (const char *)&lData, sizeof(short) ); | ||
92 | } | ||
93 | |||
94 | bool FlexBuf::appendData( const int lData ) | ||
95 | { | ||
96 | return appendData( (const char *)&lData, sizeof(int) ); | ||
97 | } | ||
98 | |||
99 | bool FlexBuf::appendData( const long lData ) | ||
100 | { | ||
101 | return appendData( (const char *)&lData, sizeof(long) ); | ||
102 | } | ||
103 | |||
104 | bool FlexBuf::appendData( const float lData ) | ||
105 | { | ||
106 | return appendData( (const char *)&lData, sizeof(float) ); | ||
107 | } | ||
108 | |||
109 | bool FlexBuf::appendData( const double lData ) | ||
110 | { | ||
111 | return appendData( (const char *)&lData, sizeof(double) ); | ||
112 | } | ||
113 | |||
114 | bool FlexBuf::appendData( const unsigned char lData ) | ||
115 | { | ||
116 | return appendData( (const char)lData ); | ||
117 | } | ||
118 | |||
119 | bool FlexBuf::appendData( const unsigned short lData ) | ||
120 | { | ||
121 | return appendData( (const char *)&lData, sizeof(short) ); | ||
122 | } | ||
123 | |||
124 | bool FlexBuf::appendData( const unsigned long lData ) | ||
125 | { | ||
126 | return appendData( (const char *)&lData, sizeof(long) ); | ||
127 | } | ||
128 | |||
129 | bool FlexBuf::appendData( const unsigned int lData ) | ||
130 | { | ||
131 | return appendData( (const char *)&lData, sizeof(int) ); | ||
132 | } | ||
133 | |||
134 | bool FlexBuf::clearData() | ||
135 | { | ||
136 | nFirstChar = nLastChar = nFill = 0; | ||
137 | lpBuf[nLastChar] = '\0'; | ||
138 | |||
139 | return true; | ||
140 | } | ||
141 | |||
142 | const char *FlexBuf::getData() | ||
143 | { | ||
144 | return (lpBuf+nFirstChar); | ||
145 | } | ||
146 | |||
147 | int FlexBuf::getLength() | ||
148 | { | ||
149 | return nFill; | ||
150 | } | ||
151 | |||
152 | int FlexBuf::getCapacity() | ||
153 | { | ||
154 | return nSize; | ||
155 | } | ||
156 | |||
157 | bool FlexBuf::usedData( int nAmount ) | ||
158 | { | ||
159 | // Remove from the end if negative | ||
160 | if( nAmount < 0 ) | ||
161 | { | ||
162 | if( nFill+nAmount < 0 ) | ||
163 | { | ||
164 | nFill = nFirstChar = nLastChar = 0; | ||
165 | return true; | ||
166 | } | ||
167 | nLastChar += nAmount; | ||
168 | nFill += nAmount; | ||
169 | return true; | ||
170 | } | ||
171 | if( nAmount > nFill ) | ||
172 | { | ||
173 | nAmount = nSize; | ||
174 | // return false; | ||
175 | } | ||
176 | |||
177 | //nLastChar -= nAmount; | ||
178 | nFirstChar += nAmount; | ||
179 | nFill -= nAmount; | ||
180 | |||
181 | if( nFill == 0 ) | ||
182 | { | ||
183 | nFirstChar = nLastChar = 0; | ||
184 | } | ||
185 | |||
186 | //if( nLastChar > 0 ) | ||
187 | //{ | ||
188 | //memmove( lpBuf, &lpBuf[nAmount], nLastChar ); | ||
189 | //} | ||
190 | |||
191 | return true; | ||
192 | } | ||
193 | |||
194 | int FlexBuf::findChar( char cTarget ) | ||
195 | { | ||
196 | for( int j = nFirstChar; j < nLastChar; j++ ) | ||
197 | { | ||
198 | if( lpBuf[j] == cTarget ) | ||
199 | { | ||
200 | return j; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | return -1; | ||
205 | } | ||
206 | |||
207 | void FlexBuf::ensureCapacity( int nAmount ) | ||
208 | { | ||
209 | if( nLastChar + nAmount + 1 > nSize ) | ||
210 | { | ||
211 | if( nFill + nAmount + 1 < nSize ) | ||
212 | { | ||
213 | memcpy( lpBuf, lpBuf+nFirstChar, nFill ); | ||
214 | nLastChar -= nFirstChar; | ||
215 | nFirstChar = 0; | ||
216 | } | ||
217 | else | ||
218 | { | ||
219 | nSize += nAmount+1; | ||
220 | char *lpNewBuf = new char[nSize]; | ||
221 | memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); | ||
222 | delete[] lpBuf; | ||
223 | lpBuf = lpNewBuf; | ||
224 | nLastChar -= nFirstChar; | ||
225 | nFirstChar = 0; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
diff --git a/src/old/flexbuf.h b/src/old/flexbuf.h new file mode 100644 index 0000000..7d7f11a --- /dev/null +++ b/src/old/flexbuf.h | |||
@@ -0,0 +1,162 @@ | |||
1 | /**\flexbuf.h | ||
2 | * Describes the FlexBuf class. | ||
3 | *@author Mike Buland | ||
4 | */ | ||
5 | |||
6 | #ifndef FLEXBUF_H | ||
7 | #define FLEXBUF_H | ||
8 | |||
9 | /** Stores any amount of data, but starts small, growing as necesarry. | ||
10 | * It is optimized to work with stream type situations, with data being | ||
11 | * added to the end while it is being taken from the begning. | ||
12 | *@todo Set this class up to auto-shrink back to a specified sized buffer each | ||
13 | * time it has shrunk below that for enough operations. | ||
14 | *@author Mike Buland | ||
15 | */ | ||
16 | class FlexBuf | ||
17 | { | ||
18 | public: | ||
19 | /** | ||
20 | * Construct a blank FlexBuf containing about 1k of buffer space. | ||
21 | */ | ||
22 | FlexBuf(); | ||
23 | |||
24 | /** | ||
25 | * Clean up the FlexBuf, delete all buffers. | ||
26 | */ | ||
27 | virtual ~FlexBuf(); | ||
28 | |||
29 | /** Appends a whole string of data to the buffer. The string | ||
30 | * must be null terminated. | ||
31 | *@param lpData The data to append to the buffer. | ||
32 | *@param nDSize The size of the data described by lpData. If this | ||
33 | * value is -1 lpData is treated as a null-terminated string. | ||
34 | *@returns True if no problems occured, false otherwise. | ||
35 | */ | ||
36 | bool appendData( const char *lpData, int nDSize=-1 ); | ||
37 | |||
38 | /** Appends a single character to the end of the buffer. | ||
39 | *@param lData The character to append to the buffer. | ||
40 | *@returns True if no problems occured, false otherwise. | ||
41 | */ | ||
42 | bool appendData( const char lData ); | ||
43 | |||
44 | /** | ||
45 | * Append the short to the buffer. | ||
46 | *@param lData The short to add to the buffer queue. | ||
47 | *@returns True if everything is ok, false otherwise. | ||
48 | */ | ||
49 | bool appendData( const short lData ); | ||
50 | |||
51 | /** | ||
52 | * Append the int to the buffer. | ||
53 | *@param lData The int to add to the buffer queue. | ||
54 | *@returns True if everything is ok, false otherwise. | ||
55 | */ | ||
56 | bool appendData( const int lData ); | ||
57 | |||
58 | /** | ||
59 | * Append the long to the buffer. | ||
60 | *@param lData The long to add to the buffer queue. | ||
61 | *@returns True if everything is ok, false otherwise. | ||
62 | */ | ||
63 | bool appendData( const long lData ); | ||
64 | |||
65 | /** | ||
66 | * Append the float to the buffer. | ||
67 | *@param lData The float to add to the buffer queue. | ||
68 | *@returns True if everything is ok, false otherwise. | ||
69 | */ | ||
70 | bool appendData( const float lData ); | ||
71 | |||
72 | /** | ||
73 | * Append the double to the buffer. | ||
74 | *@param lData The double to add to the buffer queue. | ||
75 | *@returns True if everything is ok, false otherwise. | ||
76 | */ | ||
77 | bool appendData( const double lData ); | ||
78 | |||
79 | /** | ||
80 | * Append the unsigned char to the buffer. | ||
81 | *@param lData The unsigned char to add to the buffer queue. | ||
82 | *@returns True if everything is ok, false otherwise. | ||
83 | */ | ||
84 | bool appendData( const unsigned char lData ); | ||
85 | |||
86 | /** | ||
87 | * Append the unsigned short to the buffer. | ||
88 | *@param lData The unsigned short to add to the buffer queue. | ||
89 | *@returns True if everything is ok, false otherwise. | ||
90 | */ | ||
91 | bool appendData( const unsigned short lData ); | ||
92 | |||
93 | /** | ||
94 | * Append the unsigned int to the buffer. | ||
95 | *@param lData The unsigned int to add to the buffer queue. | ||
96 | *@returns True if everything is ok, false otherwise. | ||
97 | */ | ||
98 | bool appendData( const unsigned int lData ); | ||
99 | |||
100 | /** | ||
101 | * Append the unsigned long to the buffer. | ||
102 | *@param lData The unsigned long to add to the buffer queue. | ||
103 | *@returns True if everything is ok, false otherwise. | ||
104 | */ | ||
105 | bool appendData( const unsigned long lData ); | ||
106 | |||
107 | /** Removes all pending data from the buffer. | ||
108 | *@returns True if no problems occured, false otherwise. | ||
109 | */ | ||
110 | bool clearData(); | ||
111 | |||
112 | /** Gets a pointer to the internal buffer, at the begining of the current | ||
113 | * data stream. | ||
114 | *@returns A pointer to the internal data buffer. | ||
115 | */ | ||
116 | const char *getData(); | ||
117 | |||
118 | /** Gets the length of the current buffer (how much data is really in the | ||
119 | * buffer, not it's current capacity, for that check getCapacity) | ||
120 | *@returns The length of the current buffer. | ||
121 | */ | ||
122 | int getLength(); | ||
123 | |||
124 | /** Gets the current capacity of the FlexBuf. If the size nears this value | ||
125 | * then the entire buffer is resized to accomidate more data. | ||
126 | *@returns The current capacity of the FlexBuf. | ||
127 | */ | ||
128 | int getCapacity(); | ||
129 | |||
130 | /** | ||
131 | * Removes nAmount bytes from the begning of the buffer. Actually, if | ||
132 | * nAmount happens to be negative it will remove tha absolute value of | ||
133 | * nValue bytes from the end of the buffer, like the old delData command. | ||
134 | *@param nAmount The number of bytes used. | ||
135 | *@returns True if everything was successful, false if there was an error. | ||
136 | */ | ||
137 | bool usedData( int nAmount ); | ||
138 | |||
139 | /** Finds the first instance of the given character in the buffer and | ||
140 | * returns an index to it. | ||
141 | *@param cTarget The character you're looking for. | ||
142 | *@returns The index of the first instance of the given character, or | ||
143 | * -1 if it just wasn't found. | ||
144 | */ | ||
145 | int findChar( char cTarget ); | ||
146 | |||
147 | void ensureCapacity( int nAmount ); | ||
148 | |||
149 | private: | ||
150 | /** The raw storage location of the FlexBuf. */ | ||
151 | char *lpBuf; | ||
152 | /** The real size of the FlexBuf. */ | ||
153 | int nSize; | ||
154 | /** Where the last char is. */ | ||
155 | int nLastChar; | ||
156 | /** Where the first char is. */ | ||
157 | int nFirstChar; | ||
158 | /** The amount of real data in the FlexBuf. This is effectively nLastChar-nFirstChar. */ | ||
159 | int nFill; | ||
160 | }; | ||
161 | |||
162 | #endif | ||
diff --git a/src/old/formula.cpp b/src/old/formula.cpp new file mode 100644 index 0000000..cf63cf3 --- /dev/null +++ b/src/old/formula.cpp | |||
@@ -0,0 +1,262 @@ | |||
1 | #include "formula.h" | ||
2 | |||
3 | subExceptionDef( ParseException ); | ||
4 | |||
5 | Formula::Formula() | ||
6 | { | ||
7 | hVars["pi"] = M_PI; | ||
8 | hVars["e"] = M_E; | ||
9 | |||
10 | hFunc["sin"] = FuncSin(); | ||
11 | } | ||
12 | |||
13 | Formula::~Formula() | ||
14 | { | ||
15 | } | ||
16 | |||
17 | double Formula::run( char *sFormula ) | ||
18 | { | ||
19 | for(;;) | ||
20 | { | ||
21 | uint8_t tNum = nextToken( &sFormula ); | ||
22 | if( tNum == symEOS ) | ||
23 | break; | ||
24 | else if( tNum == symSubtract ) | ||
25 | { | ||
26 | tNum = nextToken( &sFormula ); | ||
27 | if( tNum != symNumber ) | ||
28 | throw ParseException("Unary minus must be followed by a number, " | ||
29 | "variable, function, or parenthesis."); | ||
30 | sValue.top() = -sValue.top(); | ||
31 | } | ||
32 | else if( tNum == symOpenParen ) | ||
33 | { | ||
34 | sOper.push( tNum ); | ||
35 | continue; | ||
36 | } | ||
37 | |||
38 | oppart: uint8_t tOpr = nextToken( &sFormula ); | ||
39 | if( tOpr == symEOS ) | ||
40 | { | ||
41 | //printf("EOS "); | ||
42 | reduce(); | ||
43 | return sValue.top(); | ||
44 | break; | ||
45 | } | ||
46 | if( !sOper.empty() && getPrec( sOper.top() ) > getPrec( tOpr ) ) | ||
47 | { | ||
48 | reduce(); | ||
49 | } | ||
50 | if( tOpr != symCloseParen ) | ||
51 | { | ||
52 | sOper.push( tOpr ); | ||
53 | } | ||
54 | else | ||
55 | { | ||
56 | reduce( true ); | ||
57 | goto oppart; | ||
58 | } | ||
59 | } | ||
60 | return sValue.top(); | ||
61 | } | ||
62 | |||
63 | void Formula::reduce( bool bCloseParen ) | ||
64 | { | ||
65 | while( !sOper.empty() ) | ||
66 | { | ||
67 | uint8_t nOpr = sOper.top(); | ||
68 | if( nOpr == symOpenParen ) | ||
69 | { | ||
70 | //printf("Found ( stopping reduction.\n"); | ||
71 | if( bCloseParen == true ) | ||
72 | sOper.pop(); | ||
73 | return; | ||
74 | } | ||
75 | sOper.pop(); | ||
76 | |||
77 | double dTop = sValue.top(); | ||
78 | sValue.pop(); | ||
79 | |||
80 | switch( nOpr ) | ||
81 | { | ||
82 | case symAdd: | ||
83 | //printf("%f + %f = %f\n", sValue.top(), dTop, sValue.top()+dTop ); | ||
84 | sValue.top() += dTop; | ||
85 | break; | ||
86 | |||
87 | case symSubtract: | ||
88 | //printf("%f - %f = %f\n", sValue.top(), dTop, sValue.top()-dTop ); | ||
89 | sValue.top() -= dTop; | ||
90 | break; | ||
91 | |||
92 | case symMultiply: | ||
93 | //printf("%f * %f = %f\n", sValue.top(), dTop, sValue.top()*dTop ); | ||
94 | sValue.top() *= dTop; | ||
95 | break; | ||
96 | |||
97 | case symDivide: | ||
98 | //printf("%f / %f = %f\n", sValue.top(), dTop, sValue.top()/dTop ); | ||
99 | sValue.top() /= dTop; | ||
100 | break; | ||
101 | |||
102 | case symExponent: | ||
103 | //printf("%f ^ %f = %f\n", sValue.top(), dTop, pow(sValue.top(),dTop) ); | ||
104 | sValue.top() = pow( sValue.top(), dTop ); | ||
105 | break; | ||
106 | |||
107 | case symModulus: | ||
108 | //printf("%f %% %f = %f\n", sValue.top(), dTop, fmod(sValue.top(),dTop) ); | ||
109 | sValue.top() = fmod( sValue.top(), dTop ); | ||
110 | break; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if( bCloseParen == true ) | ||
115 | { | ||
116 | throw ParseException("Close-paren found without matching open-paren."); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | uint8_t Formula::getPrec( uint8_t nOper ) | ||
121 | { | ||
122 | switch( nOper ) | ||
123 | { | ||
124 | case symNumber: | ||
125 | case symVariable: | ||
126 | case symOpenParen: | ||
127 | case symCloseParen: | ||
128 | return 0; | ||
129 | |||
130 | case symAdd: | ||
131 | case symSubtract: | ||
132 | return 1; | ||
133 | |||
134 | case symMultiply: | ||
135 | case symDivide: | ||
136 | case symModulus: | ||
137 | return 2; | ||
138 | |||
139 | case symExponent: | ||
140 | return 3; | ||
141 | |||
142 | default: | ||
143 | return 0; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | uint8_t Formula::nextToken( char **sBuf ) | ||
148 | { | ||
149 | for(;;) | ||
150 | { | ||
151 | char cbuf = **sBuf; | ||
152 | ++(*sBuf); | ||
153 | switch( cbuf ) | ||
154 | { | ||
155 | case '+': | ||
156 | return symAdd; | ||
157 | |||
158 | case '-': | ||
159 | return symSubtract; | ||
160 | |||
161 | case '*': | ||
162 | return symMultiply; | ||
163 | |||
164 | case '/': | ||
165 | return symDivide; | ||
166 | |||
167 | case '^': | ||
168 | return symExponent; | ||
169 | |||
170 | case '%': | ||
171 | return symModulus; | ||
172 | |||
173 | case '(': | ||
174 | return symOpenParen; | ||
175 | |||
176 | case ')': | ||
177 | return symCloseParen; | ||
178 | |||
179 | case ' ': | ||
180 | case '\t': | ||
181 | case '\n': | ||
182 | case '\r': | ||
183 | break; | ||
184 | |||
185 | case '\0': | ||
186 | return symEOS; | ||
187 | |||
188 | default: | ||
189 | if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) | ||
190 | { | ||
191 | char num[50]={cbuf}; | ||
192 | int nPos = 1; | ||
193 | bool bDot = false; | ||
194 | |||
195 | for(;;) | ||
196 | { | ||
197 | cbuf = **sBuf; | ||
198 | if( cbuf == '.' ) | ||
199 | { | ||
200 | if( bDot == false ) | ||
201 | bDot = true; | ||
202 | else | ||
203 | throw ParseException( | ||
204 | "Numbers cannot have more than one " | ||
205 | ". in them." | ||
206 | ); | ||
207 | } | ||
208 | if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) | ||
209 | { | ||
210 | num[nPos++] = cbuf; | ||
211 | } | ||
212 | else | ||
213 | { | ||
214 | num[nPos] = '\0'; | ||
215 | sValue.push( strtod( num, NULL ) ); | ||
216 | return symNumber; | ||
217 | } | ||
218 | ++(*sBuf); | ||
219 | } | ||
220 | } | ||
221 | else if( (cbuf >= 'a' && cbuf <= 'z') || | ||
222 | (cbuf >= 'A' && cbuf <= 'Z') || | ||
223 | (cbuf == '_') ) | ||
224 | { | ||
225 | char tok[50]={cbuf}; | ||
226 | int nPos = 1; | ||
227 | |||
228 | for(;;) | ||
229 | { | ||
230 | cbuf = **sBuf; | ||
231 | if( (cbuf >= 'a' && cbuf <= 'z') || | ||
232 | (cbuf >= 'A' && cbuf <= 'Z') || | ||
233 | (cbuf >= '0' && cbuf <= '9') || | ||
234 | cbuf == '_' || cbuf == '.' || cbuf == ':' ) | ||
235 | { | ||
236 | tok[nPos++] = cbuf; | ||
237 | } | ||
238 | else | ||
239 | { | ||
240 | tok[nPos] = '\0'; | ||
241 | //printf("Checking variable \"%s\"\n", tok ); | ||
242 | try | ||
243 | { | ||
244 | sValue.push( hVars[tok] ); | ||
245 | return symNumber; | ||
246 | } | ||
247 | catch( HashException &e ) | ||
248 | { | ||
249 | throw ParseException( | ||
250 | "No variable named \"%s\" exists.", | ||
251 | tok | ||
252 | ); | ||
253 | } | ||
254 | } | ||
255 | ++(*sBuf); | ||
256 | } | ||
257 | } | ||
258 | break; | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | |||
diff --git a/src/old/formula.h b/src/old/formula.h new file mode 100644 index 0000000..939eb09 --- /dev/null +++ b/src/old/formula.h | |||
@@ -0,0 +1,77 @@ | |||
1 | #ifndef FORMULA_H | ||
2 | #define FORMULA_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | |||
6 | #include <math.h> | ||
7 | #include <stack> | ||
8 | #include "sbuffer.h" | ||
9 | |||
10 | #include "exceptionbase.h" | ||
11 | #include "hash.h" | ||
12 | |||
13 | subExceptionDecl( ParseException ); | ||
14 | |||
15 | /** | ||
16 | * Implements a very simple formula parser that allows use of variables and | ||
17 | * custom functions. This is based on a simple calculator-type parser that | ||
18 | * executes as it processes, accounting for operator precedence and grouping. | ||
19 | */ | ||
20 | class Formula | ||
21 | { | ||
22 | public: | ||
23 | Formula(); | ||
24 | virtual ~Formula(); | ||
25 | |||
26 | double run( char *sFormula ); | ||
27 | |||
28 | typedef Hash<std::string, double> varHash; | ||
29 | varHash hVars; | ||
30 | |||
31 | typedef struct Func | ||
32 | { | ||
33 | double operator()( double x ) | ||
34 | { | ||
35 | return 0.0; | ||
36 | } | ||
37 | } Func; | ||
38 | |||
39 | typedef Hash<std::string, Func> funcHash; | ||
40 | funcHash hFunc; | ||
41 | |||
42 | typedef struct FuncSin : Func | ||
43 | { | ||
44 | double operator()( double x ) | ||
45 | { | ||
46 | return sin( x ); | ||
47 | } | ||
48 | } FuncSin; | ||
49 | |||
50 | private: | ||
51 | enum | ||
52 | { | ||
53 | symEOS, | ||
54 | symAdd, | ||
55 | symSubtract, | ||
56 | symMultiply, | ||
57 | symDivide, | ||
58 | symOpenParen, | ||
59 | symCloseParen, | ||
60 | symNumber, | ||
61 | symVariable, | ||
62 | symExponent, | ||
63 | symModulus | ||
64 | }; | ||
65 | |||
66 | typedef uint8_t symType; | ||
67 | |||
68 | std::stack<symType> sOper; | ||
69 | std::stack<double> sValue; | ||
70 | |||
71 | private: | ||
72 | symType getPrec( symType nOper ); | ||
73 | symType nextToken( char **sBuf ); | ||
74 | void reduce( bool bCloseParen = false ); | ||
75 | }; | ||
76 | |||
77 | #endif | ||
diff --git a/src/old/fstring.cpp b/src/old/fstring.cpp new file mode 100644 index 0000000..82d024d --- /dev/null +++ b/src/old/fstring.cpp | |||
@@ -0,0 +1,13 @@ | |||
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 new file mode 100644 index 0000000..c5397cc --- /dev/null +++ b/src/old/fstring.h | |||
@@ -0,0 +1,651 @@ | |||
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 new file mode 100644 index 0000000..c52e6b1 --- /dev/null +++ b/src/old/hash.cpp | |||
@@ -0,0 +1,113 @@ | |||
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 new file mode 100644 index 0000000..e819379 --- /dev/null +++ b/src/old/hash.h | |||
@@ -0,0 +1,744 @@ | |||
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 new file mode 100644 index 0000000..8565956 --- /dev/null +++ b/src/old/hashable.cpp | |||
@@ -0,0 +1 @@ | |||
#include "hashable.h" | |||
diff --git a/src/old/hashable.h b/src/old/hashable.h new file mode 100644 index 0000000..98643d5 --- /dev/null +++ b/src/old/hashable.h | |||
@@ -0,0 +1,12 @@ | |||
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/hashfunction.cpp b/src/old/hashfunction.cpp new file mode 100644 index 0000000..51f2259 --- /dev/null +++ b/src/old/hashfunction.cpp | |||
@@ -0,0 +1,10 @@ | |||
1 | #include "hashfunction.h" | ||
2 | |||
3 | HashFunction::HashFunction() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | HashFunction::~HashFunction() | ||
8 | { | ||
9 | } | ||
10 | |||
diff --git a/src/old/hashfunction.h b/src/old/hashfunction.h new file mode 100644 index 0000000..cbcf70f --- /dev/null +++ b/src/old/hashfunction.h | |||
@@ -0,0 +1,48 @@ | |||
1 | #ifndef HASH_FUNCTION | ||
2 | #define HASH_FUNCTION | ||
3 | |||
4 | /** This represents the shell of a hash function. It must be aggregated in | ||
5 | * order to be used. Please read about it's two functions for specificatins | ||
6 | * relating to what values will be passed to them and what they should return | ||
7 | * for creating your own hash functions. | ||
8 | *@author Mike Buland. | ||
9 | */ | ||
10 | class HashFunction | ||
11 | { | ||
12 | public: | ||
13 | /** | ||
14 | * Standard Constructor. | ||
15 | */ | ||
16 | HashFunction(); | ||
17 | |||
18 | /** | ||
19 | * Standard Deconstructor. | ||
20 | */ | ||
21 | virtual ~HashFunction(); | ||
22 | |||
23 | /** Hashes the value represnted by id. This must return a fairly unique | ||
24 | * number in the range of 0-2^32 (or whatever the size of an unsigned long | ||
25 | * is on your system) based on the id given. The faster the number changes | ||
26 | * the better in a general sence. The return value will be the index | ||
27 | * (after probing takes place) to the data assosiated with an id, so this | ||
28 | * function should always produce the same number for any given id. | ||
29 | *@param id The identifier to use to create a unique numerical identifier. | ||
30 | *@returns A mostly unique numerical identifier generated using the given | ||
31 | * id. | ||
32 | */ | ||
33 | virtual unsigned long int hash( const void *id ) = 0; | ||
34 | |||
35 | /** This function must compare two ids in the format that this hashfunction | ||
36 | * accepts. For example, if the hash function hashes strings it should | ||
37 | * probably { return strcmp( id1, id2 ) == 0 }. | ||
38 | *@param id1 One value to use in the comparison | ||
39 | *@param id2 Another value to use in the comparison | ||
40 | *@returns True if the two values match, otherwise false. | ||
41 | */ | ||
42 | virtual bool cmpIDs( const void *id1, const void *id2 ) = 0; | ||
43 | |||
44 | // virtual void *createPersistantID( const void *id ) = 0; | ||
45 | // virtual void destroyPersistantID( const void *id ) = 0; | ||
46 | }; | ||
47 | |||
48 | #endif | ||
diff --git a/src/old/hashfunctioncasestring.cpp b/src/old/hashfunctioncasestring.cpp new file mode 100644 index 0000000..6361f45 --- /dev/null +++ b/src/old/hashfunctioncasestring.cpp | |||
@@ -0,0 +1,39 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <string.h> | ||
3 | #include <ctype.h> | ||
4 | #include "hashfunctioncasestring.h" | ||
5 | |||
6 | HashFunctionCaseString::HashFunctionCaseString() | ||
7 | { | ||
8 | } | ||
9 | |||
10 | HashFunctionCaseString::~HashFunctionCaseString() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | unsigned long int HashFunctionCaseString::hash( const void *id ) | ||
15 | { | ||
16 | const char *str = (const char *)id; | ||
17 | unsigned long int nPos = 0; | ||
18 | for( int j = 0; str[j] != '\0'; j++ ) | ||
19 | { | ||
20 | nPos = tolower(str[j]) + (nPos << 6) + (nPos << 16) - nPos; | ||
21 | // nPos += nPos<<16|(((unsigned long int)tolower(str[j]))<<((j*7)%24)); | ||
22 | } | ||
23 | return nPos; | ||
24 | } | ||
25 | |||
26 | bool HashFunctionCaseString::cmpIDs( const void *id1, const void *id2 ) | ||
27 | { | ||
28 | const char *str1 = (const char *)id1; | ||
29 | const char *str2 = (const char *)id2; | ||
30 | |||
31 | int j; | ||
32 | for( j = 0; str1[j] != '\0' && str2[j] != '\0'; j++ ) | ||
33 | { | ||
34 | if( tolower(str1[j]) != tolower(str2[j]) ) | ||
35 | return false; | ||
36 | } | ||
37 | return (str1[j]==str2[j]); | ||
38 | } | ||
39 | |||
diff --git a/src/old/hashfunctioncasestring.h b/src/old/hashfunctioncasestring.h new file mode 100644 index 0000000..7816a1b --- /dev/null +++ b/src/old/hashfunctioncasestring.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef HASH_FUNCTION_CASE_STRING | ||
2 | #define HASH_FUNCTION_CASE_STRING | ||
3 | |||
4 | #include "hashfunction.h" | ||
5 | |||
6 | /** A hash function for string data. This hash function does strings, but is | ||
7 | * actually generalized to handle any binary stream of characters terminated | ||
8 | * by a null character. This is different than HashFunctionString in that | ||
9 | * this does comparisons without regaurd to case. | ||
10 | *@author Mike Buland. | ||
11 | */ | ||
12 | class HashFunctionCaseString : public HashFunction | ||
13 | { | ||
14 | public: | ||
15 | /** | ||
16 | * Standard Constructor. | ||
17 | */ | ||
18 | HashFunctionCaseString(); | ||
19 | |||
20 | /** | ||
21 | * Standard Deconstructor. | ||
22 | */ | ||
23 | virtual ~HashFunctionCaseString(); | ||
24 | unsigned long int hash( const void *id ); | ||
25 | bool cmpIDs( const void *id1, const void *id2 ); | ||
26 | }; | ||
27 | |||
28 | #endif | ||
diff --git a/src/old/hashfunctionint.cpp b/src/old/hashfunctionint.cpp new file mode 100644 index 0000000..4bd0feb --- /dev/null +++ b/src/old/hashfunctionint.cpp | |||
@@ -0,0 +1,20 @@ | |||
1 | #include "hashfunctionint.h" | ||
2 | |||
3 | HashFunctionInt::HashFunctionInt() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | HashFunctionInt::~HashFunctionInt() | ||
8 | { | ||
9 | } | ||
10 | |||
11 | unsigned long int HashFunctionInt::hash( const void *id ) | ||
12 | { | ||
13 | return (unsigned long)(id); | ||
14 | } | ||
15 | |||
16 | bool HashFunctionInt::cmpIDs( const void *id1, const void *id2 ) | ||
17 | { | ||
18 | return (unsigned long)(id1) == (unsigned long)(id2); | ||
19 | } | ||
20 | |||
diff --git a/src/old/hashfunctionint.h b/src/old/hashfunctionint.h new file mode 100644 index 0000000..0fbc764 --- /dev/null +++ b/src/old/hashfunctionint.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #ifndef HASH_FUNCTION_INT | ||
2 | #define HASH_FUNCTION_INT | ||
3 | |||
4 | #include "hashfunction.h" | ||
5 | |||
6 | /** A hash function for integer data. Really, this does almost nothing except | ||
7 | * ensure we're dealing with positive indicies. | ||
8 | *@author Mike Buland. | ||
9 | */ | ||
10 | class HashFunctionInt : public HashFunction | ||
11 | { | ||
12 | public: | ||
13 | /** | ||
14 | * Standard Constructor. | ||
15 | */ | ||
16 | HashFunctionInt(); | ||
17 | |||
18 | /** | ||
19 | * Standard Deconstructor. | ||
20 | */ | ||
21 | virtual ~HashFunctionInt(); | ||
22 | unsigned long int hash( const void *id ); | ||
23 | bool cmpIDs( const void *id1, const void *id2 ); | ||
24 | }; | ||
25 | |||
26 | #endif | ||
diff --git a/src/old/hashfunctionstring.cpp b/src/old/hashfunctionstring.cpp new file mode 100644 index 0000000..bd14643 --- /dev/null +++ b/src/old/hashfunctionstring.cpp | |||
@@ -0,0 +1,51 @@ | |||
1 | #include "hashfunctionstring.h" | ||
2 | #ifndef NULL | ||
3 | #define NULL ((void *) 0) | ||
4 | #endif | ||
5 | |||
6 | HashFunctionString::HashFunctionString() | ||
7 | { | ||
8 | } | ||
9 | |||
10 | HashFunctionString::~HashFunctionString() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | unsigned long int HashFunctionString::hash( const void *id ) | ||
15 | { | ||
16 | if (id == NULL) | ||
17 | { | ||
18 | return 0; | ||
19 | } | ||
20 | |||
21 | unsigned long int nPos = 0; | ||
22 | for( const char *s = (const char *)id; *s; s++ ) | ||
23 | { | ||
24 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | ||
25 | } | ||
26 | return nPos; | ||
27 | } | ||
28 | |||
29 | bool HashFunctionString::cmpIDs( const void *id1, const void *id2 ) | ||
30 | { | ||
31 | if (id1 == NULL || id2 == NULL) | ||
32 | { | ||
33 | return false; | ||
34 | } | ||
35 | if (id1 == id2) | ||
36 | { | ||
37 | return true; | ||
38 | } | ||
39 | |||
40 | const char *str1 = (const char *)id1; | ||
41 | const char *str2 = (const char *)id2; | ||
42 | |||
43 | int j; | ||
44 | for( j = 0; str1[j] != '\0' && str2[j] != '\0'; j++ ) | ||
45 | { | ||
46 | if( str1[j] != str2[j] ) | ||
47 | return false; | ||
48 | } | ||
49 | return (str1[j]==str2[j]); | ||
50 | } | ||
51 | |||
diff --git a/src/old/hashfunctionstring.h b/src/old/hashfunctionstring.h new file mode 100644 index 0000000..7d2a1a6 --- /dev/null +++ b/src/old/hashfunctionstring.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef HASH_FUNCTION_STRING | ||
2 | #define HASH_FUNCTION_STRING | ||
3 | |||
4 | #include "hashfunction.h" | ||
5 | |||
6 | /** A hash function for string data. This hash function does strings, but is | ||
7 | * actually generalized to handle any binary stream of characters terminated | ||
8 | * by a null character. | ||
9 | *@author Mike Buland. | ||
10 | */ | ||
11 | class HashFunctionString : public HashFunction | ||
12 | { | ||
13 | public: | ||
14 | /** | ||
15 | * Standard Constructor. | ||
16 | */ | ||
17 | HashFunctionString(); | ||
18 | |||
19 | /** | ||
20 | * Standard Deconstructor. | ||
21 | */ | ||
22 | virtual ~HashFunctionString(); | ||
23 | unsigned long int hash( const void *id ); | ||
24 | bool cmpIDs( const void *id1, const void *id2 ); | ||
25 | }; | ||
26 | |||
27 | #endif | ||
diff --git a/src/old/hashtable.cpp b/src/old/hashtable.cpp new file mode 100644 index 0000000..dbcd964 --- /dev/null +++ b/src/old/hashtable.cpp | |||
@@ -0,0 +1,424 @@ | |||
1 | #include <string.h> | ||
2 | #include <stdio.h> | ||
3 | #include <math.h> | ||
4 | |||
5 | #include "hashtable.h" | ||
6 | |||
7 | HashTable::HashTable( HashFunction *hNewFunc, unsigned long int nInitSize, bool bAllowDupes ) | ||
8 | { | ||
9 | hFunc = hNewFunc; | ||
10 | nTableSize = nextPrime( nInitSize ); | ||
11 | aTable = new HashNode[nTableSize]; | ||
12 | //for( int j = 0; j < nTableSize; j++ ) if( aTable[j].id || aTable[j].data || aTable[j].bDeleted ) printf("Unclean entry\n"); | ||
13 | nSize = 0; | ||
14 | nFilled = 0; | ||
15 | this->bAllowDupes = bAllowDupes; | ||
16 | } | ||
17 | |||
18 | HashTable::~HashTable() | ||
19 | { | ||
20 | delete[] aTable; | ||
21 | delete hFunc; | ||
22 | } | ||
23 | |||
24 | void HashTable::set( int j, const void *newID, const void *newData ) | ||
25 | { | ||
26 | if( newData == NULL ) | ||
27 | { | ||
28 | printf("Inserting NULL data is indestinguishable from uninserted data!\n"); | ||
29 | } | ||
30 | aTable[j].id = newID; | ||
31 | aTable[j].data = newData; | ||
32 | } | ||
33 | |||
34 | void HashTable::clear() | ||
35 | { | ||
36 | memset( aTable, 0, sizeof(HashNode) * nTableSize ); | ||
37 | } | ||
38 | |||
39 | bool HashTable::isFilled( int j ) | ||
40 | { | ||
41 | return (aTable[j].id != NULL)||(aTable[j].bDeleted); | ||
42 | } | ||
43 | |||
44 | void HashTable::reHash( unsigned long int nNewSize ) | ||
45 | { | ||
46 | HashNode *aOldTable = aTable; | ||
47 | unsigned long int oldSize = nTableSize; | ||
48 | |||
49 | // If the table can still be used if we just get rid of deleted items, don't | ||
50 | // change the size of the table, otherwise, go ahead and use the number | ||
51 | // passed in. | ||
52 | if( nSize > nTableSize>>1 ) | ||
53 | { | ||
54 | nTableSize = nextPrime( nNewSize ); | ||
55 | } | ||
56 | |||
57 | aTable = newTable( nTableSize ); | ||
58 | //for( int j = 0; j < nTableSize; j++ ) if( aTable[j].id || aTable[j].data || aTable[j].bDeleted ) printf("Unclean entry\n"); | ||
59 | |||
60 | nSize = 0; | ||
61 | nFilled = 0; | ||
62 | |||
63 | for( unsigned long int j = 0; j < oldSize; j++ ) | ||
64 | { | ||
65 | if( aOldTable[j].id != NULL && aOldTable[j].bDeleted == false ) | ||
66 | { | ||
67 | insert( aOldTable[j].id, aOldTable[j].data ); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | delete[] aOldTable; | ||
72 | } | ||
73 | |||
74 | unsigned long int HashTable::probe( unsigned long int nStart, const void *id ) | ||
75 | { | ||
76 | int nHash = nStart; | ||
77 | nStart = nStart%nTableSize; | ||
78 | if( bAllowDupes == true ) | ||
79 | { | ||
80 | for( | ||
81 | unsigned long int j=0; | ||
82 | isFilled( nStart ) && j < 32; | ||
83 | nStart = (nStart+(1<<j))%nTableSize, j++ | ||
84 | ); | ||
85 | |||
86 | /** | ||
87 | * This is an ugly little hack. If the hash table is too full in allow- | ||
88 | * dups mode we have to fall back on a linear search, otherwise you can | ||
89 | * only get up to 32 entries with the same name. | ||
90 | */ | ||
91 | if( isFilled( nStart ) ) | ||
92 | { | ||
93 | unsigned long int nOldStart = nStart; | ||
94 | for( | ||
95 | nStart++; | ||
96 | isFilled( nStart ) && nStart != nOldStart; | ||
97 | nStart = (nStart+1)%nTableSize | ||
98 | ); | ||
99 | } | ||
100 | } | ||
101 | else | ||
102 | { | ||
103 | for( | ||
104 | unsigned long int j=0; | ||
105 | isFilled( nStart ) && j < 32; | ||
106 | nStart = (nStart+(1<<j))%nTableSize, j++ | ||
107 | ) | ||
108 | { | ||
109 | if( isFilled( nStart ) ) | ||
110 | { | ||
111 | if( hFunc->cmpIDs( aTable[nStart].id, id ) == true && | ||
112 | aTable[nStart].bDeleted == false ) | ||
113 | { | ||
114 | return nStart; | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | // This is our insurance, if the table is full, then go ahead and rehash, | ||
120 | // then try again. | ||
121 | if( isFilled( nStart ) ) | ||
122 | { | ||
123 | reHash( getCapacity()*2 ); | ||
124 | return probe( nHash, id ); | ||
125 | } | ||
126 | return nStart; | ||
127 | } | ||
128 | |||
129 | HashTable::HashNode *HashTable::newTable( unsigned long int nNewSize ) | ||
130 | { | ||
131 | return new HashNode[nNewSize]; | ||
132 | } | ||
133 | |||
134 | #ifdef HASH_DEBUG_VIS | ||
135 | void HashTable::printDebugLine( const char *exData ) | ||
136 | { | ||
137 | char *buf = new char[getCapacity()+3]; | ||
138 | int j; | ||
139 | buf[0] = '['; | ||
140 | for( j = 0; j < getCapacity(); j++ ) | ||
141 | { | ||
142 | buf[j+1] = (aTable[j].bDeleted)?('X'):((isFilled( j ))?('#'):('-')); | ||
143 | } | ||
144 | buf[j+1] = ']'; | ||
145 | buf[j+2] = '\0'; | ||
146 | printf("%s %s\n", buf, exData ); | ||
147 | delete[] buf; | ||
148 | } | ||
149 | #endif | ||
150 | |||
151 | bool HashTable::insert( const void *id, const void *data ) | ||
152 | { | ||
153 | unsigned long int nPos = probe( hFunc->hash( id ), id )%nTableSize; | ||
154 | |||
155 | if( bAllowDupes == true ) | ||
156 | { | ||
157 | if( aTable[nPos].id == NULL && aTable[nPos].bDeleted == false ) | ||
158 | { | ||
159 | set( nPos, id, data ); | ||
160 | #ifdef HASH_DEBUG_VIS | ||
161 | printDebugLine( (const char *)id ); | ||
162 | #endif | ||
163 | nSize++; | ||
164 | nFilled++; | ||
165 | return true; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | return false; | ||
170 | } | ||
171 | } | ||
172 | else | ||
173 | { | ||
174 | if( aTable[nPos].id == NULL && aTable[nPos].bDeleted == false ) | ||
175 | { | ||
176 | set( nPos, id, data ); | ||
177 | #ifdef HASH_DEBUG_VIS | ||
178 | printDebugLine( (const char *)id ); | ||
179 | #endif | ||
180 | nSize++; | ||
181 | nFilled++; | ||
182 | return true; | ||
183 | } | ||
184 | else if( hFunc->cmpIDs( aTable[nPos].id, id ) == true ) | ||
185 | { | ||
186 | set( nPos, id, data ); | ||
187 | #ifdef HASH_DEBUG_VIS | ||
188 | printDebugLine( (const char *)id ); | ||
189 | #endif | ||
190 | return true; | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | return false; | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | const void *HashTable::get( const void *id, unsigned long int nSkip ) | ||
200 | { | ||
201 | unsigned long int nPos = hFunc->hash( id )%nTableSize; | ||
202 | |||
203 | for( unsigned long int j=0; j < 32; nPos = (nPos+(1<<j))%nTableSize, j++ ) | ||
204 | { | ||
205 | if( !isFilled( nPos ) ) return NULL; | ||
206 | if( aTable[nPos].bDeleted == false ) | ||
207 | { | ||
208 | if( hFunc->cmpIDs( id, aTable[nPos].id ) ) | ||
209 | { | ||
210 | if( nSkip == 0 ) | ||
211 | { | ||
212 | return aTable[nPos].data; | ||
213 | } | ||
214 | else | ||
215 | { | ||
216 | nSkip--; | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | |||
222 | if( bAllowDupes ) | ||
223 | { | ||
224 | unsigned long int nOldPos = nPos; | ||
225 | for( nPos++; nPos != nOldPos; nPos=(nPos+1)%nTableSize ) | ||
226 | { | ||
227 | if( !isFilled( nPos ) ) return NULL; | ||
228 | if( aTable[nPos].bDeleted == false ) | ||
229 | { | ||
230 | if( hFunc->cmpIDs( id, aTable[nPos].id ) ) | ||
231 | { | ||
232 | if( nSkip == 0 ) | ||
233 | { | ||
234 | return aTable[nPos].data; | ||
235 | } | ||
236 | else | ||
237 | { | ||
238 | nSkip--; | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | } | ||
244 | |||
245 | return NULL; | ||
246 | } | ||
247 | |||
248 | const void *HashTable::getKey( const void *id, unsigned long int nSkip ) | ||
249 | { | ||
250 | unsigned long int nPos = hFunc->hash( id )%nTableSize; | ||
251 | |||
252 | for( unsigned long int j=0; j < 32; nPos = (nPos+(1<<j))%nTableSize, j++ ) | ||
253 | { | ||
254 | if( !isFilled( nPos ) ) return NULL; | ||
255 | if( aTable[nPos].bDeleted == false ) | ||
256 | { | ||
257 | if( hFunc->cmpIDs( id, aTable[nPos].id ) ) | ||
258 | { | ||
259 | if( nSkip == 0 ) | ||
260 | { | ||
261 | return aTable[nPos].id; | ||
262 | } | ||
263 | else | ||
264 | { | ||
265 | nSkip--; | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | } | ||
270 | |||
271 | if( bAllowDupes ) | ||
272 | { | ||
273 | unsigned long int nOldPos = nPos; | ||
274 | for( nPos++; nPos != nOldPos; nPos=(nPos+1)%nTableSize ) | ||
275 | { | ||
276 | if( !isFilled( nPos ) ) return NULL; | ||
277 | if( aTable[nPos].bDeleted == false ) | ||
278 | { | ||
279 | if( hFunc->cmpIDs( id, aTable[nPos].id ) ) | ||
280 | { | ||
281 | if( nSkip == 0 ) | ||
282 | { | ||
283 | return aTable[nPos].id; | ||
284 | } | ||
285 | else | ||
286 | { | ||
287 | nSkip--; | ||
288 | } | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | |||
294 | return NULL; | ||
295 | } | ||
296 | |||
297 | void *HashTable::getFirstItemPos() | ||
298 | { | ||
299 | HashPos *pos = new HashPos; | ||
300 | return pos; | ||
301 | } | ||
302 | |||
303 | const void *HashTable::getItemData( void *xPos ) | ||
304 | { | ||
305 | return aTable[((HashPos *)xPos)->nPos].data; | ||
306 | } | ||
307 | |||
308 | const void *HashTable::getItemID( void *xPos ) | ||
309 | { | ||
310 | return aTable[((HashPos *)xPos)->nPos].id; | ||
311 | } | ||
312 | |||
313 | void *HashTable::getNextItemPos( void *xPos ) | ||
314 | { | ||
315 | HashPos *pos = (HashPos *)xPos; | ||
316 | if( pos->bStarted == false ) | ||
317 | { | ||
318 | pos->bStarted = true; | ||
319 | pos->nPos = 0; | ||
320 | } | ||
321 | else | ||
322 | { | ||
323 | pos->nPos++; | ||
324 | } | ||
325 | if( pos->nPos < nTableSize ) | ||
326 | { | ||
327 | for( ; pos->nPos < nTableSize; pos->nPos++ ) | ||
328 | { | ||
329 | if( isFilled( pos->nPos ) && | ||
330 | aTable[pos->nPos].bDeleted == false ) | ||
331 | { | ||
332 | return xPos; | ||
333 | } | ||
334 | } | ||
335 | } | ||
336 | |||
337 | delete pos; | ||
338 | |||
339 | return NULL; | ||
340 | } | ||
341 | |||
342 | // Big-O sqrt(n) | ||
343 | // Change this to be erethpothynies table with a storage | ||
344 | // lookup later on. | ||
345 | bool HashTable::isPrime (int num) | ||
346 | { | ||
347 | if (num == 2) // the only even prime | ||
348 | return true; | ||
349 | else if (num % 2 == 0) // other even numbers are composite | ||
350 | return false; | ||
351 | else | ||
352 | { | ||
353 | //bool prime = true; | ||
354 | int divisor = 3; | ||
355 | int upperLimit = static_cast<int>(sqrt(num) + 1); | ||
356 | while (divisor <= upperLimit) | ||
357 | { | ||
358 | if (num % divisor == 0) | ||
359 | return false; | ||
360 | // prime = false; | ||
361 | divisor +=2; | ||
362 | } | ||
363 | return true; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | // Big-O n^(3/2) | ||
368 | int HashTable::nextPrime( int base ) | ||
369 | { | ||
370 | int nPrime; | ||
371 | for( nPrime = base; isPrime( nPrime ) == false; nPrime++ ); | ||
372 | return nPrime; | ||
373 | } | ||
374 | |||
375 | unsigned long int HashTable::getCapacity() | ||
376 | { | ||
377 | return nTableSize; | ||
378 | } | ||
379 | |||
380 | unsigned long int HashTable::getSize() | ||
381 | { | ||
382 | return nSize; | ||
383 | } | ||
384 | |||
385 | double HashTable::getLoad() | ||
386 | { | ||
387 | return (double)(nFilled)/(double)(nTableSize); | ||
388 | } | ||
389 | |||
390 | const void *HashTable::operator[](const void *id) | ||
391 | { | ||
392 | return get( id ); | ||
393 | } | ||
394 | |||
395 | bool HashTable::del( const void *id, int nSkip ) | ||
396 | { | ||
397 | unsigned long int nPos = hFunc->hash( id )%nTableSize; | ||
398 | |||
399 | for( unsigned long int j=0; j < 32; nPos = (nPos+(1<<j))%nTableSize, j++ ) | ||
400 | { | ||
401 | if( !isFilled( nPos ) ) return false; | ||
402 | //printf("0x%08X \"%s\" == 0x%08X \"%s\" (%d)\n", id, id, aTable[nPos].id, aTable[nPos].id, nPos ); | ||
403 | if( hFunc->cmpIDs( id, aTable[nPos].id ) && | ||
404 | aTable[nPos].bDeleted == false ) | ||
405 | { | ||
406 | if( nSkip == 0 ) | ||
407 | { | ||
408 | aTable[nPos].bDeleted = true; | ||
409 | nSize--; | ||
410 | #ifdef HASH_DEBUG_VIS | ||
411 | printDebugLine( (const char *)id ); | ||
412 | #endif | ||
413 | return true; | ||
414 | } | ||
415 | else | ||
416 | { | ||
417 | nSkip--; | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | |||
422 | return false; | ||
423 | } | ||
424 | |||
diff --git a/src/old/hashtable.h b/src/old/hashtable.h new file mode 100644 index 0000000..179b694 --- /dev/null +++ b/src/old/hashtable.h | |||
@@ -0,0 +1,308 @@ | |||
1 | /**\hashtable.h | ||
2 | * Describes the HashFunction, HashFunctionString, and HashTable classes. It | ||
3 | * was just easier to put them all in one set of files. | ||
4 | *@author Mike Buland | ||
5 | */ | ||
6 | |||
7 | #ifndef HASH_TABLE_H | ||
8 | #define HASH_TABLE_H | ||
9 | |||
10 | //Uncomment this line to see a cool text-mode visualization of what's going on | ||
11 | //#define HASH_DEBUG_VIS 1 | ||
12 | |||
13 | #include <stdlib.h> | ||
14 | #include <string.h> | ||
15 | #include <ctype.h> | ||
16 | |||
17 | #include "hashfunction.h" | ||
18 | |||
19 | /** | ||
20 | * A simple yet flexable hash-table. This uses several tricks to help ensure | ||
21 | * that the table is always running at maximum efficiency. You no longer have | ||
22 | * to specify a "danger fill level" when more space is needed a rehash is | ||
23 | * automatically trigered. Deleting elements is fully supported, as well as | ||
24 | * duplicate elements. To work with and allow duplicates simple construct your | ||
25 | * HashTable the way you normally would, but when deleting or getting elements | ||
26 | * you can specify a skip value. This effectively allows you to treat elements | ||
27 | * with duplicate ID's as though they were in a zero-based array. The first | ||
28 | * element inserted with a given ID would be at skip zero, the next at skip 1 | ||
29 | * and so on. This allows you to quickly search for elements with duplicate | ||
30 | * names, just stop when you get a null for a skip number, i.e. | ||
31 | * <pre> | ||
32 | * for( int j = 0;; j++ ) | ||
33 | * { | ||
34 | * void *pData = hash.get( myID, j ); | ||
35 | * if( !pData ) break; | ||
36 | * // Do something interesting with pData | ||
37 | * } | ||
38 | * </pre> | ||
39 | * There are new features in this HashTable that also allow for memory saving | ||
40 | * when dealing with systems where many elements are being deleted from the | ||
41 | * table. In those cases the elements deleted cannot be simply deleted, instead | ||
42 | * they have to be marked as deleted and hidden from the user, but maintained in | ||
43 | * the table so that future hashing operations don't fail. When rehashing | ||
44 | * occurs all elements marked as deleted are quietly removed. In these cases, | ||
45 | * if the number of deleted items would free enough space in the table for the | ||
46 | * table to be used efficiently without resizing, it is left the same size and | ||
47 | * rehashing is performed effectively in place, allowing the deleted items to | ||
48 | * be removed. | ||
49 | * <br> | ||
50 | * For info on adding new hashing algorithms, please see the HashFunction class. | ||
51 | *@author Mike Buland | ||
52 | *@todo Fix probing for tables that allow duplicates, and delete an item, then | ||
53 | * insert an item with the same name. | ||
54 | */ | ||
55 | class HashTable | ||
56 | { | ||
57 | public: | ||
58 | /** Constructs a hash table. | ||
59 | *@param hNewFunc A pointer to a hashfunction class to use. If this is | ||
60 | * null the default general string type will be used. | ||
61 | *@param nInitSize The initial size of the hashtable. | ||
62 | *@param bAllowDupes Setting this value to true allows the system to | ||
63 | * insert more than one copy of any given key. This can be tricky, and | ||
64 | * will require you to use the nSkip parameter on the get function. | ||
65 | */ | ||
66 | HashTable( HashFunction *hNewFunc, unsigned long int nInitSize, bool bAllowDupes=false ); | ||
67 | |||
68 | /** | ||
69 | * Destroys the hashtable, cleaning up all internal storage, but not stored | ||
70 | * elements. Also deletes the HashFunction passed in in the constructor. | ||
71 | */ | ||
72 | virtual ~HashTable(); | ||
73 | |||
74 | /** Inserts an item into the hashtable. This function will trigger a | ||
75 | * rehash if adding another item would force the table's load factor over | ||
76 | * the danger level. | ||
77 | *@param id used to find the data later. | ||
78 | *@param data The data item to insert into the table with the identifier | ||
79 | * id | ||
80 | *@returns True if insertion was successfull, and false if it failed. | ||
81 | */ | ||
82 | bool insert( const void *id, const void *data ); | ||
83 | |||
84 | /** Gets an item in the hashtable based on the id of that item. If there | ||
85 | * is more than one item with the same id you can use the nSkip parameter | ||
86 | * to access all of them. | ||
87 | *@param id The id of the item you're trying to find. | ||
88 | *@param nSkip The number of items with that id to skip before returning | ||
89 | * with the requested item. | ||
90 | *@returns A pointer to the data stored at the given id. | ||
91 | */ | ||
92 | const void *get( const void *id, unsigned long int nSkip=0 ); | ||
93 | |||
94 | const void *getKey( const void *id, unsigned long int nSkip=0 ); | ||
95 | |||
96 | /** Gets the total capacity of the hashtable. This is actually the number | ||
97 | * of total positions available inside the hashtable at the moment. This | ||
98 | * will change when the hashtable's load exceeds the danger level. | ||
99 | * Please note that this is NOT the actual amount of space available. | ||
100 | * In reality you can only access about 45-50 percent of that space. | ||
101 | *@returns The total capacity. | ||
102 | */ | ||
103 | unsigned long int getCapacity(); | ||
104 | |||
105 | /** Gets the number of filled in items in the hash table. This is roughly | ||
106 | * equivelent to the getSize function assosiated with the Lists. | ||
107 | *@returns The number of filled in items in the hash table. | ||
108 | */ | ||
109 | unsigned long int getSize(); | ||
110 | |||
111 | /** Gets the load (percentage) of filled in items in the table. This is | ||
112 | * technically the size divided by the capacity, but is definately usefull | ||
113 | * since it's required to check if it's time to rehash. | ||
114 | *@returns The table load in the range 0.0 to 1.0 | ||
115 | */ | ||
116 | double getLoad(); | ||
117 | |||
118 | /** Sets up an xPos object for use indexing the items in the table. Call | ||
119 | * this first and follow the directions for getNextItemPos below to | ||
120 | * iterate through every item in the table, while avoiding the empty | ||
121 | * spaces. | ||
122 | *@returns A pointer to a xPos object telling the hashtable where to find | ||
123 | * the item you're looking at. | ||
124 | */ | ||
125 | void *getFirstItemPos(); | ||
126 | |||
127 | /** Get the item's data that is being pointed to by xPos. This is only | ||
128 | * valid after xPos was created using getFirstItemPos and getNextItemPos | ||
129 | * was called at least once. | ||
130 | *@param xPos supplied by getFirstItemPos. | ||
131 | *@returns The key value that was used to insert the data into the table. | ||
132 | */ | ||
133 | const void *getItemData( void *xPos ); | ||
134 | |||
135 | /** Get the item's ID that is being pointed to by xPos. This is only | ||
136 | * valid after xPos was created using getFirstItemPos and getNextItemPos | ||
137 | * was called at least once. | ||
138 | *@param xPos supplied by getFirstItemPos. | ||
139 | *@returns The key value that was used to insert the data into the table. | ||
140 | */ | ||
141 | const void *getItemID( void *xPos ); | ||
142 | |||
143 | /** Used for iterating through a hash table sequentially. This will | ||
144 | * update the xPos pointer to point to the next time, all ready to | ||
145 | * be accessed with getItemID and getItemData. This must be called at | ||
146 | * least once before xPos is meaningful, and will return a NULL when it | ||
147 | * has reached the last item. | ||
148 | *@param xPos This must be an object created by a call to the function | ||
149 | * getFirstItemPos, and is only meaningful to the internal routines. | ||
150 | * Aborting a call in the middle (not running to the end of the table) | ||
151 | * may result in a memory leak at the moment. | ||
152 | *@returns xPos if still iterating through the list, otherwise it will | ||
153 | * return NULL when the end has been reached and the xPos variable has | ||
154 | * been deleted. | ||
155 | */ | ||
156 | void *getNextItemPos( void *xPos ); | ||
157 | |||
158 | /** A helpful operator to make accessing items easier. Please note that | ||
159 | * this simply returns a pointer to the data stored internally, and cannot | ||
160 | * be used like the STL operator to store new data, use insert for that. | ||
161 | *@param id The identifier used to store the requested item. | ||
162 | *@returns The data value assosiated with the given id, or NULL if it | ||
163 | * wasn't found in the table. | ||
164 | */ | ||
165 | const void *operator[](const void *id); | ||
166 | |||
167 | /** | ||
168 | * Delete the specified item from the hashtable. This actually keeps the | ||
169 | * data and marks it deleted. For all intents and purposes to the user it | ||
170 | * is deleted, except that the space is still used until a rehash is forced. | ||
171 | * This means that in hashtables where elements are being inserted and | ||
172 | * deleted frequently you may run into a higher rate of expansion. | ||
173 | *@param id The ID to delete. | ||
174 | *@param nSkip The number of similar id's to skip before deleting in a | ||
175 | * hashtable that allows duplicates. | ||
176 | *@returns True if the element was found and deleted, false otherwise. | ||
177 | */ | ||
178 | bool del( const void *id, int nSkip=0 ); | ||
179 | |||
180 | /** | ||
181 | * Deletes every entry in the hash table. See the notes on del to see what | ||
182 | * this means, except that since no data is being kept, the entire table is | ||
183 | * just marked as usable space. | ||
184 | */ | ||
185 | void clear(); | ||
186 | |||
187 | private: | ||
188 | /** | ||
189 | * Contains info related to a position in the hashtable. Used for | ||
190 | * searching through hashtables one item at a time, in order. This class | ||
191 | * should never be created by anything but a HashTable, and should never | ||
192 | * be referenced directly. Instead the hashtable returns a void pointer, | ||
193 | * which is what should be passed back in next time you use a search | ||
194 | * function. Always finish a search, since the object is deleted at the | ||
195 | * end of the search. | ||
196 | *@author Mike Buland | ||
197 | */ | ||
198 | class HashPos | ||
199 | { | ||
200 | public: | ||
201 | /** Create a blank HashPos. */ | ||
202 | HashPos() { bStarted=false; nPos = 0; }; | ||
203 | /** Has the search been started? */ | ||
204 | bool bStarted; | ||
205 | /** The position (index) into the backend storage structure. */ | ||
206 | unsigned long int nPos; | ||
207 | }; | ||
208 | |||
209 | /** | ||
210 | * All data related to a single element in the hashtable. This should | ||
211 | * really only be used and manipulated by the HashTable itself. | ||
212 | *@author Mike Buland | ||
213 | */ | ||
214 | typedef struct HashNode | ||
215 | { | ||
216 | public: | ||
217 | /** Create a new, empty HashNode. */ | ||
218 | HashNode() { id = NULL; data = NULL; bDeleted = false; }; | ||
219 | /** A pointer to the original ID that was used to key the data. */ | ||
220 | const void *id; | ||
221 | /** A pointer to the data stored along with the above ID. */ | ||
222 | const void *data; | ||
223 | /** Weather or not this data should really...exist */ | ||
224 | bool bDeleted; | ||
225 | } HashNode; | ||
226 | |||
227 | private: | ||
228 | /** | ||
229 | * Just sets the values in the element to some friendly values. | ||
230 | *@param newID The new ID to store. | ||
231 | *@param newData The new Data to store. | ||
232 | */ | ||
233 | void set( int j, const void *newID, const void *newData ); | ||
234 | /** | ||
235 | * Tells you if the node is filled or not. | ||
236 | *@returns True=an ID has been stored here, False=no ID. | ||
237 | */ | ||
238 | bool isFilled( int j ); | ||
239 | /** | ||
240 | * This actually resizes, but since every resize requires a reHash to go | ||
241 | * along with it, that's the name. This actually creates a new buffer for | ||
242 | * all of the contained data and then pulls every old element that was in | ||
243 | * the old table out and performs the hashing placement calculations again. | ||
244 | * This function skips all data that was marked as deleted, so at this | ||
245 | * point it really will be. | ||
246 | *@param nNewSize The new size to set the table to while re-hashing. | ||
247 | *@returns True if the operation was successful, false otherwise. | ||
248 | */ | ||
249 | void reHash( unsigned long int nNewSize ); | ||
250 | |||
251 | /** | ||
252 | * Helper function to allocate a new table. Really just does the memory | ||
253 | * allocation. | ||
254 | *@param nNewSize The size of the table to generate. | ||
255 | *@returns A new, blank array of HashNode objects the size you specified. | ||
256 | */ | ||
257 | HashNode *newTable( unsigned long int nNewSize ); | ||
258 | |||
259 | /** | ||
260 | * This function is used once an actual hash code is obtained. nStart is | ||
261 | * the given hash code, which is then wrapped to the size of the table. If | ||
262 | * there is data at that location, tests are performed to see if it's the | ||
263 | * right one. If it is, then it is returned, otherwise a series of further | ||
264 | * tests based on a 2^n search pattern is performed. The position of the | ||
265 | * requested data in the back-end storage is returned if found, otherwise | ||
266 | * another less useful value is returned... | ||
267 | *@param nStart The initial hashcode of the ID testing for. | ||
268 | *@param id A pointer to the id that is being searched for. | ||
269 | *@returns The real location of the data requested. | ||
270 | */ | ||
271 | unsigned long int probe( unsigned long int nStart, const void *id ); | ||
272 | |||
273 | /** | ||
274 | * Simple helper function to determine if a number is prime or not. | ||
275 | * This function runs in sqrt(n) time. | ||
276 | *@param num Number to test for prime-hood. | ||
277 | *@returns True if the number is prime, false otherwise. | ||
278 | */ | ||
279 | bool isPrime( int num ); | ||
280 | |||
281 | /** | ||
282 | * Given any number, this function finds the first number after it that is | ||
283 | * prime. Since this number is a multiple internally it's rare that the | ||
284 | * starting number would be prime. | ||
285 | *@param base The number to start the prime search on. | ||
286 | *@returns The first prime after the number given. | ||
287 | */ | ||
288 | int nextPrime( int base ); | ||
289 | |||
290 | #ifdef HASH_DEBUG_VIS | ||
291 | void printDebugLine( const char *exData ); | ||
292 | #endif | ||
293 | |||
294 | /** A pointer to the HashFunction subclass instance to use. */ | ||
295 | HashFunction *hFunc; | ||
296 | /** The complete array of HashNode objects to store data in. */ | ||
297 | HashNode *aTable; | ||
298 | /** The actual size of the table, not how many elements are in it. */ | ||
299 | unsigned long int nTableSize; | ||
300 | /** The number of elements that are in the table. */ | ||
301 | unsigned long int nSize; | ||
302 | /** The number of elements that are unavailable now. */ | ||
303 | unsigned long int nFilled; | ||
304 | /** Allow duplicate ID's in the table. */ | ||
305 | bool bAllowDupes; | ||
306 | }; | ||
307 | |||
308 | #endif | ||
diff --git a/src/old/http.cpp b/src/old/http.cpp new file mode 100644 index 0000000..df7dafe --- /dev/null +++ b/src/old/http.cpp | |||
@@ -0,0 +1,377 @@ | |||
1 | #include <string.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "http.h" | ||
4 | #include "hashfunctionstring.h" | ||
5 | |||
6 | Http::Http( Connection *pConnection ) : hReqHeader( new HashFunctionString(), 100 ) | ||
7 | { | ||
8 | pCon = pConnection; | ||
9 | nParseState = parseInit; | ||
10 | } | ||
11 | |||
12 | Http::~Http() | ||
13 | { | ||
14 | for( int j = 0; j < lStrings.getSize(); j++ ) | ||
15 | { | ||
16 | delete (std::string *)lStrings[j]; | ||
17 | } | ||
18 | } | ||
19 | |||
20 | bool Http::parseRequest() | ||
21 | { | ||
22 | for(;;) | ||
23 | { | ||
24 | pCon->readInput(); | ||
25 | switch( nParseState ) | ||
26 | { | ||
27 | case parseInit: | ||
28 | { | ||
29 | int nLen = pCon->scanInputFor( CR ); | ||
30 | if( nLen == -1 ) | ||
31 | { | ||
32 | return false; | ||
33 | } | ||
34 | else | ||
35 | { | ||
36 | nReqType = getRequestType( pCon->getInput() ); | ||
37 | pCon->usedInput( pCon->scanInputFor(' ')+1 ); | ||
38 | |||
39 | nLen = pCon->scanInputFor(' '); | ||
40 | sReqURI.append( pCon->getInput(), nLen ); | ||
41 | pCon->usedInput( nLen+1 ); | ||
42 | |||
43 | if( !strncmp( pCon->getInput(), "HTTP/", 5 ) ) | ||
44 | { | ||
45 | char mbuf[2]={'\0','\0'}; | ||
46 | unsigned char major, minor; | ||
47 | |||
48 | pCon->usedInput( 5 ); | ||
49 | mbuf[0] = pCon->getInput()[0]; | ||
50 | major = (unsigned char)atoi(mbuf); | ||
51 | mbuf[0] = pCon->getInput()[2]; | ||
52 | minor = (unsigned char)atoi(mbuf); | ||
53 | setRequestVersion( major, minor ); | ||
54 | if( checkRequestVer() ) | ||
55 | { | ||
56 | nParseState = parseHeader; | ||
57 | } | ||
58 | else | ||
59 | { | ||
60 | setResponseStatus( statusHTTPVersionNotSupported ); | ||
61 | //printf("Verson not supported.\n"); | ||
62 | return true; | ||
63 | } | ||
64 | |||
65 | pCon->usedInput( 5 ); | ||
66 | } | ||
67 | else | ||
68 | { | ||
69 | setResponseStatus( statusBadRequest ); | ||
70 | } | ||
71 | |||
72 | //return false; | ||
73 | } | ||
74 | } | ||
75 | break; | ||
76 | |||
77 | case parseHeader: | ||
78 | { | ||
79 | int nLen = pCon->scanInputFor( CR ); | ||
80 | //printf("nLen = %d: :::%s:::\n", nLen, pCon->getInput() ); | ||
81 | if( nLen == -1 ) | ||
82 | { | ||
83 | pCon->readInput( 1, 0); | ||
84 | } | ||
85 | else if( nLen == 0 ) | ||
86 | { | ||
87 | // We've got our double-newline, time for content. | ||
88 | pCon->usedInput( 2 ); | ||
89 | setResponseStatus( statusOK ); | ||
90 | return true; | ||
91 | } | ||
92 | else | ||
93 | { | ||
94 | nLen = pCon->scanInputFor(':'); | ||
95 | if( nLen == -1 ) | ||
96 | { | ||
97 | //printf("No colon? what are you trying to pull?\n"); | ||
98 | } | ||
99 | else | ||
100 | { | ||
101 | std::string *pName = new std::string( pCon->getInput(), nLen ); | ||
102 | lStrings.append( pName ); | ||
103 | pCon->usedInput( nLen+1 ); | ||
104 | |||
105 | nLen = pCon->scanInputFor( CR ); | ||
106 | std::string *pValue = convSpaceString( pCon->getInput(), nLen ); | ||
107 | lStrings.append( pValue ); | ||
108 | pCon->usedInput( nLen+2 ); | ||
109 | |||
110 | hReqHeader.insert( | ||
111 | pName->c_str(), | ||
112 | pValue->c_str() | ||
113 | ); | ||
114 | |||
115 | //printf("::%s = \"%s\"\n", | ||
116 | // pName->c_str(), | ||
117 | // pValue->c_str() | ||
118 | // ); | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | break; | ||
123 | |||
124 | case parseFinished: | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | |||
130 | bool Http::buildResponse( short nResponseCode, const char *sResponse ) | ||
131 | { | ||
132 | if( nResponseCode > 0 ) | ||
133 | { | ||
134 | nResStatus = nResponseCode; | ||
135 | } | ||
136 | |||
137 | if( sResponse == NULL ) | ||
138 | { | ||
139 | sResStatusStr = "uh yeah"; | ||
140 | } | ||
141 | else | ||
142 | { | ||
143 | sResStatusStr = sResponse; | ||
144 | } | ||
145 | |||
146 | time_t curTime; | ||
147 | time( &curTime ); | ||
148 | gmtime_r( &curTime, &tResTime ); | ||
149 | |||
150 | sServerStr = "libbu++ Http/0.0.1"; | ||
151 | bResPersistant = false; | ||
152 | |||
153 | //char buf[30]; | ||
154 | //strftime( buf, 30, "%a, %d %b %Y %H:%M:%S GMT", &tResponseTime ); | ||
155 | |||
156 | return true; | ||
157 | } | ||
158 | |||
159 | bool Http::sendResponse() | ||
160 | { | ||
161 | char buf[256]; | ||
162 | |||
163 | sprintf( buf, "HTTP/1.1 %d %s\r\n", nResStatus, sResStatusStr.c_str() ); | ||
164 | pCon->appendOutput( buf ); | ||
165 | |||
166 | strftime( buf, 256, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", &tResTime ); | ||
167 | pCon->appendOutput( buf ); | ||
168 | |||
169 | sprintf( buf, "Server: %s\r\n", sServerStr.c_str() ); | ||
170 | pCon->appendOutput( buf ); | ||
171 | |||
172 | if( bResPersistant ) | ||
173 | { | ||
174 | } | ||
175 | else | ||
176 | { | ||
177 | pCon->appendOutput("Connection: close\r\n"); | ||
178 | } | ||
179 | |||
180 | sprintf( buf, "Content-Type: %s\r\n", sResMime.c_str() ); | ||
181 | pCon->appendOutput( buf ); | ||
182 | |||
183 | sprintf( buf, "Content-Length: %d\r\n", sResContent.size() ); | ||
184 | pCon->appendOutput( buf ); | ||
185 | |||
186 | pCon->appendOutput("\r\n"); | ||
187 | |||
188 | pCon->appendOutput( sResContent.c_str(), sResContent.size() ); | ||
189 | |||
190 | return true; | ||
191 | } | ||
192 | |||
193 | void Http::setResponsePersistant( bool bPersistant ) | ||
194 | { | ||
195 | bResPersistant = bPersistant; | ||
196 | } | ||
197 | |||
198 | void Http::setResponseContent( const char *sMime, const char *sContent, int nLen ) | ||
199 | { | ||
200 | sResMime = sMime; | ||
201 | sResContent.erase(); | ||
202 | sResContent.append( sContent, nLen ); | ||
203 | } | ||
204 | |||
205 | std::string *Http::convSpaceString( const char *sStr, int nLen ) | ||
206 | { | ||
207 | int nNewLen = 0; | ||
208 | bool bStart = true; | ||
209 | bool bSpace = false; | ||
210 | |||
211 | for( int j = 0; j < nLen; j++ ) | ||
212 | { | ||
213 | if( sStr[j] == ' ' || sStr[j] == '\t' ) | ||
214 | { | ||
215 | if( bStart ) | ||
216 | { | ||
217 | } | ||
218 | else if( bSpace == false ) | ||
219 | { | ||
220 | bSpace = true; | ||
221 | nNewLen++; | ||
222 | } | ||
223 | } | ||
224 | else | ||
225 | { | ||
226 | bStart = false; | ||
227 | bSpace = false; | ||
228 | nNewLen++; | ||
229 | } | ||
230 | } | ||
231 | if( bSpace ) | ||
232 | { | ||
233 | nNewLen--; | ||
234 | } | ||
235 | |||
236 | std::string *pSStr = new std::string; | ||
237 | //char *pStr = pSStr->c_str(); | ||
238 | nNewLen = 0; | ||
239 | bStart = true; | ||
240 | bSpace = false; | ||
241 | |||
242 | for( int j = 0; j < nLen; j++ ) | ||
243 | { | ||
244 | if( sStr[j] == ' ' || sStr[j] == '\t' ) | ||
245 | { | ||
246 | if( bStart ) | ||
247 | { | ||
248 | } | ||
249 | else if( bSpace == false ) | ||
250 | { | ||
251 | bSpace = true; | ||
252 | *pSStr += ' '; | ||
253 | //pStr[nNewLen++] = ' '; | ||
254 | } | ||
255 | } | ||
256 | else | ||
257 | { | ||
258 | bStart = false; | ||
259 | bSpace = false; | ||
260 | *pSStr += sStr[j]; | ||
261 | //pStr[nNewLen++] = sStr[j]; | ||
262 | } | ||
263 | } | ||
264 | if( bSpace == true ) | ||
265 | { | ||
266 | nNewLen--; | ||
267 | // pStr[nNewLen] = '\0'; | ||
268 | } | ||
269 | |||
270 | return pSStr; | ||
271 | } | ||
272 | |||
273 | const char *Http::getRequestURI() | ||
274 | { | ||
275 | return sReqURI.c_str(); | ||
276 | } | ||
277 | |||
278 | short Http::getRequestType( const char *sType ) | ||
279 | { | ||
280 | if( !strncmp( sType, "OPTIONS", 7 ) ) | ||
281 | { | ||
282 | return reqOptions; | ||
283 | } | ||
284 | else if( !strncmp( sType, "GET", 3 ) ) | ||
285 | { | ||
286 | return reqGet; | ||
287 | } | ||
288 | else if( !strncmp( sType, "HEAD", 4 ) ) | ||
289 | { | ||
290 | return reqHead; | ||
291 | } | ||
292 | else if( !strncmp( sType, "POST", 4 ) ) | ||
293 | { | ||
294 | return reqPost; | ||
295 | } | ||
296 | else if( !strncmp( sType, "PUT", 3 ) ) | ||
297 | { | ||
298 | return reqPut; | ||
299 | } | ||
300 | else if( !strncmp( sType, "DELETE", 6 ) ) | ||
301 | { | ||
302 | return reqDelete; | ||
303 | } | ||
304 | else if( !strncmp( sType, "TRACE", 5 ) ) | ||
305 | { | ||
306 | return reqTrace; | ||
307 | } | ||
308 | else if( !strncmp( sType, "CONNECT", 7 ) ) | ||
309 | { | ||
310 | return reqConnect; | ||
311 | } | ||
312 | else | ||
313 | { | ||
314 | printf(" Uh oh, extension!\n"); | ||
315 | return reqExtension; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | const char *Http::getRequestType( short nType ) | ||
320 | { | ||
321 | switch( nType ) | ||
322 | { | ||
323 | case reqOptions: return "OPTIONS"; | ||
324 | case reqGet: return "GET"; | ||
325 | case reqHead: return "HEAD"; | ||
326 | case reqPost: return "POST"; | ||
327 | case reqPut: return "PUT"; | ||
328 | case reqDelete: return "DELETE"; | ||
329 | case reqTrace: return "TRACE"; | ||
330 | case reqConnect: return "CONNECT"; | ||
331 | case reqExtension: return "EXTENSION"; | ||
332 | default: return "INVALID VALUE"; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | short Http::getRequestType() | ||
337 | { | ||
338 | return nReqType; | ||
339 | } | ||
340 | |||
341 | const char *Http::getRequestTypeStr() | ||
342 | { | ||
343 | return getRequestType( nReqType ); | ||
344 | } | ||
345 | |||
346 | void Http::setResponseStatus( short nStatus ) | ||
347 | { | ||
348 | nResStatus = nStatus; | ||
349 | } | ||
350 | |||
351 | void Http::setRequestVersion( unsigned char nMajor, unsigned char nMinor ) | ||
352 | { | ||
353 | cReqVersion = (nMajor<<4)|nMinor; | ||
354 | } | ||
355 | |||
356 | unsigned char Http::getRequestMinorVer() | ||
357 | { | ||
358 | return cReqVersion&0x0F; | ||
359 | } | ||
360 | |||
361 | unsigned char Http::getRequestMajorVer() | ||
362 | { | ||
363 | return cReqVersion>>4; | ||
364 | } | ||
365 | |||
366 | bool Http::checkRequestVer() | ||
367 | { | ||
368 | if( cReqVersion == HTTP11 ) | ||
369 | return true; | ||
370 | return false; | ||
371 | } | ||
372 | |||
373 | const char *Http::getHeader( const char *lpStr ) | ||
374 | { | ||
375 | return (const char *)hReqHeader[lpStr]; | ||
376 | } | ||
377 | |||
diff --git a/src/old/http.h b/src/old/http.h new file mode 100644 index 0000000..7e9f9a0 --- /dev/null +++ b/src/old/http.h | |||
@@ -0,0 +1,273 @@ | |||
1 | /**\file http.h | ||
2 | * Describe a Hyper Text Transfer Protocol processor. This class will allow | ||
3 | * any program to act as either an HTTP server, client, or both. It contains | ||
4 | * a number of additional helpers and subclasses. | ||
5 | *@author Mike Buland | ||
6 | */ | ||
7 | |||
8 | #ifndef HTTP_H | ||
9 | #define HTTP_H | ||
10 | |||
11 | #include <iostream> | ||
12 | #include "connection.h" | ||
13 | #include "linkedlist.h" | ||
14 | #include "hashtable.h" | ||
15 | |||
16 | #define CR '\r' /**< The ASCII value of a Carrage Return */ | ||
17 | #define LF '\n' /**< The ASCII value of a Line Feed */ | ||
18 | #define CRLF CR LF /**< Combo of CR+LF for use in http */ | ||
19 | |||
20 | /** | ||
21 | * Macro to create combined http version codes. This just makes processing a | ||
22 | * little bit faster for the most part. | ||
23 | *@param maj Major version number, between 0 and 15 | ||
24 | *@param min Minor version number, between 0 and 15 | ||
25 | *@returns A one byte combined version number suitable for use in switches. | ||
26 | */ | ||
27 | #define HTTPVER( maj, min ) ((maj<<4)|(min)) | ||
28 | |||
29 | #define HTTP10 HTTPVER( 1, 0 ) /**< Combined version code for http 1.0 */ | ||
30 | #define HTTP11 HTTPVER( 1, 1 ) /**< Combined version code for http 1.1 */ | ||
31 | |||
32 | /** | ||
33 | * This is the master HTTP processing class. One instance handles one | ||
34 | * transaction, in the future a different mechanism may be thought up, but for | ||
35 | * now this means that you must create multiple objects to handle a single | ||
36 | * connection that contains multiple requests. | ||
37 | * In the constructor the Http class is given a connection object. This object | ||
38 | * should already be initialized and connected to whatever socket it wants to | ||
39 | * be sending and receiving data to and from. Once that's done you can call | ||
40 | * parseRequest if you're acting as a server, or a variety of buildRequest | ||
41 | * functions to create and send a request if you're a client. | ||
42 | * Please note that this class does not provide any HTTP or extended format | ||
43 | * processing systems, but will allow for mime types tables to be registered. | ||
44 | *@author Mike Buland | ||
45 | */ | ||
46 | class Http | ||
47 | { | ||
48 | public: | ||
49 | /** | ||
50 | * Create an Http object tied to an existing connection object. | ||
51 | *@param pConnection The live connection object to deal with. | ||
52 | */ | ||
53 | Http( Connection *pConnection ); | ||
54 | |||
55 | /** | ||
56 | * Standard Deconstructor. | ||
57 | */ | ||
58 | virtual ~Http(); | ||
59 | |||
60 | /** | ||
61 | * Perform all parsing needed to figure out what an HTTP client wants from | ||
62 | * us. This will setup a number of properties in the Http object itself | ||
63 | * and has the possibility of setting one or more response states initially. | ||
64 | * These states should be checked for immediately after parsing to see if | ||
65 | * an appropriate error message should be generated. These errors can | ||
66 | * include issues with protocol, data formats, or unknown versions of the | ||
67 | * protocol. | ||
68 | *@returns True means that all processing is finished, false means that | ||
69 | * the parseRequest function should be called again when more data is | ||
70 | * ready. A return value of true does not indicate success, only that | ||
71 | * processing is finished, the getResponseStatus function should be called | ||
72 | * to see what status was set in the parse routine. A 200 indicates that | ||
73 | * as far as the parser is concerned, everything when smoothly. Otherwise | ||
74 | * it's your responsibility to build the appropriate error response body | ||
75 | * (like an html file) and send it as the response. | ||
76 | */ | ||
77 | bool parseRequest(); | ||
78 | |||
79 | /** | ||
80 | * Get a request type's internal Http object id based on the string | ||
81 | * representation. These can be any HTTP/1.1 standard request type. | ||
82 | *@param sType The string that should be checked for type. This is in all | ||
83 | * caps, just like if it came from the HTTP client, which is most often | ||
84 | * the case. | ||
85 | *@returns The numerical ID of the given request type. Please note that | ||
86 | * HTTP/1.1 standard specifies that any string is valid here as long as | ||
87 | * the non-basic string is a request type understood by the serving | ||
88 | * software. This means that anything that is non-standard will return | ||
89 | * a type reqExtension and not an error. This is not a mistake. | ||
90 | */ | ||
91 | short getRequestType( const char *sType ); | ||
92 | |||
93 | /** | ||
94 | * Get the string representation of an Http object request type integer ID. | ||
95 | * This is used mainly for debugging to be sure the system has what we | ||
96 | * think it has. | ||
97 | *@param nType The integer ID of the request type to process. | ||
98 | *@returns The HTTP/1.1 string representation of that Http object ID code. | ||
99 | */ | ||
100 | const char *getRequestType( short nType ); | ||
101 | |||
102 | /** | ||
103 | * Returns the Http object request type ID code that is stored in the | ||
104 | * object by either the parseRequest function or use of the buildRequest | ||
105 | * functions. | ||
106 | *@returns The ID of the request type stored in the object. | ||
107 | */ | ||
108 | short getRequestType(); | ||
109 | |||
110 | /** | ||
111 | * Same as getRequestType, only returns the string representation. | ||
112 | *@returns The string representation of the request type ID stored in the | ||
113 | * object. | ||
114 | */ | ||
115 | const char *getRequestTypeStr(); | ||
116 | |||
117 | /** | ||
118 | * Sets the version of the request used by the system. This will be used | ||
119 | * by parse request, but is also part of the buildRequest tool functions. | ||
120 | *@param nMajor The major version number. | ||
121 | *@param nMinor The minor version number. | ||
122 | */ | ||
123 | void setRequestVersion( unsigned char nMajor, unsigned char nMinor ); | ||
124 | |||
125 | /** | ||
126 | * Gets the major version number of the protocol used/to be used in this | ||
127 | * request. | ||
128 | *@returns The major version number of the request protocol. | ||
129 | */ | ||
130 | unsigned char getRequestMinorVer(); | ||
131 | |||
132 | /** | ||
133 | * Gets the minor version number of the protocol used/to be used in this | ||
134 | * request. | ||
135 | *@returns The minor version number of the request protocol. | ||
136 | */ | ||
137 | unsigned char getRequestMajorVer(); | ||
138 | |||
139 | /** | ||
140 | * Checks the stored request version against an internal table of supported | ||
141 | * protocol versions. | ||
142 | *@returns True if the protocol version is supported, false otherwise. | ||
143 | */ | ||
144 | bool checkRequestVer(); | ||
145 | |||
146 | /** | ||
147 | * Converts an arbitrary string to a new string object with space saving | ||
148 | * operations performed ala the HTTP/1.1 specs. All leading and trailing | ||
149 | * whitespace is stripped, and all whitespace within the string is reduced | ||
150 | * to a single space char. | ||
151 | *@param sStr A pointer to the string data to process. | ||
152 | *@param nLen The length of the string to process. Since this function is | ||
153 | * often called on stream data, there is no null terminator where we need | ||
154 | * one. This is here for convinience so the data doesn't need to be hacked | ||
155 | * up or moved to an intermediate buffer. | ||
156 | *@returns A new string that may well be shorter than the original but that | ||
157 | * will have the same value as far as the HTTP/1.1 specs are concerned. | ||
158 | */ | ||
159 | std::string *convSpaceString( const char *sStr, int nLen ); | ||
160 | |||
161 | /** | ||
162 | * Gets a string pointer to the URI that was/is being requested. This can | ||
163 | * be any RFC standard URI, with or without protocol and domain. | ||
164 | *@returns A pointer to the URI that was/is being requested. | ||
165 | */ | ||
166 | const char *getRequestURI(); | ||
167 | |||
168 | /** | ||
169 | * Set a new response status. This status can be anything that the HTTP | ||
170 | * specs allow. Other values are allowed as well, but beware, not all | ||
171 | * servers/clients will accept values that are not in the tables in this | ||
172 | * class. | ||
173 | *@param nStatus The status to set. | ||
174 | */ | ||
175 | void setResponseStatus( short nStatus ); | ||
176 | |||
177 | bool buildResponse( short nResponseCode=-1, const char *sResponse=NULL ); | ||
178 | void setResponseContent( const char *sMime, const char *sContent, int nLen ); | ||
179 | void setResponsePersistant( bool bPersistant ); | ||
180 | bool sendResponse(); | ||
181 | |||
182 | enum | ||
183 | { | ||
184 | reqOptions, | ||
185 | reqGet, | ||
186 | reqHead, | ||
187 | reqPost, | ||
188 | reqPut, | ||
189 | reqDelete, | ||
190 | reqTrace, | ||
191 | reqConnect, | ||
192 | reqExtension | ||
193 | }; | ||
194 | |||
195 | enum | ||
196 | { | ||
197 | statusContinue = 100, | ||
198 | statusSwitchProto = 101, | ||
199 | |||
200 | statusOK = 200, | ||
201 | statusCreated = 201, | ||
202 | statusAccepted = 202, | ||
203 | statusNonAuthInfo = 203, | ||
204 | statusNoContent = 204, | ||
205 | statusResetContent = 205, | ||
206 | statusPartialContent = 206, | ||
207 | |||
208 | statusMultiChoices = 300, | ||
209 | statusMovedPermanently = 301, | ||
210 | statusFound = 302, | ||
211 | statusSeeOther = 303, | ||
212 | statusNotModified = 304, | ||
213 | statusUseProxy = 305, | ||
214 | statusUnused = 306, | ||
215 | statusTempRedirect = 307, | ||
216 | |||
217 | statusBadRequest = 400, | ||
218 | statusUnauthorized = 401, | ||
219 | statusPaymentRequired = 402, | ||
220 | statusForbidden = 403, | ||
221 | statusNotFound = 404, | ||
222 | statusMethodNotAllowed = 405, | ||
223 | statusNotAcceptable = 406, | ||
224 | statusProxyAuthRequired = 407, | ||
225 | statusRequestTimeout = 408, | ||
226 | statusConflict = 409, | ||
227 | statusGone = 410, | ||
228 | statusLengthRequired = 411, | ||
229 | statusPreconditionFailed = 412, | ||
230 | statusRequestEntityTooLarge = 413, | ||
231 | statusRequestURITooLong = 414, | ||
232 | statusUnsupportedMediaType = 415, | ||
233 | statusRequestedRangeNotSatisfiable = 416, | ||
234 | statusExpectationFailed = 417, | ||
235 | |||
236 | statusInternalServerError = 500, | ||
237 | statusNotImplemented = 501, | ||
238 | statusBadGateway = 502, | ||
239 | statusServiceUnavailable = 503, | ||
240 | statusGatewayTimeout = 504, | ||
241 | statusHTTPVersionNotSupported = 505 | ||
242 | }; | ||
243 | |||
244 | const char *getHeader( const char *lpStr ); | ||
245 | |||
246 | private: | ||
247 | Connection *pCon; | ||
248 | unsigned char nParseState; | ||
249 | |||
250 | short nReqType; | ||
251 | std::string *pReqStr; | ||
252 | std::string sReqURI; | ||
253 | unsigned char cReqVersion; | ||
254 | HashTable hReqHeader; | ||
255 | LinkedList lStrings; | ||
256 | |||
257 | std::string sServerStr; | ||
258 | std::string sResMime; | ||
259 | std::string sResContent; | ||
260 | std::string sResStatusStr; | ||
261 | bool bResPersistant; | ||
262 | struct tm tResTime; | ||
263 | short nResStatus; | ||
264 | |||
265 | enum | ||
266 | { | ||
267 | parseInit, | ||
268 | parseHeader, | ||
269 | parseFinished | ||
270 | }; | ||
271 | }; | ||
272 | |||
273 | #endif | ||
diff --git a/src/old/httpget.cpp b/src/old/httpget.cpp new file mode 100644 index 0000000..ee1f29c --- /dev/null +++ b/src/old/httpget.cpp | |||
@@ -0,0 +1,263 @@ | |||
1 | #include "httpget.h" | ||
2 | #include "exceptions.h" | ||
3 | #include "connection.h" | ||
4 | #include <stdio.h> | ||
5 | |||
6 | char HttpGet::hexcode[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; | ||
7 | |||
8 | HttpGet::HttpGet() : | ||
9 | nPort( 80 ), | ||
10 | sUserAgent("libbu++; HttpGet") | ||
11 | { | ||
12 | } | ||
13 | |||
14 | HttpGet::HttpGet( const std::string &url ) : | ||
15 | nPort( 80 ) | ||
16 | { | ||
17 | setURL( url ); | ||
18 | } | ||
19 | |||
20 | HttpGet::~HttpGet() | ||
21 | { | ||
22 | } | ||
23 | |||
24 | void HttpGet::setURL( const std::string &url ) | ||
25 | { | ||
26 | int len = url.size(); | ||
27 | //printf("Full URL: %s\n", url.c_str() ); | ||
28 | int pos = url.find("://"); | ||
29 | sProto.assign( url, 0, pos ); | ||
30 | //printf("Protocol: %s\n", sProto.c_str() ); | ||
31 | |||
32 | int pos2 = url.find("/", pos+3 ); | ||
33 | if( pos2 >= 0 ) | ||
34 | { | ||
35 | sHost.assign( url, pos+3, pos2-pos-3 ); | ||
36 | } | ||
37 | else | ||
38 | { | ||
39 | sHost.assign( url, pos+3, std::string::npos ); | ||
40 | } | ||
41 | |||
42 | int pos3 = sHost.find(":"); | ||
43 | if( pos3 >= 0 ) | ||
44 | { | ||
45 | nPort = strtol( sHost.c_str()+pos3+1, NULL, 10 ); | ||
46 | sHost.erase( pos3 ); | ||
47 | } | ||
48 | //printf("Hostname: %s\n", sHost.c_str() ); | ||
49 | //printf("Port: %d\n", nPort ); | ||
50 | |||
51 | pos3 = url.find("?", pos2+1 ); | ||
52 | if( pos3 >= 0 ) | ||
53 | { | ||
54 | sPath.assign( url, pos2, pos3-pos2 ); | ||
55 | //printf("Path: %s\n", sPath.c_str() ); | ||
56 | for(;;) | ||
57 | { | ||
58 | int end = pos3+1; | ||
59 | for(; url[end] != '=' && url[end] != '&' && end < len; end++ ); | ||
60 | std::string sKey, sValue; | ||
61 | sKey.assign( url, pos3+1, end-pos3-1 ); | ||
62 | if( url[end] == '=' ) | ||
63 | { | ||
64 | pos3 = end; | ||
65 | for( end++; url[end] != '&' && end < len; end++ ); | ||
66 | sValue.assign( url, pos3+1, end-pos3-1 ); | ||
67 | pos3 = end; | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | } | ||
72 | lParams.push_back( StringPair( sKey, sValue ) ); | ||
73 | //printf("Param: %s = %s\n", sKey.c_str(), sValue.c_str() ); | ||
74 | if( end+1 >= len ) break; | ||
75 | } | ||
76 | } | ||
77 | else | ||
78 | { | ||
79 | sPath.assign( url, pos2, std::string::npos ); | ||
80 | //printf("Path: %s\n", sPath.c_str() ); | ||
81 | } | ||
82 | |||
83 | //printf("\n"); | ||
84 | } | ||
85 | |||
86 | void HttpGet::addParam( const std::string &key, const std::string &value ) | ||
87 | { | ||
88 | lParams.push_back( StringPair( key, value ) ); | ||
89 | } | ||
90 | |||
91 | std::string HttpGet::escape( const std::string &src ) | ||
92 | { | ||
93 | std::string escaped(""); | ||
94 | for( std::string::const_iterator i = src.begin(); i != src.end(); i++ ) | ||
95 | { | ||
96 | unsigned char j = *i; | ||
97 | if( (j >= '0' && j <= '9') || | ||
98 | (j >= 'a' && j <= 'z') || | ||
99 | (j >= 'A' && j <= 'Z') || | ||
100 | j == '$' || | ||
101 | j == '-' || | ||
102 | j == '_' || | ||
103 | j == '.' || | ||
104 | j == '+' || | ||
105 | j == '!' || | ||
106 | j == '*' || | ||
107 | j == '\'' || | ||
108 | j == '(' || | ||
109 | j == ')' ) | ||
110 | { | ||
111 | escaped += j; | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | escaped += "%"; | ||
116 | escaped += hexcode[j>>4]; | ||
117 | escaped += hexcode[j&0x0F]; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | return escaped; | ||
122 | } | ||
123 | |||
124 | SBuffer *HttpGet::get() | ||
125 | { | ||
126 | std::string sData; | ||
127 | sData = "GET " + sPath; | ||
128 | if( !lParams.empty() ) | ||
129 | { | ||
130 | sData += "?"; | ||
131 | for( std::list<StringPair>::iterator i = lParams.begin(); | ||
132 | i != lParams.end(); i++ ) | ||
133 | { | ||
134 | if( i != lParams.begin() ) | ||
135 | sData += "&"; | ||
136 | |||
137 | if( (*i).second == "" ) | ||
138 | { | ||
139 | sData += escape( (*i).first ); | ||
140 | } | ||
141 | else | ||
142 | { | ||
143 | sData += escape( (*i).first ); | ||
144 | sData += "="; | ||
145 | sData += escape( (*i).second ); | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | |||
150 | sData += " HTTP/1.1\r\n" | ||
151 | "User-Agent: " + sUserAgent + "\r\n" | ||
152 | "Connection: close\r\n" | ||
153 | "Host: " + sHost + "\r\n" | ||
154 | "Content-type: application/x-www-form-urlencoded\r\n\r\n"; | ||
155 | |||
156 | //printf("Connection content:\n\n%s\n\n", sData.c_str() ); | ||
157 | |||
158 | Connection con; | ||
159 | //printf("Opening connection...\n"); | ||
160 | con.open( sHost.c_str(), nPort ); | ||
161 | { | ||
162 | int nSocket = con.getSocket(); | ||
163 | fd_set rfds, wfds, efds; | ||
164 | int retval; | ||
165 | |||
166 | FD_ZERO(&rfds); | ||
167 | FD_SET(nSocket, &rfds); | ||
168 | FD_ZERO(&wfds); | ||
169 | FD_SET(nSocket, &wfds); | ||
170 | FD_ZERO(&efds); | ||
171 | FD_SET(nSocket, &efds); | ||
172 | |||
173 | struct timeval tv; | ||
174 | tv.tv_sec = 4; | ||
175 | tv.tv_usec = 0; | ||
176 | |||
177 | //printf("Selecting on socket, can we read, write, etc?\n"); | ||
178 | retval = select( nSocket+1, &rfds, &wfds, &efds, &tv ); | ||
179 | /*printf("About to write: sock=%d, r=%d, w=%d, e=%d, ret=%d\n", | ||
180 | nSocket, | ||
181 | FD_ISSET( nSocket, &rfds ), | ||
182 | FD_ISSET( nSocket, &wfds ), | ||
183 | FD_ISSET( nSocket, &efds ), | ||
184 | retval | ||
185 | );*/ | ||
186 | |||
187 | if( retval == 0 ) | ||
188 | { | ||
189 | //printf("Timeout on connection.\n"); | ||
190 | con.close(); | ||
191 | throw ExceptionBase("Connection Timeout on open.\n"); | ||
192 | } | ||
193 | |||
194 | } | ||
195 | con.appendOutput( sData.c_str(), sData.size() ); | ||
196 | //printf("Writing to socket...\n"); | ||
197 | con.writeOutput(); | ||
198 | //printf("Data written...\n"); | ||
199 | int nSec = 5; | ||
200 | int nUSec = 0; | ||
201 | int nLastAmnt = con.getInputAmnt(); | ||
202 | try | ||
203 | { | ||
204 | double dTotTime = 0.0; | ||
205 | //printf("About to read input...\n"); | ||
206 | while( con.readInput( nSec, nUSec, &nSec, &nUSec ) ) | ||
207 | { | ||
208 | if( nLastAmnt == con.getInputAmnt() ) | ||
209 | { | ||
210 | if( nSec <= 0 && nUSec <= 0 ) | ||
211 | { | ||
212 | //printf("out of time, closing up.\n"); | ||
213 | con.close(); | ||
214 | throw ExceptionBase("Connection Timeout.\n"); | ||
215 | } | ||
216 | if( nSec == 5 && nUSec == 0 ) | ||
217 | { | ||
218 | //printf("No new data, breaking.\n"); | ||
219 | break; | ||
220 | } | ||
221 | } | ||
222 | else | ||
223 | { | ||
224 | dTotTime += (5.0-(nSec+nUSec/1000000.0)); | ||
225 | printf("\rRead %db at %.2fkb/sec", | ||
226 | con.getInputAmnt(), | ||
227 | ((double)(con.getInputAmnt())/1024.0) / dTotTime | ||
228 | ); | ||
229 | fflush( stdout ); | ||
230 | nSec = 5; | ||
231 | nUSec = 0; | ||
232 | nLastAmnt = con.getInputAmnt(); | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | catch( ConnectionException &e ) | ||
237 | { | ||
238 | //con.close(); | ||
239 | if( strcmp( e.what(), "Connection closed" ) ) | ||
240 | printf("\nConnectionException: %s\n", e.what() ); | ||
241 | } | ||
242 | |||
243 | int total = con.getInputAmnt(); | ||
244 | const char *dat = con.getInput(); | ||
245 | //printf("\n===> Final size %d\n", total ); | ||
246 | for( int i = 0; i < total; i++ ) | ||
247 | { | ||
248 | if( !memcmp( dat+i, "\r\n\r\n", 4 ) ) | ||
249 | { | ||
250 | SBuffer *buf = new SBuffer; | ||
251 | buf->write( dat+i+4, total-i-4 ); | ||
252 | buf->setPos( 0 ); | ||
253 | con.close(); | ||
254 | return buf; | ||
255 | } | ||
256 | } | ||
257 | con.close(); | ||
258 | |||
259 | //printf("\n\n%s\n\n", dat ); | ||
260 | |||
261 | throw ExceptionBase("Something went wrong, incomplete response? fix this.\n"); | ||
262 | } | ||
263 | |||
diff --git a/src/old/httpget.h b/src/old/httpget.h new file mode 100644 index 0000000..8272641 --- /dev/null +++ b/src/old/httpget.h | |||
@@ -0,0 +1,44 @@ | |||
1 | #ifndef HTTP_GET_H | ||
2 | #define HTTP_GET_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <string> | ||
6 | #include <list> | ||
7 | #include <utility> | ||
8 | |||
9 | #include "sbuffer.h" | ||
10 | |||
11 | class HttpGet | ||
12 | { | ||
13 | public: | ||
14 | HttpGet(); | ||
15 | HttpGet( const std::string &url ); | ||
16 | virtual ~HttpGet(); | ||
17 | |||
18 | void setURL( const std::string &url ); | ||
19 | void addParam( const std::string &key, const std::string &value ); | ||
20 | void setUserAgent( const std::string &sUserAgent ) | ||
21 | { | ||
22 | this->sUserAgent = sUserAgent; | ||
23 | } | ||
24 | void setHost( const std::string &sHost ) | ||
25 | { | ||
26 | this->sHost = sHost; | ||
27 | } | ||
28 | |||
29 | std::string escape( const std::string &src ); | ||
30 | SBuffer *get(); | ||
31 | |||
32 | private: | ||
33 | std::string sProto; | ||
34 | std::string sHost; | ||
35 | std::string sPath; | ||
36 | int nPort; | ||
37 | std::string sUserAgent; | ||
38 | typedef std::pair<std::string,std::string> StringPair; | ||
39 | std::list<StringPair> lParams; | ||
40 | static char hexcode[]; | ||
41 | |||
42 | }; | ||
43 | |||
44 | #endif | ||
diff --git a/src/old/linkedlist.cpp b/src/old/linkedlist.cpp new file mode 100644 index 0000000..a9902bc --- /dev/null +++ b/src/old/linkedlist.cpp | |||
@@ -0,0 +1,210 @@ | |||
1 | #include "linkedlist.h" | ||
2 | |||
3 | LinkedList::LinkedList( ) | ||
4 | { | ||
5 | pBase = NULL; | ||
6 | pTop = NULL; | ||
7 | pLast = NULL; | ||
8 | nSize = 0; | ||
9 | nLast = -1; | ||
10 | } | ||
11 | |||
12 | LinkedList::~LinkedList( ) | ||
13 | { | ||
14 | /* | ||
15 | Link *pCur = pBase; | ||
16 | while( pCur ) | ||
17 | { | ||
18 | Link *pLast = pCur; | ||
19 | pCur = pCur->pNext; | ||
20 | delete pLast; | ||
21 | } | ||
22 | */ | ||
23 | empty(); | ||
24 | } | ||
25 | |||
26 | void *LinkedList::getAt( int index ) | ||
27 | { | ||
28 | if( index < 0 || index >= nSize ) | ||
29 | return NULL; | ||
30 | |||
31 | return getPtrTo( index )->pData; | ||
32 | } | ||
33 | |||
34 | void LinkedList::append( void *data ) | ||
35 | { | ||
36 | if( pBase == NULL ) | ||
37 | { | ||
38 | pBase = new Link( data ); | ||
39 | pTop = pBase; | ||
40 | nSize++; | ||
41 | } | ||
42 | else | ||
43 | { | ||
44 | pTop->pNext = new Link( data ); | ||
45 | pTop = pTop->pNext; | ||
46 | nSize++; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | void LinkedList::insertBefore( void *data, int pos ) | ||
51 | { | ||
52 | if( pos < 0 || pos > nSize ) | ||
53 | return; | ||
54 | |||
55 | if( pos == 0 ) | ||
56 | { | ||
57 | Link *pTmp = new Link( data, pBase ); | ||
58 | if( pBase == NULL ) | ||
59 | { | ||
60 | pTop = pTmp; | ||
61 | } | ||
62 | pBase = pTmp; | ||
63 | if( nLast >= 0 ) nLast++; | ||
64 | nSize++; | ||
65 | } | ||
66 | else | ||
67 | { | ||
68 | Link *pCur; | ||
69 | if( (pCur = getPtrTo( pos-1 )) == NULL ) | ||
70 | { | ||
71 | return; | ||
72 | } | ||
73 | Link *pNew = new Link( data, pCur->pNext ); | ||
74 | pCur->pNext = pNew; | ||
75 | if( pNew->pNext == NULL ) | ||
76 | { | ||
77 | pTop = pNew; | ||
78 | } | ||
79 | if( nLast >= pos ) nLast++; | ||
80 | nSize++; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | int LinkedList::getSize( ) | ||
85 | { | ||
86 | return nSize; | ||
87 | } | ||
88 | |||
89 | bool LinkedList::isEmpty( ) | ||
90 | { | ||
91 | if( nSize == 0 ) | ||
92 | return true; | ||
93 | return false; | ||
94 | } | ||
95 | |||
96 | void LinkedList::deleteAt( int index ) | ||
97 | { | ||
98 | if( index >= nSize || | ||
99 | pBase == NULL ) | ||
100 | return; | ||
101 | |||
102 | if( index == 0 ) | ||
103 | { | ||
104 | Link *pTmp = pBase->pNext; | ||
105 | delete pBase; | ||
106 | pBase = pTmp; | ||
107 | if( nLast >= 0 ) nLast--; | ||
108 | nSize--; | ||
109 | if( pBase == NULL ) | ||
110 | { | ||
111 | pTop = NULL; | ||
112 | } | ||
113 | else if( pBase->pNext == NULL ) | ||
114 | { | ||
115 | pTop = pBase; | ||
116 | } | ||
117 | } | ||
118 | else | ||
119 | { | ||
120 | Link *pCur = getPtrTo( index-1 ); | ||
121 | if( pCur->pNext == pTop ) | ||
122 | { | ||
123 | pTop = pCur; | ||
124 | } | ||
125 | Link *pTmp; | ||
126 | if( pCur->pNext == NULL ) | ||
127 | { | ||
128 | pTmp = NULL; | ||
129 | } | ||
130 | else | ||
131 | { | ||
132 | pTmp = pCur->pNext->pNext; | ||
133 | } | ||
134 | delete pCur->pNext; | ||
135 | pCur->pNext = pTmp; | ||
136 | if( nLast == index ) nLast = -1; | ||
137 | else if( index < nLast ) nLast--; | ||
138 | nSize--; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | void LinkedList::empty() | ||
143 | { | ||
144 | while( nSize > 0 ) | ||
145 | { | ||
146 | deleteAt( 0 ); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | void LinkedList::setSize( int newSize ) | ||
151 | { | ||
152 | if( newSize < nSize ) | ||
153 | { | ||
154 | // Delete items off of the end of the list. | ||
155 | while( nSize > newSize ) | ||
156 | { | ||
157 | deleteAt( nSize-1 ); | ||
158 | } | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | // Add null items to the end of the list. | ||
163 | while( nSize < newSize ) | ||
164 | { | ||
165 | append( NULL ); | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | |||
170 | void LinkedList::setAt( int index, void *data ) | ||
171 | { | ||
172 | if( index >= nSize || index < 0 ) | ||
173 | return; | ||
174 | |||
175 | getPtrTo( index )->pData = data; | ||
176 | } | ||
177 | |||
178 | LinkedList::Link *LinkedList::getPtrTo( int index ) | ||
179 | { | ||
180 | if( index < 0 || index >= nSize ) | ||
181 | return NULL; | ||
182 | if( index == nLast ) | ||
183 | { | ||
184 | return pLast; | ||
185 | } | ||
186 | if( index == 0 ) | ||
187 | { | ||
188 | pLast = pBase; | ||
189 | nLast = 0; | ||
190 | return pBase; | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | Link *pCur = pBase; | ||
195 | int nCur = 0; | ||
196 | if( nLast < index && nLast >= 0 ) | ||
197 | { | ||
198 | pCur = pLast; | ||
199 | nCur = nLast; | ||
200 | } | ||
201 | while( nCur != index ) | ||
202 | { | ||
203 | pCur = pCur->pNext; | ||
204 | nCur++; | ||
205 | } | ||
206 | nLast = index; | ||
207 | pLast = pCur; | ||
208 | return pCur; | ||
209 | } | ||
210 | } | ||
diff --git a/src/old/linkedlist.h b/src/old/linkedlist.h new file mode 100644 index 0000000..e430108 --- /dev/null +++ b/src/old/linkedlist.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /**@file | ||
2 | * Describes the LinkedList implementation of the List ADT. | ||
3 | *@author Mike Buland | ||
4 | */ | ||
5 | |||
6 | #ifndef LINKEDLIST_H | ||
7 | #define LINKEDLIST_H | ||
8 | |||
9 | #include <stdio.h> | ||
10 | #include "list.h" | ||
11 | |||
12 | /** A linked-item implementation of the List ADT. Since the data is linked | ||
13 | * sequentially this is a great choice for lists that will grow and shrink | ||
14 | * a lot, but don't require as much random access. This implementation | ||
15 | * includes optomizations that make iterating through data, and appending | ||
16 | * items to the list take O(1) time. | ||
17 | *@author Mike Buland | ||
18 | */ | ||
19 | class LinkedList : public List | ||
20 | { | ||
21 | public: | ||
22 | /** | ||
23 | * Construct a blank LinkedList. | ||
24 | */ | ||
25 | LinkedList(); | ||
26 | |||
27 | /** | ||
28 | * Delete all list data, but do not delete any of the contained elements. | ||
29 | */ | ||
30 | virtual ~LinkedList(); | ||
31 | |||
32 | void *getAt( int nIndex ); | ||
33 | void append( void *pData ); | ||
34 | void insertBefore( void *pData, int nPos = 0 ); | ||
35 | int getSize( ); | ||
36 | bool isEmpty( ); | ||
37 | void deleteAt( int nIndex ); | ||
38 | void empty(); | ||
39 | void setSize( int nNewSize ); | ||
40 | void setAt( int nIndex, void *pData ); | ||
41 | |||
42 | private: | ||
43 | /** | ||
44 | * A link in the linked list. | ||
45 | */ | ||
46 | class Link | ||
47 | { | ||
48 | public: | ||
49 | /** | ||
50 | * Construct an empty link. | ||
51 | */ | ||
52 | Link() | ||
53 | { | ||
54 | pData = NULL; | ||
55 | pNext = NULL; | ||
56 | } | ||
57 | /** | ||
58 | * Construct a link filled in with useful data. | ||
59 | *@param newData The data this link should hold. | ||
60 | *@param newNext The next link that this link should point to. | ||
61 | */ | ||
62 | Link( void *newData = NULL, Link * newNext = NULL ) | ||
63 | { | ||
64 | pData = newData; | ||
65 | pNext = newNext; | ||
66 | } | ||
67 | void *pData; /**< A pointer to the contained data. */ | ||
68 | Link *pNext; /**< A pointer to the next link in the chain */ | ||
69 | }; | ||
70 | |||
71 | /** | ||
72 | * Finds a pointer to the link at index index. This is the core function | ||
73 | * called for all seek operations, and has been optimized as heavily as | ||
74 | * possible. | ||
75 | *@param index The zero-based index of the desired element. | ||
76 | *@returns A pointer to the requested Link, or NULL if it isn't found. | ||
77 | */ | ||
78 | Link *getPtrTo( int index ); | ||
79 | Link *pBase; /**< The first link in the list. */ | ||
80 | Link *pTop; /**< The Last link in the list. */ | ||
81 | Link *pLast; /**< The previously requested link. */ | ||
82 | int nSize; /**< The number of contained links. */ | ||
83 | int nLast; /**< The index of the previously requested link. */ | ||
84 | }; | ||
85 | |||
86 | #endif | ||
87 | |||
diff --git a/src/old/linkmessage.cpp b/src/old/linkmessage.cpp new file mode 100644 index 0000000..cf3df42 --- /dev/null +++ b/src/old/linkmessage.cpp | |||
@@ -0,0 +1,44 @@ | |||
1 | #include "linkmessage.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | LinkMessage::LinkMessage( int nNewMsg ) | ||
5 | { | ||
6 | nMsg = nNewMsg; | ||
7 | } | ||
8 | |||
9 | LinkMessage::~LinkMessage() | ||
10 | { | ||
11 | } | ||
12 | |||
13 | /* | ||
14 | void LinkMessage::setBroadcast( bool bOn ) | ||
15 | { | ||
16 | bBroadcast = bOn; | ||
17 | } | ||
18 | |||
19 | bool LinkMessage::isBroadcast() | ||
20 | { | ||
21 | return bBroadcast; | ||
22 | } | ||
23 | |||
24 | |||
25 | void LinkMessage::setFromID( int id ) | ||
26 | { | ||
27 | nFromLinkID = id; | ||
28 | } | ||
29 | |||
30 | int LinkMessage::getFromID() | ||
31 | { | ||
32 | return nFromLinkID; | ||
33 | } | ||
34 | |||
35 | void LinkMessage::setToID( int id ) | ||
36 | { | ||
37 | nTargetLinkID = id; | ||
38 | } | ||
39 | |||
40 | int LinkMessage::getToID() | ||
41 | { | ||
42 | return nTargetLinkID; | ||
43 | } | ||
44 | */ | ||
diff --git a/src/old/linkmessage.h b/src/old/linkmessage.h new file mode 100644 index 0000000..6cdfb2f --- /dev/null +++ b/src/old/linkmessage.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /**\file linkmessage.h | ||
2 | */ | ||
3 | |||
4 | #ifndef LINKMESSAGE_H | ||
5 | #define LINKMESSAGE_H | ||
6 | |||
7 | /** | ||
8 | * A message to be broadcast accross ProgramLinks in a ProgramChain. Generally | ||
9 | * one would make a subclass of this in order to transmit more useful | ||
10 | * information, but sometimes it isn't necesarry. | ||
11 | *@author Mike Buland | ||
12 | */ | ||
13 | class LinkMessage | ||
14 | { | ||
15 | public: | ||
16 | /** | ||
17 | * Construct a blank LinkMessage. | ||
18 | */ | ||
19 | LinkMessage() {}; | ||
20 | |||
21 | /** | ||
22 | * Deconstruct a LinkMessage. | ||
23 | */ | ||
24 | virtual ~LinkMessage(); | ||
25 | |||
26 | /** | ||
27 | * Create a LinkMessage object with a specific message assosiated with it | ||
28 | * to start with. | ||
29 | *@param nNewMsg The message to use in the Message object. | ||
30 | */ | ||
31 | LinkMessage( int nNewMsg ); | ||
32 | |||
33 | /** | ||
34 | * The message contained in the Message object. | ||
35 | */ | ||
36 | int nMsg; | ||
37 | }; | ||
38 | |||
39 | #endif | ||
diff --git a/src/old/linkmessenger.cpp b/src/old/linkmessenger.cpp new file mode 100644 index 0000000..3bd401a --- /dev/null +++ b/src/old/linkmessenger.cpp | |||
@@ -0,0 +1,41 @@ | |||
1 | #include "linkmessenger.h" | ||
2 | |||
3 | LinkMessenger::LinkMessenger() : | ||
4 | pFirst( NULL ), | ||
5 | pLast( NULL ) | ||
6 | { | ||
7 | } | ||
8 | |||
9 | LinkMessenger::~LinkMessenger() | ||
10 | { | ||
11 | } | ||
12 | |||
13 | void LinkMessenger::enqueueMessage( LinkMessage *pMsg ) | ||
14 | { | ||
15 | if( pLast == NULL ) | ||
16 | { | ||
17 | pFirst = pLast = new Link; | ||
18 | pLast->pMsg = pMsg; | ||
19 | pLast->pNext = NULL; | ||
20 | } | ||
21 | else | ||
22 | { | ||
23 | pLast->pNext = new Link; | ||
24 | pLast = pLast->pNext; | ||
25 | pLast->pMsg = pMsg; | ||
26 | pLast->pNext = NULL; | ||
27 | } | ||
28 | } | ||
29 | |||
30 | LinkMessage *LinkMessenger::dequeueMessage() | ||
31 | { | ||
32 | if( pFirst == NULL ) | ||
33 | return NULL; | ||
34 | |||
35 | Link *pTmp = pFirst; | ||
36 | pFirst = pFirst->pNext; | ||
37 | LinkMessage *pRet = pTmp->pMsg; | ||
38 | delete pTmp; | ||
39 | return pRet; | ||
40 | } | ||
41 | |||
diff --git a/src/old/linkmessenger.h b/src/old/linkmessenger.h new file mode 100644 index 0000000..ed52639 --- /dev/null +++ b/src/old/linkmessenger.h | |||
@@ -0,0 +1,32 @@ | |||
1 | #ifndef LINK_MESSENGER_H | ||
2 | #define LINK_MESSENGER_H | ||
3 | |||
4 | #include <stdlib.h> | ||
5 | #include <stdint.h> | ||
6 | #include "linkmessage.h" | ||
7 | |||
8 | class LinkMessenger | ||
9 | { | ||
10 | public: | ||
11 | LinkMessenger(); | ||
12 | virtual ~LinkMessenger(); | ||
13 | |||
14 | void enqueueMessage( LinkMessage *pMsg ); | ||
15 | LinkMessage *dequeueMessage(); | ||
16 | bool hasMessages() | ||
17 | { | ||
18 | return (pFirst != NULL); | ||
19 | } | ||
20 | |||
21 | private: | ||
22 | typedef struct Link | ||
23 | { | ||
24 | LinkMessage *pMsg; | ||
25 | Link *pNext; | ||
26 | }; | ||
27 | Link *pFirst; | ||
28 | Link *pLast; | ||
29 | |||
30 | }; | ||
31 | |||
32 | #endif | ||
diff --git a/src/old/list.cpp b/src/old/list.cpp new file mode 100644 index 0000000..18f1a66 --- /dev/null +++ b/src/old/list.cpp | |||
@@ -0,0 +1,10 @@ | |||
1 | #include "list.h" | ||
2 | |||
3 | List::List( ) | ||
4 | { | ||
5 | } | ||
6 | |||
7 | List::~List( ) | ||
8 | { | ||
9 | } | ||
10 | |||
diff --git a/src/old/list.h b/src/old/list.h new file mode 100644 index 0000000..c71b328 --- /dev/null +++ b/src/old/list.h | |||
@@ -0,0 +1,101 @@ | |||
1 | #ifndef LIST_H | ||
2 | #define LIST_H | ||
3 | |||
4 | |||
5 | /** The basic List class ADT. This, on it's own, does absolutely nothing, but | ||
6 | * does define all standard interface functions to access a list. | ||
7 | *@author Mike Buland | ||
8 | */ | ||
9 | class List | ||
10 | { | ||
11 | public: | ||
12 | /** | ||
13 | * Construct a list. | ||
14 | */ | ||
15 | List(); | ||
16 | |||
17 | /** | ||
18 | * Desconstruct a list. | ||
19 | */ | ||
20 | virtual ~List(); | ||
21 | |||
22 | /** Gets the value at a specified index. | ||
23 | *@param nIndex The index of the item to return. | ||
24 | *@returns The specified item, or NULL if the index was beyond the range | ||
25 | * of the list. | ||
26 | *@author Mike Buland | ||
27 | */ | ||
28 | virtual void *getAt( int nIndex ) = 0; | ||
29 | |||
30 | /** Append the given data to the end of the list. This increases the | ||
31 | * size of the list by one. | ||
32 | *@param pData The data to append to the list. | ||
33 | *@author Mike Buland | ||
34 | */ | ||
35 | virtual void append( void *pData ) = 0; | ||
36 | |||
37 | /** Inserts an item at the specified position in the list. The | ||
38 | * new item takes the index that you specify, and all other items | ||
39 | * are moved up one position. The size of the list is increased by | ||
40 | * one. | ||
41 | *@param pData The value to insert into the list. | ||
42 | *@param nPos Where to insert the data into the list. | ||
43 | *@author Mike Buland | ||
44 | */ | ||
45 | virtual void insertBefore( void *pData, int nPos = 0 ) = 0; | ||
46 | |||
47 | /** Determines the size of the list, in elements. | ||
48 | *@returns The size of the list. | ||
49 | *@author Mike Buland | ||
50 | */ | ||
51 | virtual int getSize( ) = 0; | ||
52 | |||
53 | /** Determines if the list is empty or not. | ||
54 | *@returns True if the list is empty, or false if the list has | ||
55 | * data in it (if the size is greater than zero). | ||
56 | *@author Mike Buland | ||
57 | */ | ||
58 | virtual bool isEmpty( ) = 0; | ||
59 | |||
60 | /** Deletes an item at the specified index and moves all other | ||
61 | * values down one index. The size of the list is decreased by one. | ||
62 | *@param nIndex The index of the item to delete. | ||
63 | *@author Mike Buland | ||
64 | */ | ||
65 | virtual void deleteAt( int nIndex ) = 0; | ||
66 | |||
67 | /** Completely empties the list, and sets the effective size to | ||
68 | * zero. | ||
69 | *@author Mike Buland | ||
70 | */ | ||
71 | virtual void empty() = 0; | ||
72 | |||
73 | /** Sets the size of the list. This can be larger or smaller | ||
74 | * than what it was previously. If larger, new blank items will | ||
75 | * be added to the end of the list. If smaller than the old list | ||
76 | * items will be deleted from the end. | ||
77 | *@param nNewSize The new size of the list. | ||
78 | *@author Mike Buland | ||
79 | */ | ||
80 | virtual void setSize( int nNewSize ) = 0; | ||
81 | |||
82 | /** Sets a member at a specified location to a new value. | ||
83 | * If the member being set is outside of the range of the | ||
84 | * current list it should be expanded. | ||
85 | *@param nIndex The zero-based index of the item to change. | ||
86 | *@param pData The new value for that index. | ||
87 | *@author Mike Buland | ||
88 | */ | ||
89 | virtual void setAt( int nIndex, void *pData ) = 0; | ||
90 | |||
91 | /** Makes the List work like an array. Just say listObj[2] to get | ||
92 | * the third element. | ||
93 | *@param nIndex The index to access in the list. | ||
94 | *@returns A pointer to the data at element index. | ||
95 | *@author Mike Buland | ||
96 | */ | ||
97 | void *operator[]( int nIndex ) { return getAt( nIndex ); }; | ||
98 | }; | ||
99 | |||
100 | #endif | ||
101 | |||
diff --git a/src/old/md5.cpp b/src/old/md5.cpp new file mode 100644 index 0000000..c0cacdd --- /dev/null +++ b/src/old/md5.cpp | |||
@@ -0,0 +1,190 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | #include "md5.h" | ||
5 | |||
6 | // This is a fun macro that tells us where the length char goes after the data | ||
7 | // section in the padded data segment. It's short for OBfuscation LOCaction. | ||
8 | #define OBLOC(len) ((((len + 64) >> 9) << 4) + 14) | ||
9 | // This performs a wrapping bitwise shift, kinda' fun! | ||
10 | |||
11 | #define bit_roll( num, cnt ) \ | ||
12 | (((num) << (cnt)) | (((num) >> (32 - (cnt))) & ~(-1<<(cnt)))) | ||
13 | |||
14 | //#define md5_cmn( q, a, b, x, s, t ) (bit_roll((a + q + x + t), s) + b) | ||
15 | |||
16 | // The following are handy wrappers for the cmn function | ||
17 | #define md5_ff( a, b, c, d, x, s, t ) \ | ||
18 | (md5_cmn((b & c) | ((~b) & d), a, b, x, s, t)) | ||
19 | |||
20 | #define md5_gg( a, b, c, d, x, s, t ) \ | ||
21 | (md5_cmn((b & d) | (c & (~d)), a, b, x, s, t)) | ||
22 | |||
23 | #define md5_hh( a, b, c, d, x, s, t ) \ | ||
24 | (md5_cmn(b ^ c ^ d, a, b, x, s, t)) | ||
25 | |||
26 | #define md5_ii( a, b, c, d, x, s, t ) \ | ||
27 | (md5_cmn(c ^ (b | (~d)), a, b, x, s, t)) | ||
28 | |||
29 | inline long md5_cmn( long q, long a, long b, long x, long s, long t ) | ||
30 | { | ||
31 | return bit_roll((a + q + x + t), s) + b; | ||
32 | } | ||
33 | |||
34 | md5::md5() | ||
35 | { | ||
36 | } | ||
37 | |||
38 | md5::~md5() | ||
39 | { | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | * Calculate the MD5 of an array of little-endian words, and a bit length | ||
44 | */ | ||
45 | void md5::core_md5( long *x, long len, md5sum *output ) | ||
46 | { | ||
47 | long a = 1732584193, olda; | ||
48 | long b = -271733879, oldb; | ||
49 | long c = -1732584194, oldc; | ||
50 | long d = 271733878, oldd; | ||
51 | |||
52 | for( long i = 0; i < len; i += 16 ) | ||
53 | { | ||
54 | olda = a; | ||
55 | oldb = b; | ||
56 | oldc = c; | ||
57 | oldd = d; | ||
58 | |||
59 | a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); | ||
60 | d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); | ||
61 | c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); | ||
62 | b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); | ||
63 | a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); | ||
64 | d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); | ||
65 | c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); | ||
66 | b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); | ||
67 | a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); | ||
68 | d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); | ||
69 | c = md5_ff(c, d, a, b, x[i+10], 17, -42063); | ||
70 | b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); | ||
71 | a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); | ||
72 | d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); | ||
73 | c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); | ||
74 | b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); | ||
75 | |||
76 | a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); | ||
77 | d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); | ||
78 | c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); | ||
79 | b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); | ||
80 | a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); | ||
81 | d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); | ||
82 | c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); | ||
83 | b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); | ||
84 | a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); | ||
85 | d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); | ||
86 | c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); | ||
87 | b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); | ||
88 | a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); | ||
89 | d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); | ||
90 | c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); | ||
91 | b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); | ||
92 | |||
93 | a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); | ||
94 | d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); | ||
95 | c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); | ||
96 | b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); | ||
97 | a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); | ||
98 | d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); | ||
99 | c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); | ||
100 | b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); | ||
101 | a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); | ||
102 | d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); | ||
103 | c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); | ||
104 | b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); | ||
105 | a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); | ||
106 | d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); | ||
107 | c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); | ||
108 | b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); | ||
109 | |||
110 | a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); | ||
111 | d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); | ||
112 | c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); | ||
113 | b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); | ||
114 | a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); | ||
115 | d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); | ||
116 | c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); | ||
117 | b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); | ||
118 | a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); | ||
119 | d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); | ||
120 | c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); | ||
121 | b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); | ||
122 | a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); | ||
123 | d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); | ||
124 | c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); | ||
125 | b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); | ||
126 | |||
127 | a = a + olda; | ||
128 | b = b + oldb; | ||
129 | c = c + oldc; | ||
130 | d = d + oldd; | ||
131 | } | ||
132 | |||
133 | output->data[0] = a; | ||
134 | output->data[1] = b; | ||
135 | output->data[2] = c; | ||
136 | output->data[3] = d; | ||
137 | delete[] x; | ||
138 | } | ||
139 | |||
140 | long *md5::c2l( const char *str, long len, long *nNewLen ) | ||
141 | { | ||
142 | long len8 = len*8; | ||
143 | long mlen = OBLOC( len8 ); | ||
144 | long flen = (((mlen/16)+((mlen%16)?(1):(0))))*16; | ||
145 | long *aBin = new long[flen]; | ||
146 | memset( aBin, 0, flen*4 ); | ||
147 | |||
148 | for( long i = 0; i < len8; i+=8 ) | ||
149 | { | ||
150 | aBin[i>>5] |= ((long)str[i/8]) << (i%32); | ||
151 | } | ||
152 | |||
153 | aBin[len8 >> 5] |= 0x80 << ((len8) % 32); | ||
154 | aBin[OBLOC( len8 )] = len8; | ||
155 | |||
156 | (*nNewLen) = flen; | ||
157 | |||
158 | return aBin; | ||
159 | } | ||
160 | |||
161 | void md5::l2hexstr( long *binarray, char *str ) | ||
162 | { | ||
163 | static const char hex_tab[] = {"0123456789abcdef"}; | ||
164 | //static char str[33]; | ||
165 | |||
166 | int k = 0; | ||
167 | for( int i = 0; i < 16; i++) | ||
168 | { | ||
169 | str[k++] = hex_tab[(binarray[i>>2] >> ((i%4)*8+4)) & 0xF]; | ||
170 | str[k++] = hex_tab[(binarray[i>>2] >> ((i%4)*8 )) & 0xF]; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | void md5::sumString( md5sum *pSum, const char *sStr ) | ||
175 | { | ||
176 | sumData( pSum, sStr, strlen( sStr ) ); | ||
177 | } | ||
178 | |||
179 | void md5::sumData( md5sum *pSum, const char *aData, long nLen ) | ||
180 | { | ||
181 | long nNewLen; | ||
182 | long *aOb = c2l( aData, nLen, &nNewLen ); | ||
183 | core_md5( aOb, nNewLen, pSum ); | ||
184 | } | ||
185 | |||
186 | void md5::sumToHex( md5sum *pSum, char *sHex ) | ||
187 | { | ||
188 | l2hexstr( pSum->data, sHex ); | ||
189 | } | ||
190 | |||
diff --git a/src/old/md5.h b/src/old/md5.h new file mode 100644 index 0000000..7f77d83 --- /dev/null +++ b/src/old/md5.h | |||
@@ -0,0 +1,81 @@ | |||
1 | #ifndef MD5_H | ||
2 | #define MD5_H | ||
3 | |||
4 | /** | ||
5 | * Used to store an MD5 sum in a handy container. | ||
6 | */ | ||
7 | typedef struct | ||
8 | { | ||
9 | /** The actual data-storage for an MD5 sum. */ | ||
10 | long data[4]; | ||
11 | } md5sum; | ||
12 | |||
13 | /** | ||
14 | * Class for easily calculating MD5 sums of just about any data. | ||
15 | *@author Mike Buland | ||
16 | */ | ||
17 | class md5 | ||
18 | { | ||
19 | public: | ||
20 | /** Build an MD5 sum builder. */ | ||
21 | md5(); | ||
22 | |||
23 | /** Deconstruct */ | ||
24 | virtual ~md5(); | ||
25 | |||
26 | /** | ||
27 | * Create a sum of a standard c string, null terminated. This is probably | ||
28 | * the easiest function to use. | ||
29 | *@param pSum The MD5 sum structure to fill up. | ||
30 | *@param sStr The null-terminated string to turn into an MD5 sum. | ||
31 | */ | ||
32 | void sumString( md5sum *pSum, const char *sStr ); | ||
33 | |||
34 | /** | ||
35 | * Create a sum of an array of arbitrary data. This is the most handy for | ||
36 | * dealing with files and so on. | ||
37 | *@param pSum The MD5 sum structure to fill up. | ||
38 | *@param aData A pointer to the base of the data to sum. | ||
39 | *@param nLen The number of bytes to use in the sum. | ||
40 | */ | ||
41 | void sumData( md5sum *pSum, const char *aData, long nLen ); | ||
42 | |||
43 | /** | ||
44 | * Convert an md5sum to standard hex representation. Make sure that sHex | ||
45 | * contains at least 17 characters of space. | ||
46 | *@param pSum The sum structure to convert to hex. | ||
47 | *@param sHex The string to store the hex value in. | ||
48 | */ | ||
49 | void sumToHex( md5sum *pSum, char *sHex ); | ||
50 | |||
51 | private: | ||
52 | /** | ||
53 | * Do the bulk of the work of the md5 algorithm. | ||
54 | *@param x I'm not sure. I'll need to look it up. | ||
55 | *@param len The length of the data. | ||
56 | *@param output The sum structure to put the output in. | ||
57 | */ | ||
58 | void core_md5( long *x, long len, md5sum *output ); | ||
59 | |||
60 | /** | ||
61 | * Convert an array of charaters to an array of longs in a very crafty way. | ||
62 | * This also applies standard MD5 obfuscation to the resulting array, and | ||
63 | * makes it fit within MD5 size constraints. | ||
64 | *@param str The data to convert. | ||
65 | *@param len The length of the data. | ||
66 | *@param nNewLen A pointer to a variable that will hold the new length of | ||
67 | * the resulting array of longs. | ||
68 | *@returns The newly obfuscated and resized long array. | ||
69 | */ | ||
70 | long *c2l( const char *str, long len, long *nNewLen ); | ||
71 | |||
72 | /** | ||
73 | * Backend helper to convert an array of longs into a hex string. | ||
74 | *@param binarray The binary data to convert. | ||
75 | *@param str The string to store the hex string in. | ||
76 | */ | ||
77 | void l2hexstr( long *binarray, char *str ); | ||
78 | |||
79 | }; | ||
80 | |||
81 | #endif | ||
diff --git a/src/old/multilog.cpp b/src/old/multilog.cpp new file mode 100644 index 0000000..143ee89 --- /dev/null +++ b/src/old/multilog.cpp | |||
@@ -0,0 +1,102 @@ | |||
1 | #include "multilog.h" | ||
2 | #include <stdio.h> | ||
3 | #include <time.h> | ||
4 | #include <string.h> | ||
5 | #include <stdlib.h> | ||
6 | |||
7 | #include "multilogchannel.h" | ||
8 | |||
9 | MultiLog::MultiLog() | ||
10 | { | ||
11 | lChannel = new LinkedList(); | ||
12 | rEntry = new RingList( 150 ); | ||
13 | nEntriesLost = 0; | ||
14 | } | ||
15 | |||
16 | MultiLog::~MultiLog() | ||
17 | { | ||
18 | int nMax = lChannel->getSize(); | ||
19 | for( int j = 0; j < nMax; j++ ) | ||
20 | { | ||
21 | ((MultiLogChannel *)lChannel->getAt(j))->closeLog(); | ||
22 | delete ((MultiLogChannel *)lChannel->getAt(j)); | ||
23 | } | ||
24 | delete lChannel; | ||
25 | |||
26 | for( int j = 0; j < rEntry->getSize(); j++ ) | ||
27 | { | ||
28 | delete (LogEntry *)rEntry->getAt( j ); | ||
29 | } | ||
30 | delete rEntry; | ||
31 | } | ||
32 | /* | ||
33 | void MultiLog::Log( int nLevel, const char *lpFormat, ...) | ||
34 | { | ||
35 | switch( nLevel ) | ||
36 | { | ||
37 | default: | ||
38 | break; | ||
39 | } | ||
40 | va_list ap; | ||
41 | va_start(ap, lpFormat); | ||
42 | |||
43 | vprintf( lpFormat, ap ); | ||
44 | |||
45 | va_end(ap); | ||
46 | }*/ | ||
47 | |||
48 | void MultiLog::DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...) | ||
49 | { | ||
50 | LogEntry *e = new LogEntry(); | ||
51 | |||
52 | va_list ap; | ||
53 | va_start(ap, lpFormat); | ||
54 | char *text; | ||
55 | vasprintf( &text, lpFormat, ap ); | ||
56 | va_end(ap); | ||
57 | |||
58 | time( &e->xTime ); | ||
59 | e->nLevel = nLevel; | ||
60 | e->nLine = nLine; | ||
61 | e->lpFile = new char[strlen(lpFile)+1]; | ||
62 | strcpy( e->lpFile, lpFile ); | ||
63 | e->lpText = new char[strlen(text)+1]; | ||
64 | strcpy( e->lpText, text ); | ||
65 | free( text ); | ||
66 | |||
67 | append( e ); | ||
68 | } | ||
69 | |||
70 | void MultiLog::append( LogEntry *pEntry ) | ||
71 | { | ||
72 | rEntry->append( pEntry ); | ||
73 | if( rEntry->getPushBuf() ) | ||
74 | { | ||
75 | delete (LogEntry *)rEntry->getPushBuf(); | ||
76 | nEntriesLost++; | ||
77 | } | ||
78 | |||
79 | for( int j = 0; j < lChannel->getSize(); j++ ) | ||
80 | { | ||
81 | ((MultiLogChannel *)lChannel->getAt( j ))->append( pEntry ); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | void MultiLog::addChannel( MultiLogChannel *pChannel ) | ||
86 | { | ||
87 | lChannel->append( pChannel ); | ||
88 | |||
89 | pChannel->openLog(); | ||
90 | |||
91 | for( int j = 0; j < rEntry->getSize(); j++ ) | ||
92 | { | ||
93 | pChannel->append( (LogEntry *)rEntry->getAt( j ) ); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | MultiLog::LogEntry::~LogEntry() | ||
98 | { | ||
99 | delete[] lpFile; | ||
100 | delete[] lpText; | ||
101 | } | ||
102 | |||
diff --git a/src/old/multilog.h b/src/old/multilog.h new file mode 100644 index 0000000..692095a --- /dev/null +++ b/src/old/multilog.h | |||
@@ -0,0 +1,130 @@ | |||
1 | #ifndef MULTILOG_H | ||
2 | #define MULTILOG_H | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include <stdarg.h> | ||
6 | #include <time.h> | ||
7 | |||
8 | #include "ringlist.h" | ||
9 | #include "linkedlist.h" | ||
10 | #include "singleton.h" | ||
11 | |||
12 | /** | ||
13 | * Calls the DetailLog function but includes pre-processor macros to fill in | ||
14 | * most of the fields for you. This makes your life a lot easier, and makes the | ||
15 | * log useful for system debugging as well as just letting people know what's | ||
16 | * going on. | ||
17 | *@param LEVEL The log level, comes from an enum in the MultiLog class. | ||
18 | *@param FORMAT The text to store in the log, using printf style formatting. | ||
19 | *@param ... Parameters to help format the text in the FROMAT param. | ||
20 | */ | ||
21 | #define LineLog( LEVEL, FORMAT, ...) DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ ) | ||
22 | |||
23 | #define MultiLineLog( LEVEL, FORMAT, ...) MultiLog::getInstance().DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ ) | ||
24 | |||
25 | /** MultiLog keeps track of logfile info in a myriad of varieties, and is | ||
26 | * easily configurable between them all. It allows output to the standard | ||
27 | * output, error output, files, networks, and streams, which includes memory | ||
28 | * buffers. | ||
29 | * MultiLog uses the singleton pattern to keep only a single instance of | ||
30 | * the log. Instead of instantiating a new copy, call the getLog method. | ||
31 | *@author Mike Buland | ||
32 | */ | ||
33 | class MultiLog : public Singleton<MultiLog> | ||
34 | { | ||
35 | friend class Singleton<MultiLog>; | ||
36 | public: | ||
37 | /** | ||
38 | * Keeps track of a single log entry, in a standard format, that can be | ||
39 | * processed by any MultiLogChannel derrived class. | ||
40 | *@author Mike Buland | ||
41 | */ | ||
42 | typedef struct LogEntry | ||
43 | { | ||
44 | /** Safely delete a log entry. */ | ||
45 | virtual ~LogEntry(); | ||
46 | time_t xTime; /**< The time the log entry was made. */ | ||
47 | int nLevel; /**< The log-level of the entry. */ | ||
48 | char *lpFile; /**< The name of the file this entry came from. */ | ||
49 | int nLine; /**< The line number that this log came from. */ | ||
50 | char *lpText; /**< The text content of this log entry. */ | ||
51 | } LogEntry; | ||
52 | |||
53 | protected: | ||
54 | /** | ||
55 | * Private constructor, this ensures that this is a singleton. | ||
56 | */ | ||
57 | MultiLog(); | ||
58 | |||
59 | /** | ||
60 | * Destroy the multilog. | ||
61 | */ | ||
62 | virtual ~MultiLog(); | ||
63 | |||
64 | /** | ||
65 | * Append a new logentry to the log list, possibly pushing an old entry off. | ||
66 | *@param pEntry The new entry to append. | ||
67 | */ | ||
68 | void append( LogEntry *pEntry ); | ||
69 | |||
70 | /** | ||
71 | * The actual log entry storage mechanism. | ||
72 | */ | ||
73 | RingList *rEntry; | ||
74 | |||
75 | /** | ||
76 | * The number of entries that have rolled off the end of the RingList. | ||
77 | */ | ||
78 | unsigned long nEntriesLost; | ||
79 | |||
80 | /** | ||
81 | * A list of all channels that are registered with the MultiLog. | ||
82 | */ | ||
83 | LinkedList *lChannel; | ||
84 | |||
85 | public: | ||
86 | |||
87 | /** Sends info to the logfile. | ||
88 | *@param nLevel The type of data being logged (error, info, etc.) | ||
89 | *@param lpFormat The data to send to the log. | ||
90 | *@author Mike Buland | ||
91 | */ | ||
92 | //void Log( int nLevel, const char *lpFormat, ...); | ||
93 | |||
94 | /** Sends info to the logfile with extra information, including the files | ||
95 | * that it was called from and the line in the code. Besides that, it's | ||
96 | * exactly the same as Log. Please use the LineLog macro to make DetailLog | ||
97 | * really easy to use. It operates exacly like Log, but inserts the | ||
98 | * builtin macros as the lpFile and nLine parameters. | ||
99 | *@param nLevel The type of data being logged (error, info, etc.) | ||
100 | *@param lpFile The name of the file that called the log function. | ||
101 | *@param nLine The line in the file that this log function was called from. | ||
102 | *@param lpFunction The name of the function that called the log function. | ||
103 | *@param lpFormat The data to send to the log. | ||
104 | *@author Mike Buland | ||
105 | */ | ||
106 | void DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...); | ||
107 | |||
108 | /** | ||
109 | * Adds a logging channel to the MultiLog channel chain. Every added | ||
110 | * channel will automatically receive a complete log of everything that | ||
111 | * happened before the channel was added as well as all future messages. | ||
112 | *@param pChannel A pointer to the pre-contructed channel object to add. | ||
113 | */ | ||
114 | void addChannel( class MultiLogChannel *pChannel ); | ||
115 | |||
116 | /** The various pre-defined levels available to use when logging. | ||
117 | * The person logging can make up their own, just make sure to remember | ||
118 | * which value is which (all levels are integers). | ||
119 | *@author Mike Buland | ||
120 | */ | ||
121 | enum Levels | ||
122 | { | ||
123 | LError, | ||
124 | LWarning, | ||
125 | LInfo, | ||
126 | LStatus | ||
127 | }; | ||
128 | }; | ||
129 | |||
130 | #endif | ||
diff --git a/src/old/multilogchannel.cpp b/src/old/multilogchannel.cpp new file mode 100644 index 0000000..ee4c9bf --- /dev/null +++ b/src/old/multilogchannel.cpp | |||
@@ -0,0 +1,13 @@ | |||
1 | // | ||
2 | // C++ Implementation: multilogchannel | ||
3 | // | ||
4 | // Description: | ||
5 | // | ||
6 | // | ||
7 | // Author: Mike Buland <eichlan@yf-soft.com>, (C) 2005 | ||
8 | // | ||
9 | // Copyright: See COPYING file that comes with this distribution | ||
10 | // | ||
11 | // | ||
12 | #include "multilogchannel.h" | ||
13 | |||
diff --git a/src/old/multilogchannel.h b/src/old/multilogchannel.h new file mode 100644 index 0000000..d891a65 --- /dev/null +++ b/src/old/multilogchannel.h | |||
@@ -0,0 +1,46 @@ | |||
1 | #ifndef MULTILOGCHANNEL_H | ||
2 | #define MULTILOGCHANNEL_H | ||
3 | |||
4 | #include "multilog.h" | ||
5 | |||
6 | /** | ||
7 | * The baseclass for any MultiLog output channel. Any class that implements | ||
8 | * all of these functions can be put in the log chain and will be sent | ||
9 | * messages from active MultiLoggers. | ||
10 | *@author Mike Buland | ||
11 | */ | ||
12 | class MultiLogChannel | ||
13 | { | ||
14 | public: | ||
15 | /** | ||
16 | * Deconstruct a MultiLogChannel. | ||
17 | */ | ||
18 | virtual ~MultiLogChannel() {}; | ||
19 | |||
20 | /** | ||
21 | * Should perform any operations that need to take place in order to start | ||
22 | * the output of data into this channel. This will be called once by the | ||
23 | * MultiLog when the MultiLogChannel is registered. | ||
24 | *@returns True means that everything can go as planned. False means that | ||
25 | * the MultiLog should remove this channel from the list and delete it. | ||
26 | */ | ||
27 | virtual bool openLog() = 0; | ||
28 | |||
29 | /** | ||
30 | * Should append a log entry to the long, by whatever means are necesarry. | ||
31 | *@param pEntry The LogEntry to append. | ||
32 | *@returns True means that everything can go as planned. False means that | ||
33 | * the MultiLog should remove this channel from the list and delete it. | ||
34 | */ | ||
35 | virtual bool append( MultiLog::LogEntry *pEntry ) = 0; | ||
36 | |||
37 | /** | ||
38 | * Should perform any operations that need to take place in order to safely | ||
39 | * close and cleanup the log. | ||
40 | *@returns True means that everything can go as planned. False means that | ||
41 | * the MultiLog should remove this channel from the list and delete it. | ||
42 | */ | ||
43 | virtual bool closeLog() = 0; | ||
44 | }; | ||
45 | |||
46 | #endif | ||
diff --git a/src/old/multilogtext.cpp b/src/old/multilogtext.cpp new file mode 100644 index 0000000..4337cc9 --- /dev/null +++ b/src/old/multilogtext.cpp | |||
@@ -0,0 +1,188 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <fcntl.h> | ||
4 | #include <unistd.h> | ||
5 | #include <time.h> | ||
6 | #include <string.h> | ||
7 | #include "multilogtext.h" | ||
8 | /* | ||
9 | bool fileexists( const char *sPath ) | ||
10 | { | ||
11 | int nFileDesc = open( sPath, O_RDONLY ); | ||
12 | if( nFileDesc < 0 ) | ||
13 | { | ||
14 | return false; | ||
15 | } | ||
16 | else | ||
17 | { | ||
18 | close( nFileDesc ); | ||
19 | return true; | ||
20 | } | ||
21 | }*/ | ||
22 | |||
23 | MultiLogText::MultiLogText( const char *sFileName, const char *lpFormat, bool bRotateLog, int nMaxLogs ) | ||
24 | { | ||
25 | this->lpFormat = NULL; | ||
26 | /* | ||
27 | if( bRotateLog ) | ||
28 | { | ||
29 | if( fileexists( sFileName ) == false ) | ||
30 | { | ||
31 | return; | ||
32 | } | ||
33 | |||
34 | int nLen = strlen( sFileName ); | ||
35 | char *buf = new char[nLen+6]; | ||
36 | sprintf( buf, "%s.", sFileName ); | ||
37 | |||
38 | for( int j = 1; j < nMaxLogs; j++ ) | ||
39 | { | ||
40 | sprintf( &buf[nLen+1], "%d", j ); | ||
41 | if( !fileexists( buf ) ) | ||
42 | { | ||
43 | rename( sFileName, buf ); | ||
44 | break; | ||
45 | } | ||
46 | } | ||
47 | }*/ | ||
48 | |||
49 | nFD = open( sFileName, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ); | ||
50 | setLogFormat( lpFormat ); | ||
51 | } | ||
52 | |||
53 | MultiLogText::MultiLogText( int nFileDesc, const char *lpFormat ) | ||
54 | { | ||
55 | this->lpFormat = NULL; | ||
56 | nFD = nFileDesc; | ||
57 | setLogFormat( lpFormat ); | ||
58 | } | ||
59 | |||
60 | MultiLogText::~MultiLogText() | ||
61 | { | ||
62 | if( nFD != -1 ) | ||
63 | { | ||
64 | close( nFD ); | ||
65 | } | ||
66 | |||
67 | delete[] lpFormat; | ||
68 | } | ||
69 | |||
70 | bool MultiLogText::setLogFormat( const char *lpFormat ) | ||
71 | { | ||
72 | char buf[200]; | ||
73 | int k = 0; | ||
74 | static char fmts[10][4]={ | ||
75 | {'y', 'd', '0', '1'}, | ||
76 | {'m', 'd', '0', '2'}, | ||
77 | {'d', 'd', '0', '3'}, | ||
78 | {'h', 'd', '0', '4'}, | ||
79 | {'M', 'd', '0', '5'}, | ||
80 | {'s', 'd', '0', '6'}, | ||
81 | {'l', 'd', '0', '7'}, | ||
82 | {'f', 's', '0', '8'}, | ||
83 | {'L', 'd', '0', '9'}, | ||
84 | {'t', 's', '1', '0'}, | ||
85 | }; | ||
86 | |||
87 | for( int j = 0; lpFormat[j] != '\0'; j++ ) | ||
88 | { | ||
89 | if( lpFormat[j] == '%' ) | ||
90 | { | ||
91 | buf[k++] = '%'; | ||
92 | int nPlace = k++; | ||
93 | k++; | ||
94 | buf[k++] = '$'; | ||
95 | bool bDone = false; | ||
96 | for( j++; bDone == false; j++ ) | ||
97 | { | ||
98 | int l; | ||
99 | for( l = 0; l < 10; l++ ) | ||
100 | { | ||
101 | if( lpFormat[j] == fmts[l][0] ) | ||
102 | { | ||
103 | buf[nPlace] = fmts[l][2]; | ||
104 | buf[nPlace+1] = fmts[l][3]; | ||
105 | buf[k++] = fmts[l][1]; | ||
106 | bDone = true; | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | if( l == 10 ) | ||
111 | { | ||
112 | buf[k++] = lpFormat[j]; | ||
113 | } | ||
114 | } | ||
115 | j--; | ||
116 | } | ||
117 | else | ||
118 | { | ||
119 | buf[k++] = lpFormat[j]; | ||
120 | } | ||
121 | } | ||
122 | buf[k++] = '\n'; | ||
123 | buf[k] = '\0'; | ||
124 | |||
125 | if( this->lpFormat != NULL ) | ||
126 | { | ||
127 | delete[] this->lpFormat; | ||
128 | } | ||
129 | this->lpFormat = new char[k+1]; | ||
130 | strcpy( this->lpFormat, buf ); | ||
131 | |||
132 | return true; | ||
133 | } | ||
134 | |||
135 | bool MultiLogText::openLog() | ||
136 | { | ||
137 | if( nFD == -1 ) | ||
138 | { | ||
139 | return false; | ||
140 | } | ||
141 | return true; | ||
142 | } | ||
143 | |||
144 | bool MultiLogText::append( MultiLog::LogEntry *pEntry ) | ||
145 | { | ||
146 | if( nFD == -1 ) | ||
147 | { | ||
148 | return false; | ||
149 | } | ||
150 | |||
151 | char *line = NULL; | ||
152 | struct tm *pTime; | ||
153 | pTime = localtime( &pEntry->xTime ); | ||
154 | asprintf( | ||
155 | &line, | ||
156 | lpFormat, | ||
157 | pTime->tm_year+1900, | ||
158 | pTime->tm_mon+1, | ||
159 | pTime->tm_mday, | ||
160 | pTime->tm_hour, | ||
161 | pTime->tm_min, | ||
162 | pTime->tm_sec, | ||
163 | pEntry->nLevel, | ||
164 | pEntry->lpFile, | ||
165 | pEntry->nLine, | ||
166 | pEntry->lpText | ||
167 | ); | ||
168 | write( nFD, line, strlen(line) ); | ||
169 | free( line ); | ||
170 | |||
171 | return true; | ||
172 | } | ||
173 | |||
174 | bool MultiLogText::closeLog() | ||
175 | { | ||
176 | if( nFD == -1 ) | ||
177 | { | ||
178 | return false; | ||
179 | } | ||
180 | // Don't close it if it's sdtout or errorout | ||
181 | if( nFD > 2 ) | ||
182 | { | ||
183 | close( nFD ); | ||
184 | } | ||
185 | nFD = -1; | ||
186 | return true; | ||
187 | } | ||
188 | |||
diff --git a/src/old/multilogtext.h b/src/old/multilogtext.h new file mode 100644 index 0000000..197aef1 --- /dev/null +++ b/src/old/multilogtext.h | |||
@@ -0,0 +1,70 @@ | |||
1 | #ifndef MULTILOGTEXT_H | ||
2 | #define MULTILOGTEXT_H | ||
3 | |||
4 | #include "multilogchannel.h" | ||
5 | |||
6 | /** | ||
7 | * Simple MultiLogChannel that takes the logdata, formats it textually, and | ||
8 | * writes it to a text device, either a file or the screen, yay! This takes | ||
9 | * the place of the old standard logging facility. | ||
10 | * The entries in the format follow the standard printf % style, and are as | ||
11 | * follows: | ||
12 | * <ul> | ||
13 | * <li>%y - current year</li> | ||
14 | * <li>%m - current month</li> | ||
15 | * <li>%d - current day</li> | ||
16 | * <li>%h - current hour (24-hour format)</li> | ||
17 | * <li>%M - current minute</li> | ||
18 | * <li>%s - current seccond</li> | ||
19 | * <li>%l - Loglevel (numerical)</li> | ||
20 | * <li>%f - Filename</li> | ||
21 | * <li>%L - Line number</li> | ||
22 | * <li>%t - Full text of the log entry</li> | ||
23 | * </ul> | ||
24 | *@author Mike Buland | ||
25 | */ | ||
26 | class MultiLogText : public MultiLogChannel | ||
27 | { | ||
28 | public: | ||
29 | /** | ||
30 | * Construct a MultiLogText object around a specific filename and format. | ||
31 | * The file named by sFileName will be opened for writting in text+append | ||
32 | * mode. No existing data will be destroyed. | ||
33 | *@param sFileName The file to output log-data to. | ||
34 | *@param lpFormat The format using the above specifications to be used for | ||
35 | * every log entry. | ||
36 | */ | ||
37 | MultiLogText( const char *sFileName, const char *lpFormat, bool bRotateLog=false, int nMaxLogs=0 ); | ||
38 | |||
39 | /** | ||
40 | * Construct a MultiLogText object around a specific file and format. | ||
41 | * The file descriptor passed in should describe an already opened and set- | ||
42 | * up file or device. This could easily be a socket or stdout or stderr. | ||
43 | *@param nFileDesc The already opened descriptor to send data to. | ||
44 | *@param lpFormat The format using the above specifications to be used for | ||
45 | * every log entry. | ||
46 | */ | ||
47 | MultiLogText( int nFileDesc, const char *lpFormat ); | ||
48 | |||
49 | /** | ||
50 | * Destroy the object. | ||
51 | */ | ||
52 | virtual ~MultiLogText(); | ||
53 | |||
54 | bool openLog(); | ||
55 | bool append( MultiLog::LogEntry *pEntry ); | ||
56 | bool closeLog(); | ||
57 | |||
58 | /** | ||
59 | * Change the log format on the fly. | ||
60 | *@param lpFormat The new format to use for all future log entries. | ||
61 | *@returns True if everything was fine, false for catastrophic failure. | ||
62 | */ | ||
63 | bool setLogFormat( const char *lpFormat ); | ||
64 | |||
65 | private: | ||
66 | int nFD; /**< The file descriptor we're writing to. */ | ||
67 | char *lpFormat; /**< The format that we're using, converted for printf. */ | ||
68 | }; | ||
69 | |||
70 | #endif | ||
diff --git a/src/old/ordhash.cpp b/src/old/ordhash.cpp new file mode 100644 index 0000000..77cbd61 --- /dev/null +++ b/src/old/ordhash.cpp | |||
@@ -0,0 +1 @@ | |||
#include "ordhash.h" | |||
diff --git a/src/old/ordhash.h b/src/old/ordhash.h new file mode 100644 index 0000000..e946f95 --- /dev/null +++ b/src/old/ordhash.h | |||
@@ -0,0 +1,104 @@ | |||
1 | #ifndef ORD_HASH_H | ||
2 | #define ORD_HASH_H | ||
3 | |||
4 | #include "hash.h" | ||
5 | #include "tqsort.h" | ||
6 | |||
7 | template<typename key, typename value, typename cmpfnc, typename sizecalc = __calcNextTSize_fast, typename keyalloc = std::allocator<key>, typename valuealloc = std::allocator<value>, typename challoc = std::allocator<uint32_t> > | ||
8 | class OrdHash : public Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> | ||
9 | { | ||
10 | public: | ||
11 | OrdHash() : | ||
12 | bSorted( false ), | ||
13 | aData( NULL ) | ||
14 | { | ||
15 | } | ||
16 | |||
17 | virtual ~OrdHash() | ||
18 | { | ||
19 | } | ||
20 | |||
21 | protected: | ||
22 | virtual void invalidate() | ||
23 | { | ||
24 | bSorted = false; | ||
25 | delete[] aData; | ||
26 | aData = NULL; | ||
27 | } | ||
28 | |||
29 | virtual void onInsert() | ||
30 | { | ||
31 | invalidate(); | ||
32 | } | ||
33 | |||
34 | virtual void onUpdate() | ||
35 | { | ||
36 | invalidate(); | ||
37 | } | ||
38 | |||
39 | virtual void onDelete() | ||
40 | { | ||
41 | invalidate(); | ||
42 | } | ||
43 | |||
44 | virtual void onReHash() | ||
45 | { | ||
46 | invalidate(); | ||
47 | } | ||
48 | |||
49 | virtual std::pair<key,value> getAtPos( uint32_t nPos ) | ||
50 | { | ||
51 | return Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>::getAtPos( aData[nPos].nIndex ); | ||
52 | } | ||
53 | |||
54 | virtual void buildIndex() | ||
55 | { | ||
56 | aData = new struct ind[this->nFilled]; | ||
57 | uint32_t k = 0; | ||
58 | for( uint32_t j = 0; j < this->nCapacity; j++ ) | ||
59 | { | ||
60 | if( this->isFilled( j ) ) | ||
61 | { | ||
62 | if( !this->isDeleted( j ) ) | ||
63 | { | ||
64 | aData[k].pVal = &(this->aValues[j]); | ||
65 | aData[k].nIndex = j; | ||
66 | k++; | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | |||
71 | tqsort<typename OrdHash<key, value, cmpfnc, sizecalc, keyalloc, valuealloc, challoc>::ind, cmpfnc, value **>( aData, this->nFilled ); | ||
72 | |||
73 | bSorted = true; | ||
74 | } | ||
75 | |||
76 | virtual uint32_t getFirstPos( bool &bFinished ) | ||
77 | { | ||
78 | if( bSorted == false ) | ||
79 | buildIndex(); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | virtual uint32_t getNextPos( uint32_t nPos, bool &bFinished ) | ||
85 | { | ||
86 | if( nPos+1 >= this->nFilled ) | ||
87 | { | ||
88 | bFinished = true; | ||
89 | return 0; | ||
90 | } | ||
91 | return ++nPos; | ||
92 | } | ||
93 | public: | ||
94 | typedef struct ind | ||
95 | { | ||
96 | value *pVal; | ||
97 | uint32_t nIndex; | ||
98 | } ind; | ||
99 | private: | ||
100 | bool bSorted; | ||
101 | ind *aData; | ||
102 | }; | ||
103 | |||
104 | #endif | ||
diff --git a/src/old/paramproc.cpp b/src/old/paramproc.cpp new file mode 100644 index 0000000..a352e66 --- /dev/null +++ b/src/old/paramproc.cpp | |||
@@ -0,0 +1,514 @@ | |||
1 | #include "paramproc.h" | ||
2 | #include <stdio.h> | ||
3 | |||
4 | #define ptrtype( iitype, iiname ) \ | ||
5 | ParamProc::ParamPtr::ParamPtr( iitype *iiname ) : \ | ||
6 | type( vt ##iiname ) { val.iiname = iiname; } | ||
7 | |||
8 | ParamProc::ParamPtr::ParamPtr() | ||
9 | { | ||
10 | val.str = NULL; | ||
11 | type = vtunset; | ||
12 | } | ||
13 | |||
14 | ptrtype( std::string, str ); | ||
15 | ptrtype( uint64_t, uint64 ); | ||
16 | ptrtype( uint32_t, uint32 ); | ||
17 | ptrtype( uint16_t, uint16 ); | ||
18 | ptrtype( uint8_t, uint8 ); | ||
19 | ptrtype( int64_t, int64 ); | ||
20 | ptrtype( int32_t, int32 ); | ||
21 | ptrtype( int16_t, int16 ); | ||
22 | ptrtype( int8_t, int8 ); | ||
23 | ptrtype( float, float32 ); | ||
24 | ptrtype( double, float64 ); | ||
25 | ptrtype( long double, float96 ); | ||
26 | ptrtype( bool, bln ); | ||
27 | |||
28 | ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( ParamProc::ParamPtr &ptr ) | ||
29 | { | ||
30 | val = ptr.val; | ||
31 | type = ptr.type; | ||
32 | |||
33 | return *this; | ||
34 | } | ||
35 | |||
36 | bool ParamProc::ParamPtr::isSet() | ||
37 | { | ||
38 | return type != vtunset; | ||
39 | } | ||
40 | |||
41 | ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( const char *str ) | ||
42 | { | ||
43 | if( !isSet() ) return *this; | ||
44 | switch( type ) | ||
45 | { | ||
46 | case vtstr: | ||
47 | (*val.str) = str; | ||
48 | break; | ||
49 | |||
50 | case vtuint64: | ||
51 | (*val.uint64) = strtoull( str, NULL, 10 ); | ||
52 | break; | ||
53 | |||
54 | case vtuint32: | ||
55 | (*val.uint32) = strtoul( str, NULL, 10 ); | ||
56 | break; | ||
57 | |||
58 | case vtuint16: | ||
59 | (*val.uint16) = (uint16_t)strtoul( str, NULL, 10 ); | ||
60 | break; | ||
61 | |||
62 | case vtuint8: | ||
63 | (*val.uint8) = (uint8_t)strtoul( str, NULL, 10 ); | ||
64 | break; | ||
65 | |||
66 | case vtint64: | ||
67 | (*val.int64) = strtoll( str, NULL, 10 ); | ||
68 | break; | ||
69 | |||
70 | case vtint32: | ||
71 | (*val.int32) = strtol( str, NULL, 10 ); | ||
72 | break; | ||
73 | |||
74 | case vtint16: | ||
75 | (*val.int16) = (int16_t)strtol( str, NULL, 10 ); | ||
76 | break; | ||
77 | |||
78 | case vtint8: | ||
79 | (*val.int8) = (int8_t)strtol( str, NULL, 10 ); | ||
80 | break; | ||
81 | |||
82 | case vtfloat32: | ||
83 | (*val.float32) = strtof( str, NULL ); | ||
84 | break; | ||
85 | |||
86 | case vtfloat64: | ||
87 | (*val.float64) = strtod( str, NULL ); | ||
88 | break; | ||
89 | |||
90 | case vtfloat96: | ||
91 | (*val.float96) = strtold( str, NULL ); | ||
92 | break; | ||
93 | |||
94 | case vtbln: | ||
95 | if( strcasecmp("yes", str ) == 0 || | ||
96 | strcasecmp("true", str ) == 0 ) | ||
97 | { | ||
98 | (*val.bln) = true; | ||
99 | } | ||
100 | else | ||
101 | { | ||
102 | (*val.bln) = false; | ||
103 | } | ||
104 | break; | ||
105 | } | ||
106 | |||
107 | return *this; | ||
108 | } | ||
109 | |||
110 | ParamProc::ParamProc() | ||
111 | { | ||
112 | } | ||
113 | |||
114 | ParamProc::~ParamProc() | ||
115 | { | ||
116 | for( std::list<ArgSpec *>::iterator i = lArg.begin(); | ||
117 | i != lArg.end(); i++ ) | ||
118 | { | ||
119 | delete *i; | ||
120 | } | ||
121 | |||
122 | for( std::list<Banner *>::iterator i = lBan.begin(); | ||
123 | i != lBan.end(); i++ ) | ||
124 | { | ||
125 | delete *i; | ||
126 | } | ||
127 | |||
128 | } | ||
129 | /* | ||
130 | void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val ) | ||
131 | { | ||
132 | printf("Calling callback...\n"); | ||
133 | val = "Hello there, this is set in the ParamProc"; | ||
134 | (this->*proc)(); | ||
135 | }*/ | ||
136 | |||
137 | void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, | ||
138 | ParamPtr val, const char *lpDesc, const char *lpExtra, | ||
139 | const char *lpValue ) | ||
140 | { | ||
141 | ArgSpec *as = new ArgSpec; | ||
142 | if( lpWord ) | ||
143 | as->sWord = lpWord; | ||
144 | |||
145 | as->cChar = cChar; | ||
146 | as->proc = proc; | ||
147 | as->val = val; | ||
148 | if( lpDesc ) | ||
149 | as->sDesc = lpDesc; | ||
150 | if( lpExtra ) | ||
151 | as->sExtra = lpExtra; | ||
152 | if( lpValue ) | ||
153 | as->sValue = lpValue; | ||
154 | |||
155 | lArg.push_back( as ); | ||
156 | |||
157 | if( !lBan.empty() ) | ||
158 | { | ||
159 | if( lBan.back()->pBefore == NULL ) | ||
160 | lBan.back()->pBefore = as; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, | ||
165 | const char *lpDesc, const char *lpExtra, | ||
166 | const char *lpValue ) | ||
167 | { | ||
168 | addParam( lpWord, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); | ||
169 | } | ||
170 | |||
171 | void ParamProc::addParam( const char *lpWord, char cChar, ParamPtr val, | ||
172 | const char *lpDesc, const char *lpExtra, | ||
173 | const char *lpValue ) | ||
174 | { | ||
175 | addParam( lpWord, cChar, NULL, val, lpDesc, lpExtra, lpValue ); | ||
176 | } | ||
177 | |||
178 | void ParamProc::addParam( const char *lpWord, Proc proc, ParamPtr val, | ||
179 | const char *lpDesc, const char *lpExtra, | ||
180 | const char *lpValue ) | ||
181 | { | ||
182 | addParam( lpWord, '\0', proc, val, lpDesc, lpExtra, lpValue ); | ||
183 | } | ||
184 | |||
185 | void ParamProc::addParam( const char *lpWord, Proc proc, | ||
186 | const char *lpDesc, const char *lpExtra, | ||
187 | const char *lpValue ) | ||
188 | { | ||
189 | addParam( lpWord, '\0', proc, ParamPtr(), lpDesc, lpExtra, lpValue ); | ||
190 | } | ||
191 | |||
192 | void ParamProc::addParam( const char *lpWord, ParamPtr val, | ||
193 | const char *lpDesc, const char *lpExtra, | ||
194 | const char *lpValue ) | ||
195 | { | ||
196 | addParam( lpWord, '\0', NULL, val, lpDesc, lpExtra, lpValue ); | ||
197 | } | ||
198 | |||
199 | void ParamProc::addParam( char cChar, Proc proc, ParamPtr val, | ||
200 | const char *lpDesc, const char *lpExtra, | ||
201 | const char *lpValue ) | ||
202 | { | ||
203 | addParam( NULL, cChar, proc, val, lpDesc, lpExtra, lpValue ); | ||
204 | } | ||
205 | |||
206 | void ParamProc::addParam( char cChar, Proc proc, | ||
207 | const char *lpDesc, const char *lpExtra, | ||
208 | const char *lpValue ) | ||
209 | { | ||
210 | addParam( NULL, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); | ||
211 | } | ||
212 | |||
213 | void ParamProc::addParam( char cChar, ParamPtr val, | ||
214 | const char *lpDesc, const char *lpExtra, | ||
215 | const char *lpValue ) | ||
216 | { | ||
217 | addParam( NULL, cChar, NULL, val, lpDesc, lpExtra, lpValue ); | ||
218 | } | ||
219 | |||
220 | void ParamProc::process( int argc, char *argv[] ) | ||
221 | { | ||
222 | for( int arg = 1; arg < argc; arg++ ) | ||
223 | { | ||
224 | //printf(":::%d:::%s\n", arg, argv[arg] ); | ||
225 | if( argv[arg][0] == '-' ) | ||
226 | { | ||
227 | if( argv[arg][1] == '-' ) | ||
228 | { | ||
229 | ArgSpec *s = checkWord( argv[arg]+2 ); | ||
230 | if( s ) | ||
231 | { | ||
232 | if( argv[arg][s->sWord.getLength()+2] == '=' ) | ||
233 | { | ||
234 | if( s->val.isSet() ) | ||
235 | { | ||
236 | if( s->sValue.getString() == NULL ) | ||
237 | { | ||
238 | s->val = argv[arg]+s->sWord.getLength()+3; | ||
239 | } | ||
240 | else | ||
241 | { | ||
242 | s->val = s->sValue.getString(); | ||
243 | } | ||
244 | } | ||
245 | if( s->proc ) | ||
246 | { | ||
247 | char **tmp = new char*[argc-arg]; | ||
248 | tmp[0] = argv[arg]+s->sWord.getLength()+3; | ||
249 | for( int k = 1; k < argc-arg; k++ ) | ||
250 | tmp[k] = argv[arg+k]; | ||
251 | int ret = (this->*s->proc)( argc-arg, tmp ); | ||
252 | if( ret > 0 ) | ||
253 | { | ||
254 | arg += ret-1; | ||
255 | } | ||
256 | delete tmp; | ||
257 | } | ||
258 | } | ||
259 | else | ||
260 | { | ||
261 | int add = 0; | ||
262 | if( s->val.isSet() ) | ||
263 | { | ||
264 | if( s->sValue.getString() == NULL ) | ||
265 | { | ||
266 | if( arg+1 >= argc ) | ||
267 | { | ||
268 | return; | ||
269 | } | ||
270 | s->val = argv[arg+1]; | ||
271 | add++; | ||
272 | } | ||
273 | else | ||
274 | { | ||
275 | s->val = s->sValue.getString(); | ||
276 | } | ||
277 | } | ||
278 | if( s->proc ) | ||
279 | { | ||
280 | int ret = (this->*s->proc)( | ||
281 | argc-arg-1, argv+arg+1 ); | ||
282 | |||
283 | if( ret > add ) | ||
284 | add = 0; | ||
285 | else | ||
286 | add -= ret; | ||
287 | arg += ret; | ||
288 | } | ||
289 | arg += add; | ||
290 | } | ||
291 | continue; | ||
292 | } | ||
293 | else | ||
294 | { | ||
295 | unknownParam( argc-arg, argv+arg ); | ||
296 | } | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | for( int chr = 1; argv[arg][chr]; chr++ ) | ||
301 | { | ||
302 | ArgSpec *s = checkLetr( argv[arg][chr] ); | ||
303 | if( s ) | ||
304 | { | ||
305 | if( argv[arg][chr+1] != '\0' ) | ||
306 | { | ||
307 | bool bUsed = false; | ||
308 | if( s->val.isSet() ) | ||
309 | { | ||
310 | if( s->sValue.getString() == NULL ) | ||
311 | { | ||
312 | s->val = argv[arg]+chr+1; | ||
313 | bUsed = true; | ||
314 | } | ||
315 | else | ||
316 | { | ||
317 | s->val = s->sValue.getString(); | ||
318 | } | ||
319 | } | ||
320 | if( s->proc ) | ||
321 | { | ||
322 | char **tmp = new char*[argc-arg]; | ||
323 | tmp[0] = argv[arg]+chr+1; | ||
324 | for( int k = 1; k < argc-arg; k++ ) | ||
325 | tmp[k] = argv[arg+k]; | ||
326 | int ret = (this->*s->proc)( argc-arg, tmp ); | ||
327 | if( ret > 0 ) | ||
328 | { | ||
329 | arg += ret - 1; | ||
330 | delete tmp; | ||
331 | break; | ||
332 | } | ||
333 | delete tmp; | ||
334 | } | ||
335 | if( bUsed ) | ||
336 | { | ||
337 | break; | ||
338 | } | ||
339 | } | ||
340 | else | ||
341 | { | ||
342 | bool bUsed = false; | ||
343 | if( s->val.isSet() ) | ||
344 | { | ||
345 | if( s->sValue.getString() == NULL ) | ||
346 | { | ||
347 | s->val = argv[arg+1]; | ||
348 | bUsed = true; | ||
349 | } | ||
350 | else | ||
351 | { | ||
352 | s->val = s->sValue.getString(); | ||
353 | } | ||
354 | } | ||
355 | if( s->proc ) | ||
356 | { | ||
357 | int ret = (this->*s->proc)( | ||
358 | argc-arg-1, argv+arg+1 | ||
359 | ); | ||
360 | if( ret > 0 ) | ||
361 | { | ||
362 | arg += ret; | ||
363 | break; | ||
364 | } | ||
365 | } | ||
366 | if( bUsed ) | ||
367 | { | ||
368 | arg++; | ||
369 | break; | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | else | ||
374 | { | ||
375 | unknownParam( argc-arg, argv+arg ); | ||
376 | } | ||
377 | } | ||
378 | } | ||
379 | } | ||
380 | else | ||
381 | { | ||
382 | cmdParam( argc-arg, argv+arg ); | ||
383 | } | ||
384 | } | ||
385 | } | ||
386 | |||
387 | ParamProc::ArgSpec *ParamProc::checkWord( const char *arg ) | ||
388 | { | ||
389 | //printf("Checking \"%s\"...\n", arg ); | ||
390 | std::list<ArgSpec *>::const_iterator i; | ||
391 | for( i = lArg.begin(); i != lArg.end(); i++ ) | ||
392 | { | ||
393 | if( (*i)->sWord.getString() == NULL ) | ||
394 | continue; | ||
395 | |||
396 | if( !strcmp( (*i)->sWord, arg ) ) | ||
397 | return *i; | ||
398 | |||
399 | if( (*i)->val.isSet() ) | ||
400 | { | ||
401 | if( !strncmp( (*i)->sWord, arg, (*i)->sWord.getLength() ) && | ||
402 | arg[(*i)->sWord.getLength()] == '=' ) | ||
403 | { | ||
404 | return *i; | ||
405 | } | ||
406 | } | ||
407 | } | ||
408 | |||
409 | return NULL; | ||
410 | } | ||
411 | |||
412 | ParamProc::ArgSpec *ParamProc::checkLetr( const char arg ) | ||
413 | { | ||
414 | //printf("Checking \'%c\'...\n", arg ); | ||
415 | std::list<ArgSpec *>::const_iterator i; | ||
416 | for( i = lArg.begin(); i != lArg.end(); i++ ) | ||
417 | { | ||
418 | if( (*i)->cChar == '\0' ) | ||
419 | continue; | ||
420 | |||
421 | if( (*i)->cChar == arg ) | ||
422 | { | ||
423 | return *i; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | return NULL; | ||
428 | } | ||
429 | |||
430 | int ParamProc::cmdParam( int argc, char *argv[] ) | ||
431 | { | ||
432 | printf("Unhandled command parameter \"%s\" found!\n", argv[0] ); | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | int ParamProc::unknownParam( int argc, char *argv[] ) | ||
437 | { | ||
438 | printf("Unknown parameter \"%s\" found!\n", argv[0] ); | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | int ParamProc::help( int argc, char *argv[] ) | ||
443 | { | ||
444 | std::list<Banner *>::const_iterator b = lBan.begin(); | ||
445 | std::list<ArgSpec *>::const_iterator i; | ||
446 | int len=0; | ||
447 | for( i = lArg.begin(); i != lArg.end(); i++ ) | ||
448 | { | ||
449 | if( len < (*i)->sWord.getLength() + (*i)->sExtra.getLength() ) | ||
450 | len = (*i)->sWord.getLength() + (*i)->sExtra.getLength(); | ||
451 | } | ||
452 | char fmt[10]; | ||
453 | sprintf( fmt, "%%-%ds ", len ); | ||
454 | |||
455 | for( i = lArg.begin(); i != lArg.end(); i++ ) | ||
456 | { | ||
457 | if( b != lBan.end() ) | ||
458 | { | ||
459 | if( (*b)->pBefore == (*i) ) | ||
460 | { | ||
461 | printf( (*b)->sBanner.getString() ); | ||
462 | b++; | ||
463 | } | ||
464 | } | ||
465 | printf(" "); | ||
466 | if( (*i)->cChar ) | ||
467 | { | ||
468 | if( (*i)->sWord.getString() ) | ||
469 | { | ||
470 | printf("-%c, ", (*i)->cChar ); | ||
471 | } | ||
472 | else | ||
473 | { | ||
474 | printf("-%c ", (*i)->cChar ); | ||
475 | } | ||
476 | } | ||
477 | else | ||
478 | { | ||
479 | printf(" "); | ||
480 | } | ||
481 | if( (*i)->sWord.getString() ) | ||
482 | { | ||
483 | printf("--"); | ||
484 | std::string sTmp = (*i)->sWord.getString(); | ||
485 | if( (*i)->sExtra.getString() ) | ||
486 | sTmp += (*i)->sExtra.getString(); | ||
487 | printf( fmt, sTmp.c_str() ); | ||
488 | } | ||
489 | else | ||
490 | { | ||
491 | printf(" "); | ||
492 | printf(fmt, "" ); | ||
493 | } | ||
494 | printf("%s\n", (*i)->sDesc.getString() ); | ||
495 | } | ||
496 | if( b != lBan.end() ) | ||
497 | { | ||
498 | if( (*b)->pBefore == NULL ) | ||
499 | { | ||
500 | printf( (*b)->sBanner.getString() ); | ||
501 | } | ||
502 | } | ||
503 | |||
504 | exit( 0 ); | ||
505 | } | ||
506 | |||
507 | void ParamProc::addHelpBanner( const char *sHelpBanner ) | ||
508 | { | ||
509 | Banner *pBan = new Banner; | ||
510 | pBan->sBanner = sHelpBanner; | ||
511 | pBan->pBefore = NULL; | ||
512 | lBan.push_back( pBan ); | ||
513 | } | ||
514 | |||
diff --git a/src/old/paramproc.h b/src/old/paramproc.h new file mode 100644 index 0000000..d857193 --- /dev/null +++ b/src/old/paramproc.h | |||
@@ -0,0 +1,153 @@ | |||
1 | #ifndef PARAM_PROC_H | ||
2 | #define PARAM_PROC_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <string> | ||
6 | #include <list> | ||
7 | #include "staticstring.h" | ||
8 | |||
9 | class ParamProc | ||
10 | { | ||
11 | public: | ||
12 | class ParamPtr | ||
13 | { | ||
14 | public: | ||
15 | ParamPtr(); | ||
16 | ParamPtr( std::string *str ); | ||
17 | ParamPtr( uint64_t *uint64 ); | ||
18 | ParamPtr( uint32_t *uint32 ); | ||
19 | ParamPtr( uint16_t *uint16 ); | ||
20 | ParamPtr( uint8_t *uint8 ); | ||
21 | ParamPtr( int64_t *int64 ); | ||
22 | ParamPtr( int32_t *int32 ); | ||
23 | ParamPtr( int16_t *int16 ); | ||
24 | ParamPtr( int8_t *int8 ); | ||
25 | ParamPtr( float *float32 ); | ||
26 | ParamPtr( double *float64 ); | ||
27 | ParamPtr( long double *float96 ); | ||
28 | ParamPtr( bool *bln ); | ||
29 | |||
30 | enum | ||
31 | { | ||
32 | vtunset, | ||
33 | vtstr, | ||
34 | vtuint64, | ||
35 | vtuint32, | ||
36 | vtuint16, | ||
37 | vtuint8, | ||
38 | vtint64, | ||
39 | vtint32, | ||
40 | vtint16, | ||
41 | vtint8, | ||
42 | vtfloat32, | ||
43 | vtfloat64, | ||
44 | vtfloat96, | ||
45 | vtbln, | ||
46 | }; | ||
47 | ParamPtr &operator=( ParamPtr &ptr ); | ||
48 | ParamPtr &operator=( const char *str ); | ||
49 | |||
50 | bool isSet(); | ||
51 | |||
52 | private: | ||
53 | int type; | ||
54 | union | ||
55 | { | ||
56 | std::string *str; | ||
57 | uint64_t *uint64; | ||
58 | uint32_t *uint32; | ||
59 | uint16_t *uint16; | ||
60 | uint8_t *uint8; | ||
61 | int64_t *int64; | ||
62 | int32_t *int32; | ||
63 | int16_t *int16; | ||
64 | int8_t *int8; | ||
65 | float *float32; | ||
66 | double *float64; | ||
67 | long double *float96; | ||
68 | bool *bln; | ||
69 | } val; | ||
70 | }; | ||
71 | |||
72 | typedef int (ParamProc::*Proc)( int, char *[] ); | ||
73 | |||
74 | typedef struct ArgSpec | ||
75 | { | ||
76 | uint8_t nFlags; | ||
77 | StaticString sWord; | ||
78 | char cChar; | ||
79 | Proc proc; | ||
80 | ParamProc::ParamPtr val; | ||
81 | StaticString sExtra; | ||
82 | StaticString sDesc; | ||
83 | StaticString sValue; | ||
84 | } ArgSpec; | ||
85 | |||
86 | public: | ||
87 | ParamProc(); | ||
88 | virtual ~ParamProc(); | ||
89 | |||
90 | void addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val, | ||
91 | const char *lpDesc=NULL, const char *lpExtra=NULL, | ||
92 | const char *lpValue=NULL | ||
93 | ); | ||
94 | void addParam( const char *lpWord, char cChar, Proc proc, | ||
95 | const char *lpDesc=NULL, const char *lpExtra=NULL, | ||
96 | const char *lpValue=NULL | ||
97 | ); | ||
98 | void addParam( const char *lpWord, char cChar, ParamPtr val, | ||
99 | const char *lpDesc=NULL, const char *lpExtra=NULL, | ||
100 | const char *lpValue=NULL | ||
101 | ); | ||
102 | |||
103 | void addParam( const char *lpWord, Proc proc, ParamPtr val, | ||
104 | const char *lpDesc=NULL, const char *lpExtra=NULL, | ||
105 | const char *lpValue=NULL | ||
106 | ); | ||
107 | void addParam( const char *lpWord, Proc proc, | ||
108 | const char *lpDesc=NULL, const char *lpExtra=NULL, | ||
109 | const char *lpValue=NULL | ||
110 | ); | ||
111 | void addParam( const char *lpWord, ParamPtr val, | ||
112 | const char *lpDesc=NULL, const char *lpExtra=NULL, | ||
113 | const char *lpValue=NULL | ||
114 | ); | ||
115 | |||
116 | void addParam( char cChar, Proc proc, ParamPtr val, | ||
117 | const char *lpDesc=NULL, const char *lpExtra=NULL, | ||
118 | const char *lpValue=NULL | ||
119 | ); | ||
120 | void addParam( char cChar, Proc proc, | ||
121 | const char *lpDesc=NULL, const char *lpExtra=NULL, | ||
122 | const char *lpValue=NULL | ||
123 | ); | ||
124 | void addParam( char cChar, ParamPtr val, | ||
125 | const char *lpDesc=NULL, const char *lpExtra=NULL, | ||
126 | const char *lpValue=NULL | ||
127 | ); | ||
128 | |||
129 | void process( int argc, char *argv[] ); | ||
130 | void addHelpBanner( const char *sHelpBanner ); | ||
131 | |||
132 | private: | ||
133 | ArgSpec *checkWord( const char *arg ); | ||
134 | ArgSpec *checkLetr( const char arg ); | ||
135 | |||
136 | public: | ||
137 | virtual int cmdParam( int argc, char *argv[] ); | ||
138 | virtual int unknownParam( int argc, char *argv[] ); | ||
139 | virtual int help( int argc, char *argv[] ); | ||
140 | |||
141 | private: | ||
142 | typedef struct Banner | ||
143 | { | ||
144 | StaticString sBanner; | ||
145 | ArgSpec *pBefore; | ||
146 | } Banner; | ||
147 | std::list<Banner *> lBan; | ||
148 | std::list<ArgSpec *> lArg; | ||
149 | }; | ||
150 | |||
151 | #define mkproc( cls ) static_cast<int (ParamProc::*)( int, char *[])>(&cls) | ||
152 | |||
153 | #endif | ||
diff --git a/src/old/plugger.cpp b/src/old/plugger.cpp new file mode 100644 index 0000000..f3bfa67 --- /dev/null +++ b/src/old/plugger.cpp | |||
@@ -0,0 +1 @@ | |||
#include "plugger.h" | |||
diff --git a/src/old/plugger.h b/src/old/plugger.h new file mode 100644 index 0000000..d92f194 --- /dev/null +++ b/src/old/plugger.h | |||
@@ -0,0 +1,198 @@ | |||
1 | #ifndef PLUGGER_H | ||
2 | #define PLUGGER_H | ||
3 | |||
4 | |||
5 | #include "hashtable.h" | ||
6 | #include "list" | ||
7 | #include "hashfunctionstring.h" | ||
8 | #include "hashfunctionint.h" | ||
9 | #include "dlfcn.h" | ||
10 | #include "exceptions.h" | ||
11 | |||
12 | typedef struct PluginInfo | ||
13 | { | ||
14 | const char *sID; | ||
15 | const char *sAuthor; | ||
16 | unsigned short nVersion; | ||
17 | unsigned short nRevision; | ||
18 | void *(*createPlugin)(); | ||
19 | void (*destroyPlugin)( void * ); | ||
20 | } PluginInfo; | ||
21 | |||
22 | typedef struct PluginReg | ||
23 | { | ||
24 | bool bBuiltin; | ||
25 | void *dlHandle; | ||
26 | PluginInfo *pInfo; | ||
27 | } PluginReg; | ||
28 | |||
29 | #define PluginInterface( classname, baseclass, name, ver, rev ) \ | ||
30 | extern "C" { \ | ||
31 | baseclass *create ##classname() \ | ||
32 | { \ | ||
33 | return new classname(); \ | ||
34 | } \ | ||
35 | void destroy ##classname( baseclass *pCls ) \ | ||
36 | { \ | ||
37 | delete pCls; \ | ||
38 | } \ | ||
39 | PluginInfo classname = { \ | ||
40 | #classname, name, ver, rev, \ | ||
41 | create ##classname, destroy ##classname }; \ | ||
42 | } | ||
43 | |||
44 | #define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ | ||
45 | extern "C" { \ | ||
46 | baseclass *create ##classname() \ | ||
47 | { \ | ||
48 | return new classname(); \ | ||
49 | } \ | ||
50 | void destroy ##classname( baseclass *pCls ) \ | ||
51 | { \ | ||
52 | delete pCls; \ | ||
53 | } \ | ||
54 | PluginInfo pluginname = { \ | ||
55 | #pluginname, name, ver, rev, \ | ||
56 | (void *(*)())(create ##classname), \ | ||
57 | (void (*)( void * ))(destroy ##classname) }; \ | ||
58 | } | ||
59 | |||
60 | #define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ | ||
61 | extern "C" { \ | ||
62 | baseclass *create ##classname() \ | ||
63 | { \ | ||
64 | return new classname(); \ | ||
65 | } \ | ||
66 | void destroy ##classname( baseclass *pCls ) \ | ||
67 | { \ | ||
68 | delete pCls; \ | ||
69 | } \ | ||
70 | PluginInfo structname = { \ | ||
71 | #pluginname, name, ver, rev, \ | ||
72 | (void *(*)())(create ##classname), \ | ||
73 | (void (*)( void * ))(destroy ##classname) }; \ | ||
74 | } | ||
75 | |||
76 | template<class T> | ||
77 | class Plugger | ||
78 | { | ||
79 | public: | ||
80 | |||
81 | public: | ||
82 | Plugger() : | ||
83 | hPlugin( new HashFunctionString(), 11 ), | ||
84 | hObj( new HashFunctionInt(), 11 ) | ||
85 | { | ||
86 | } | ||
87 | |||
88 | virtual ~Plugger() | ||
89 | { | ||
90 | void *pos = hObj.getFirstItemPos(); | ||
91 | while( (pos = hObj.getNextItemPos( pos )) ) | ||
92 | { | ||
93 | T *pPlug = (T *)hObj.getItemID( pos ); | ||
94 | PluginReg *pReg = (PluginReg *)hObj.getItemData( pos ); | ||
95 | pReg->pInfo->destroyPlugin( pPlug ); | ||
96 | } | ||
97 | |||
98 | std::list<PluginReg *>::iterator i; | ||
99 | for( i = lPlugin.begin(); i != lPlugin.end(); i++ ) | ||
100 | { | ||
101 | if( (*i)->bBuiltin == false ) | ||
102 | { | ||
103 | dlclose( (*i)->dlHandle ); | ||
104 | } | ||
105 | delete (*i); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | void registerBuiltinPlugin( PluginInfo *pInfo ) | ||
110 | { | ||
111 | PluginReg *pReg = new PluginReg; | ||
112 | pReg->bBuiltin = true; | ||
113 | pReg->pInfo = pInfo; | ||
114 | lPlugin.insert( lPlugin.end(), pReg ); | ||
115 | hPlugin.insert( pInfo->sID, pReg ); | ||
116 | } | ||
117 | |||
118 | void registerExternalPlugin( const char *sFName, const char *sPluginName ) | ||
119 | { | ||
120 | PluginReg *pReg = (PluginReg *)hPlugin[sPluginName]; | ||
121 | if( pReg != NULL ) | ||
122 | { | ||
123 | hPlugin.del( sPluginName ); | ||
124 | dlclose( pReg->dlHandle ); | ||
125 | delete pReg; | ||
126 | pReg = NULL; | ||
127 | } | ||
128 | |||
129 | pReg = new PluginReg; | ||
130 | |||
131 | pReg->bBuiltin = false; | ||
132 | pReg->dlHandle = dlopen( sFName, RTLD_NOW ); | ||
133 | if( pReg->dlHandle == NULL ) | ||
134 | { | ||
135 | throw PluginException( 1, "Error on %s: %s", sFName, dlerror() ); | ||
136 | } | ||
137 | pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, sPluginName ); | ||
138 | if( pReg->pInfo == NULL ) | ||
139 | { | ||
140 | throw PluginException( 2, "Error on %s: %s", sFName, dlerror() ); | ||
141 | } | ||
142 | hPlugin.insert( pReg->pInfo->sID, pReg ); | ||
143 | lPlugin.insert( lPlugin.end(), pReg ); | ||
144 | } | ||
145 | |||
146 | T *instantiate( const char *lpName ) | ||
147 | { | ||
148 | PluginReg *pReg = (PluginReg *)hPlugin[lpName]; | ||
149 | if( pReg == NULL ) | ||
150 | return NULL; | ||
151 | |||
152 | T *p = (T *)pReg->pInfo->createPlugin(); | ||
153 | hObj.insert( p, pReg ); | ||
154 | //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); | ||
155 | |||
156 | return p; | ||
157 | } | ||
158 | |||
159 | bool hasPlugin( const char *lpName ) | ||
160 | { | ||
161 | if( hPlugin[lpName] == NULL ) | ||
162 | return false; | ||
163 | return true; | ||
164 | } | ||
165 | |||
166 | void destroy( T *pPlug ) | ||
167 | { | ||
168 | PluginReg *pReg = (PluginReg *)hObj[pPlug]; | ||
169 | //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); | ||
170 | if( pReg == NULL ) | ||
171 | return; | ||
172 | |||
173 | pReg->pInfo->destroyPlugin( pPlug ); | ||
174 | |||
175 | hObj.del( pPlug ); | ||
176 | } | ||
177 | |||
178 | void unloadAll() | ||
179 | { | ||
180 | std::list<PluginReg *>::iterator i; | ||
181 | for( i = lPlugin.begin(); i != lPlugin.end(); i++ ) | ||
182 | { | ||
183 | if( (*i)->bBuiltin == false ) | ||
184 | { | ||
185 | dlclose( (*i)->dlHandle ); | ||
186 | } | ||
187 | delete (*i); | ||
188 | } | ||
189 | hPlugin.clear(); | ||
190 | } | ||
191 | |||
192 | private: | ||
193 | std::list<PluginReg *> lPlugin; | ||
194 | HashTable hPlugin; | ||
195 | HashTable hObj; | ||
196 | }; | ||
197 | |||
198 | #endif | ||
diff --git a/src/old/pqueue.cpp b/src/old/pqueue.cpp new file mode 100644 index 0000000..1f0b8b5 --- /dev/null +++ b/src/old/pqueue.cpp | |||
@@ -0,0 +1,33 @@ | |||
1 | #include "pqueue.h" | ||
2 | |||
3 | PQueue::PQueue( int nNewNumQueues ) | ||
4 | { | ||
5 | nNumQueues = nNewNumQueues; | ||
6 | aQueue = new Queue[nNumQueues]; | ||
7 | } | ||
8 | |||
9 | PQueue::~PQueue() | ||
10 | { | ||
11 | delete[] aQueue; | ||
12 | } | ||
13 | |||
14 | void PQueue::enqueue( void *pData, int nQueueLevel ) | ||
15 | { | ||
16 | if( nQueueLevel < 0 || nQueueLevel >= nNumQueues ) | ||
17 | return; | ||
18 | |||
19 | aQueue[nQueueLevel].enqueue( pData ); | ||
20 | } | ||
21 | |||
22 | void *PQueue::dequeue() | ||
23 | { | ||
24 | for( int j = 0; j < nNumQueues; j++ ) | ||
25 | { | ||
26 | if( aQueue[j].isEmpty() == false ) | ||
27 | { | ||
28 | return aQueue[j].dequeue(); | ||
29 | } | ||
30 | } | ||
31 | |||
32 | return NULL; | ||
33 | } | ||
diff --git a/src/old/pqueue.h b/src/old/pqueue.h new file mode 100644 index 0000000..8307d56 --- /dev/null +++ b/src/old/pqueue.h | |||
@@ -0,0 +1,48 @@ | |||
1 | #ifndef PQUEUE_H | ||
2 | #define PQUEUE_H | ||
3 | |||
4 | #include "queue.h" | ||
5 | |||
6 | /** Priority queue. This is just like a queue, but something with a higher | ||
7 | * priority will always come off the queue before something with a lower | ||
8 | * priority, even if it's added after. Otherwise works just like a queue. | ||
9 | *@author Mike Buland | ||
10 | */ | ||
11 | class PQueue | ||
12 | { | ||
13 | public: | ||
14 | /** Create a queue with any number of different priorities. | ||
15 | *@param nNewNumQueues The number of queues, the default is 3 | ||
16 | */ | ||
17 | PQueue( int nNewNumQueues=3 ); | ||
18 | |||
19 | /** | ||
20 | * Cleanup all contained queues. | ||
21 | */ | ||
22 | virtual ~PQueue(); | ||
23 | |||
24 | /** Add a new item to the queue at the specified priority. A lower | ||
25 | * number means a higher priority! | ||
26 | *@param pData A pointer to the data to add to the queue | ||
27 | *@param nQueueLevel The priority to set the new data to | ||
28 | */ | ||
29 | void enqueue( void *pData, int nQueueLevel ); | ||
30 | |||
31 | /** Pull the next item off the queue, high priority first. | ||
32 | *@returns A pointer to the data that was next in the priority queue | ||
33 | */ | ||
34 | void *dequeue(); | ||
35 | |||
36 | private: | ||
37 | /** | ||
38 | * The queues we use for real data storage. | ||
39 | */ | ||
40 | Queue *aQueue; | ||
41 | |||
42 | /** | ||
43 | * The number of priorities or queus that we need. | ||
44 | */ | ||
45 | int nNumQueues; | ||
46 | }; | ||
47 | |||
48 | #endif | ||
diff --git a/src/old/programchain.cpp b/src/old/programchain.cpp new file mode 100644 index 0000000..6120d58 --- /dev/null +++ b/src/old/programchain.cpp | |||
@@ -0,0 +1,96 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include "programchain.h" | ||
3 | |||
4 | ProgramChain::ProgramChain() : | ||
5 | xLog( MultiLog::getInstance() ) | ||
6 | { | ||
7 | xLog.LineLog( MultiLog::LStatus, "Program Chain Initialized." ); | ||
8 | } | ||
9 | |||
10 | ProgramChain::~ProgramChain() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | bool ProgramChain::addLink( ProgramLink *pLink ) | ||
15 | { | ||
16 | if( pLink->init() == false ) | ||
17 | { | ||
18 | emergencyShutdown(); | ||
19 | return false; | ||
20 | } | ||
21 | |||
22 | lLink.append( pLink ); | ||
23 | |||
24 | pLink->setChain( this ); | ||
25 | |||
26 | return true; | ||
27 | } | ||
28 | |||
29 | ProgramLink *ProgramChain::getLink( const char *lpName ) | ||
30 | { | ||
31 | char a; | ||
32 | a = lpName[0]; | ||
33 | return NULL; | ||
34 | } | ||
35 | |||
36 | ProgramLink *ProgramChain::getBaseLink() | ||
37 | { | ||
38 | return NULL; | ||
39 | } | ||
40 | |||
41 | bool ProgramChain::execChainOnce() | ||
42 | { | ||
43 | int nLen = lLink.getSize(); | ||
44 | for( int j = 0; j < nLen; j++ ) | ||
45 | { | ||
46 | if( ((ProgramLink *)lLink[j])->timeSlice() == false ) | ||
47 | { | ||
48 | xLog.LineLog( MultiLog::LInfo, "Shutting down due to signal from link #%d", j ); | ||
49 | emergencyShutdown(); | ||
50 | return false; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | return true; | ||
55 | } | ||
56 | |||
57 | bool ProgramChain::enterChainLoop() | ||
58 | { | ||
59 | for(;;) | ||
60 | { | ||
61 | if( execChainOnce() == false ) | ||
62 | { | ||
63 | return false; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | return true; | ||
68 | } | ||
69 | |||
70 | void ProgramChain::emergencyShutdown() | ||
71 | { | ||
72 | int nLen = lLink.getSize(); | ||
73 | for( int j = 0; j < nLen; j++ ) | ||
74 | { | ||
75 | ((ProgramLink *)lLink[j])->deInit(); | ||
76 | delete (ProgramLink *)lLink[j]; | ||
77 | } | ||
78 | lLink.empty(); | ||
79 | } | ||
80 | |||
81 | LinkMessage *ProgramChain::broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ) | ||
82 | { | ||
83 | int nLen = lLink.getSize(); | ||
84 | for( int j = 0; j < nLen; j++ ) | ||
85 | { | ||
86 | LinkMessage *pMsg = ((ProgramLink *)lLink[j])->processIRM( pMsgOut ); | ||
87 | if( pMsg != NULL ) | ||
88 | { | ||
89 | delete pMsgOut; | ||
90 | return pMsg; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | delete pMsgOut; | ||
95 | return NULL; | ||
96 | } | ||
diff --git a/src/old/programchain.h b/src/old/programchain.h new file mode 100644 index 0000000..2bdfeee --- /dev/null +++ b/src/old/programchain.h | |||
@@ -0,0 +1,95 @@ | |||
1 | #ifndef PROGRAMCHAIN_H | ||
2 | #define PROGRAMCHAIN_H | ||
3 | |||
4 | #include "linkedlist.h" | ||
5 | #include "multilog.h" | ||
6 | #include "programlink.h" | ||
7 | |||
8 | /** | ||
9 | * The Program Chain links together program "chunks" to more easily facilitate | ||
10 | * a generalized program loop with modular extensions. | ||
11 | *@author Mike Buland | ||
12 | */ | ||
13 | class ProgramChain | ||
14 | { | ||
15 | public: | ||
16 | /** | ||
17 | * Construct an empty chain. | ||
18 | */ | ||
19 | ProgramChain(); | ||
20 | |||
21 | /** | ||
22 | * Destroy your chain. | ||
23 | */ | ||
24 | virtual ~ProgramChain(); | ||
25 | |||
26 | /** | ||
27 | * Adds a link to the end of the chain. | ||
28 | *@param pLink A pointer to the link to add to the chain. | ||
29 | *@returns True if adding the link was successful, otherwise false | ||
30 | *@author Mike Buland | ||
31 | */ | ||
32 | bool addLink( ProgramLink *pLink ); | ||
33 | |||
34 | /** | ||
35 | * Gets a link by name. | ||
36 | *@param lpName The name of the link you're looking for. Every link has a | ||
37 | * name, apparently. | ||
38 | *@returns A pointer to the specified ProgramLink, or NULL if none were | ||
39 | * found matching your criteria. | ||
40 | *@author Mike Buland | ||
41 | */ | ||
42 | class ProgramLink *getLink( const char *lpName ); | ||
43 | |||
44 | /** | ||
45 | * Gets the very first link in the chain. | ||
46 | *@returns A pointer to the first link in the chain. | ||
47 | *@author Mike Buland | ||
48 | */ | ||
49 | class ProgramLink *getBaseLink(); | ||
50 | |||
51 | /** | ||
52 | * Runs through the chain once. Useful if you want to have more control | ||
53 | * over the operation of the chain. | ||
54 | *@returns true if every link returned true. If at least one link returns | ||
55 | * false, then returns false. | ||
56 | *@author Mike Buland | ||
57 | */ | ||
58 | bool execChainOnce(); | ||
59 | |||
60 | /** | ||
61 | * Enters the master chain loop, looping over the entire chain and | ||
62 | * executing every link's TimeSlice routine in order, over and over, until | ||
63 | * a link returns a false value. | ||
64 | *@returns False, always. It returns true unless a link returned false, | ||
65 | * but loops until a link does return false. | ||
66 | *@author Mike Buland | ||
67 | **/ | ||
68 | bool enterChainLoop(); | ||
69 | |||
70 | /** | ||
71 | * Broadcasts an Immediate Response Message to all active links, save the | ||
72 | * sender. Whatever link first responds with a non-null response message | ||
73 | * will have it's messages sent back to the broadcasting link as the returns | ||
74 | * of this function call. Therefore it is very important that all message | ||
75 | * processing code is handled in a fairly timely fasion. | ||
76 | *@param pMsgOut The message to broadcast in hopes of a response. | ||
77 | *@param pSender The message that sent out the message and doesn't want to | ||
78 | * receive it's own message. This should always just be "this". | ||
79 | *@returns The message that was returned by the first link to return a | ||
80 | * non-null response. If all messages return null responses then this also | ||
81 | * returns null. Please note that whoever calls this will be responsible | ||
82 | * for deleting the message returned by it, if non-null. | ||
83 | */ | ||
84 | class LinkMessage *broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ); | ||
85 | |||
86 | private: | ||
87 | /** | ||
88 | * Shuts down all operation no matter what point in the operation we were. | ||
89 | */ | ||
90 | void emergencyShutdown(); | ||
91 | MultiLog &xLog; /**< A reference to the log. */ | ||
92 | LinkedList lLink; /**< The linked list that contains all of the links. */ | ||
93 | }; | ||
94 | |||
95 | #endif | ||
diff --git a/src/old/programlink.cpp b/src/old/programlink.cpp new file mode 100644 index 0000000..21c6fe4 --- /dev/null +++ b/src/old/programlink.cpp | |||
@@ -0,0 +1,54 @@ | |||
1 | #include "programlink.h" | ||
2 | #include "programchain.h" | ||
3 | |||
4 | ProgramLink::ProgramLink() | ||
5 | { | ||
6 | } | ||
7 | |||
8 | ProgramLink::~ProgramLink() | ||
9 | { | ||
10 | } | ||
11 | |||
12 | LinkMessage *ProgramLink::sendIRM( LinkMessage *pMsgOut ) | ||
13 | { | ||
14 | return pChain->broadcastIRM( pMsgOut, this ); | ||
15 | } | ||
16 | |||
17 | void ProgramLink::setChain( ProgramChain *pNewChain ) | ||
18 | { | ||
19 | pChain = pNewChain; | ||
20 | } | ||
21 | |||
22 | /* | ||
23 | void ProgramLink::postMessage( LinkMessage *pMsg, int nLvl ) | ||
24 | { | ||
25 | if( nLvl == msgToChain ) | ||
26 | { | ||
27 | qMsgToChain.enqueue( pMsg ); | ||
28 | } | ||
29 | else if( nLvl == msgToLink ) | ||
30 | { | ||
31 | qMsgToLink.enqueue( pMsg ); | ||
32 | } | ||
33 | else | ||
34 | { | ||
35 | // ERROR! | ||
36 | } | ||
37 | } | ||
38 | |||
39 | LinkMessage *ProgramLink::getMessage( int nLvl ) | ||
40 | { | ||
41 | if( nLvl == msgToChain ) | ||
42 | { | ||
43 | return (LinkMessage *)qMsgToChain.dequeue(); | ||
44 | } | ||
45 | else if( nLvl == msgToLink ) | ||
46 | { | ||
47 | return (LinkMessage *)qMsgToLink.dequeue(); | ||
48 | } | ||
49 | else | ||
50 | { | ||
51 | // ERROR! | ||
52 | } | ||
53 | } | ||
54 | */ | ||
diff --git a/src/old/programlink.h b/src/old/programlink.h new file mode 100644 index 0000000..f93edcc --- /dev/null +++ b/src/old/programlink.h | |||
@@ -0,0 +1,99 @@ | |||
1 | #ifndef PROGRAMLINK_H | ||
2 | #define PROGRAMLINK_H | ||
3 | |||
4 | class ProgramLink; | ||
5 | #include "queue.h" | ||
6 | #include "linkmessage.h" | ||
7 | #include "programchain.h" | ||
8 | |||
9 | /** | ||
10 | * Program Link is the base class for any object that will be a piece of the | ||
11 | * main program chain loop. | ||
12 | *@author Mike Buland | ||
13 | */ | ||
14 | class ProgramLink | ||
15 | { | ||
16 | friend class ProgramChain; | ||
17 | public: | ||
18 | /** | ||
19 | * Construct a program link. | ||
20 | */ | ||
21 | ProgramLink(); | ||
22 | |||
23 | /** | ||
24 | * Deconstruct. | ||
25 | */ | ||
26 | virtual ~ProgramLink(); | ||
27 | |||
28 | /** | ||
29 | * Initialization code required for a link that wasn't performed in the | ||
30 | * constructor. | ||
31 | *@returns true if initialization was successful. A false value will halt | ||
32 | * the chain. | ||
33 | */ | ||
34 | virtual bool init()=0; | ||
35 | |||
36 | /** | ||
37 | * DeInitialization code that should happen, but doesn't belong in the | ||
38 | * destructor. | ||
39 | *@returns true means everything worked, false means failure, but is | ||
40 | * meaningless. | ||
41 | */ | ||
42 | virtual bool deInit()=0; | ||
43 | |||
44 | /** | ||
45 | * Executed once per link per chain pass. Contains the guts of the program. | ||
46 | *@returns true if everything went well. A false value will halt the chain. | ||
47 | */ | ||
48 | virtual bool timeSlice()=0; | ||
49 | |||
50 | /** | ||
51 | * This must be handled in order to process Instant Response Messages. | ||
52 | * This function should return null on all messages that it doesn't | ||
53 | * understand how to handle, and construct new messages to return to sender | ||
54 | * in the cases where it does understand. | ||
55 | *@param pMsgIn The message that must be processed. | ||
56 | *@returns Either a new message in cases where a response is required, | ||
57 | * or null if nothing needs to be done by this link. | ||
58 | */ | ||
59 | virtual LinkMessage *processIRM( LinkMessage *pMsgIn ) = 0; | ||
60 | |||
61 | /** | ||
62 | * Broadcast a LinkMessage to all other links in the system. Each other | ||
63 | * link will get a call of their processIRM function. If the message gets | ||
64 | * a response then you will regain control immediately, otherwise the system | ||
65 | * will give all other Links a chance to respond before returning NULL. | ||
66 | *@param pMsgOut The message to broadcast. | ||
67 | *@returns The message response, or NULL if no Link understood your message. | ||
68 | */ | ||
69 | LinkMessage *sendIRM( LinkMessage *pMsgOut ); | ||
70 | |||
71 | private: | ||
72 | /** | ||
73 | * Set which chain we're assosiated with. This is how IRM messages make | ||
74 | * it out to the rest of the world. | ||
75 | *@param pNewChain A pointer to the containing program chain. | ||
76 | */ | ||
77 | void setChain( class ProgramChain *pNewChain ); | ||
78 | |||
79 | /** | ||
80 | * The pointer to the containing chain. | ||
81 | */ | ||
82 | class ProgramChain *pChain; | ||
83 | /* | ||
84 | void postMessage( LinkMessage *pMsg, int nLvl ); | ||
85 | LinkMessage *getMessage( int nLvl ); | ||
86 | |||
87 | enum | ||
88 | { | ||
89 | msgToChain, | ||
90 | msgToLink | ||
91 | }; | ||
92 | |||
93 | private: | ||
94 | Queue qMsgToChain; | ||
95 | Queue qMsgToLink; | ||
96 | */ | ||
97 | }; | ||
98 | |||
99 | #endif | ||
diff --git a/src/old/protocol.cpp b/src/old/protocol.cpp new file mode 100644 index 0000000..78b3ee2 --- /dev/null +++ b/src/old/protocol.cpp | |||
@@ -0,0 +1,20 @@ | |||
1 | #include "protocol.h" | ||
2 | |||
3 | Protocol::Protocol() | ||
4 | { | ||
5 | pConnection = NULL; | ||
6 | } | ||
7 | |||
8 | Protocol::~Protocol() | ||
9 | { | ||
10 | } | ||
11 | |||
12 | void Protocol::setConnection( Connection *pNewConnection ) | ||
13 | { | ||
14 | pConnection = pNewConnection; | ||
15 | } | ||
16 | |||
17 | Connection *Protocol::getConnection() | ||
18 | { | ||
19 | return pConnection; | ||
20 | } | ||
diff --git a/src/old/protocol.h b/src/old/protocol.h new file mode 100644 index 0000000..09e1c98 --- /dev/null +++ b/src/old/protocol.h | |||
@@ -0,0 +1,62 @@ | |||
1 | #ifndef PROTOCOL_H | ||
2 | #define PROTOCOL_H | ||
3 | |||
4 | #include "connection.h" | ||
5 | |||
6 | /** This is the template for a class that handles specialized input and output | ||
7 | * to connections of different types with different protocols. | ||
8 | *@author Mike Buland | ||
9 | */ | ||
10 | class Protocol | ||
11 | { | ||
12 | public: | ||
13 | /** Constructor */ | ||
14 | Protocol(); | ||
15 | /** Deconstructor */ | ||
16 | virtual ~Protocol(); | ||
17 | |||
18 | /** | ||
19 | * Function is called every time there is new data on the line. This is | ||
20 | * called directly from the Connection class to process data. This is not | ||
21 | * called whever there is pending data on the input, but every time new data | ||
22 | * is added to the input buffer. | ||
23 | *@returns True if processing went alright, false if something went wrong, | ||
24 | * I suppose. In truth this value is thrown away right now. | ||
25 | *@todo Either make a return value of false mean something, or make these | ||
26 | * void. | ||
27 | */ | ||
28 | virtual bool onNewData()=0; | ||
29 | |||
30 | /** | ||
31 | * Function is called when there is a new connection. This should only | ||
32 | * happen once per Protocol object, but gives each protocol object a | ||
33 | * chance to perform connection handshaking and initialization at a point | ||
34 | * where they know that they have a handle to an active Connection. | ||
35 | *@returns See onNewData | ||
36 | */ | ||
37 | virtual bool onNewConnection()=0; | ||
38 | |||
39 | virtual void onNewClientConnection(){}; | ||
40 | |||
41 | virtual void poll(){}; | ||
42 | |||
43 | /** | ||
44 | * Sets the Protocol's Connection object. This is rather important, and | ||
45 | * handled usually by the ConnectionManager. | ||
46 | *@param pNewConnection The Connection object that this protocol will use to | ||
47 | * deal with the outside world. | ||
48 | */ | ||
49 | void setConnection( class Connection *pNewConnection ); | ||
50 | |||
51 | /** | ||
52 | * Get a pointer to this object's Connection object, or NULL if one was | ||
53 | * never set. If used with the ConnectionManager that should never happen. | ||
54 | *@returns A pointer to the active Connection. | ||
55 | */ | ||
56 | Connection *getConnection(); | ||
57 | |||
58 | private: | ||
59 | class Connection *pConnection; /**< The pointer to the Connection. */ | ||
60 | }; | ||
61 | |||
62 | #endif | ||
diff --git a/src/old/protocoltelnet.cpp b/src/old/protocoltelnet.cpp new file mode 100644 index 0000000..b169a51 --- /dev/null +++ b/src/old/protocoltelnet.cpp | |||
@@ -0,0 +1,316 @@ | |||
1 | #include "protocoltelnet.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | ProtocolTelnet::ProtocolTelnet() | ||
5 | { | ||
6 | nTermType = termUnInited; | ||
7 | bEchoOn = true; | ||
8 | } | ||
9 | |||
10 | ProtocolTelnet::~ProtocolTelnet() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | bool ProtocolTelnet::onNewConnection() | ||
15 | { | ||
16 | Connection *pCon = getConnection(); | ||
17 | |||
18 | pCon->appendOutput( (char)IAC ); | ||
19 | pCon->appendOutput( (char)WILL ); | ||
20 | pCon->appendOutput( (char)SUPPRESSGA ); | ||
21 | |||
22 | pCon->appendOutput( (char)IAC ); | ||
23 | pCon->appendOutput( (char)DO ); | ||
24 | pCon->appendOutput( (char)SUPPRESSGA ); | ||
25 | |||
26 | pCon->appendOutput( (char)IAC ); | ||
27 | pCon->appendOutput( (char)DONT ); | ||
28 | pCon->appendOutput( (char)TERMTYPE ); | ||
29 | |||
30 | // pCon->appendOutput( IAC ); | ||
31 | // pCon->appendOutput( SB ); | ||
32 | // pCon->appendOutput( TERMTYPE ); | ||
33 | // pCon->appendOutput( 1 ); | ||
34 | // pCon->appendOutput( IAC ); | ||
35 | // pCon->appendOutput( SE ); | ||
36 | |||
37 | pCon->appendOutput( (char)IAC ); | ||
38 | pCon->appendOutput( (char)DONT ); | ||
39 | pCon->appendOutput( (char)ECHO ); | ||
40 | |||
41 | pCon->appendOutput( (char)IAC ); | ||
42 | pCon->appendOutput( (char)WILL ); | ||
43 | pCon->appendOutput( (char)ECHO ); | ||
44 | |||
45 | // 255(IAC),251(WILL),3 | ||
46 | return true; | ||
47 | } | ||
48 | |||
49 | bool ProtocolTelnet::onNewData() | ||
50 | { | ||
51 | Connection *pCon = getConnection(); | ||
52 | if( !pCon->hasInput() ) | ||
53 | { | ||
54 | return true; | ||
55 | } | ||
56 | |||
57 | int nInSize = pCon->getInputAmnt(); | ||
58 | char *lpInStr = (char *)pCon->getInput(); | ||
59 | |||
60 | // Here we interpret the basic commands and un-encapsulate them, so to | ||
61 | // speak. We'll allow this, even if the terminal is in raw mode, we | ||
62 | // just won't send anything in response... | ||
63 | for( int j = 0; j < nInSize; j++ ) | ||
64 | { | ||
65 | switch( (unsigned char)lpInStr[j] ) | ||
66 | { | ||
67 | case '\r': | ||
68 | fbEdited.appendData('\n'); | ||
69 | if( bEchoOn ) pCon->appendOutput("\n\r"); | ||
70 | break; | ||
71 | |||
72 | case '\n': | ||
73 | break; | ||
74 | |||
75 | case '\177': // backspace | ||
76 | if( fbEdited.getLength() > 0 ) | ||
77 | { | ||
78 | fbEdited.usedData( -1 ); // Delete one char from the end | ||
79 | if( bEchoOn ) pCon->appendOutput(ESC "[D"); // Move the cursor back one | ||
80 | if( bEchoOn ) pCon->appendOutput(ESC "[P"); // Delete one character | ||
81 | } | ||
82 | break; | ||
83 | |||
84 | case '\x1B': // escape sequence | ||
85 | if( (unsigned char)lpInStr[j+1] == '[' ) | ||
86 | { | ||
87 | switch( (unsigned char)lpInStr[j+2] ) | ||
88 | { | ||
89 | case 'A': // Up | ||
90 | break; | ||
91 | |||
92 | case 'B': // Down | ||
93 | break; | ||
94 | |||
95 | case 'C': // Right | ||
96 | break; | ||
97 | |||
98 | case 'D': // Left | ||
99 | break; | ||
100 | } | ||
101 | j+=2; | ||
102 | } | ||
103 | break; | ||
104 | |||
105 | case 0: // NOP: No operation | ||
106 | break; | ||
107 | |||
108 | case IAC: // IAC: Interpret as command | ||
109 | switch( lpInStr[j+1] ) | ||
110 | { | ||
111 | case SE: // SE: End of subnegotiation parameters. | ||
112 | break; | ||
113 | |||
114 | case NOP: // NOP: No operation | ||
115 | break; | ||
116 | |||
117 | case DM: // DM: Data mark. Indicates the position of a Synch event within the data stream. This should always be accompanied by a TCP urgent notification. | ||
118 | break; | ||
119 | |||
120 | case BRK: // BRK: Break. Indicates that the "break" or "attention" key was hit. | ||
121 | break; | ||
122 | |||
123 | case IP: // IP: Suspend, interrupt or abort the process to which the NVT is connected. | ||
124 | break; | ||
125 | |||
126 | case AO: // AO: Abort output. Allows the current process to run to completion but do not send its output to the user. | ||
127 | break; | ||
128 | |||
129 | case AYT: // AYT: Are you there. Send back to the NVT some visible evidence that the AYT was received. | ||
130 | break; | ||
131 | |||
132 | case EC: // EC: Erase character. The receiver should delete the last preceding undeleted character from the data stream. | ||
133 | break; | ||
134 | |||
135 | case EL: // EL: Erase line. Delete characters from the data stream back to but not including the previous CRLF. | ||
136 | break; | ||
137 | |||
138 | case GA: // GA: Go ahead. Used, under certain circumstances, to tell the other end that it can transmit. | ||
139 | break; | ||
140 | |||
141 | case SB: // SB: Subnegotiation of the indicated option follows. | ||
142 | switch( lpInStr[j+2] ) | ||
143 | { | ||
144 | case TERMTYPE: | ||
145 | if( lpInStr[j+3] == 0 ) | ||
146 | { | ||
147 | for( int k = 0; j+4+k < nInSize; k++ ) | ||
148 | { | ||
149 | if( (unsigned char)lpInStr[j+4+k] == IAC && | ||
150 | (unsigned char)lpInStr[j+5+k] == SE ) | ||
151 | { | ||
152 | lpInStr[j+4+k] = 0; | ||
153 | //@TODO: Do something with the term type... | ||
154 | printf("Term type: %s\n", &lpInStr[j+4] ); | ||
155 | j += 5+k; | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | else | ||
160 | { | ||
161 | } | ||
162 | break; | ||
163 | |||
164 | default: | ||
165 | //printf("unknown subnegotiation parameters! (%d)\n", lpInStr[j+2] ); | ||
166 | break; | ||
167 | } | ||
168 | break; | ||
169 | |||
170 | case WILL: // WILL: Indicates the desire to begin performing | ||
171 | switch( lpInStr[j+2] ) | ||
172 | { | ||
173 | case SUPPRESSGA: | ||
174 | j += 2; | ||
175 | // pCon->usedInput( 3 ); | ||
176 | break; | ||
177 | |||
178 | case TERMTYPE: | ||
179 | j += 2; | ||
180 | // pCon->usedInput( 3 ); | ||
181 | break; | ||
182 | |||
183 | case ECHO: | ||
184 | j += 2; | ||
185 | // pCon->usedInput( 3 ); | ||
186 | break; | ||
187 | |||
188 | case NAWS: | ||
189 | default: | ||
190 | pCon->appendOutput( (char)ESC[0] ); | ||
191 | pCon->appendOutput( (char)DONT ); | ||
192 | pCon->appendOutput( lpInStr[j+2] ); | ||
193 | //printf("unknown will command used! (%d)\n", lpInStr[j+2] ); | ||
194 | j += 2; | ||
195 | break; | ||
196 | } | ||
197 | break; | ||
198 | |||
199 | case WONT: // WONT: Indicates the refusal to perform | ||
200 | switch( lpInStr[j+2] ) | ||
201 | { | ||
202 | case ECHO: | ||
203 | j += 2; | ||
204 | // pCon->usedInput( 3 ); | ||
205 | break; | ||
206 | |||
207 | default: | ||
208 | //printf("unknown wont command used! (%d)\n", lpInStr[j+2] ); | ||
209 | j += 2; | ||
210 | break; | ||
211 | } | ||
212 | break; | ||
213 | |||
214 | case DO: // DO: Indicates the request that the other party perform | ||
215 | switch( lpInStr[j+2] ) | ||
216 | { | ||
217 | case ECHO: | ||
218 | j += 2; | ||
219 | break; | ||
220 | |||
221 | case SUPPRESSGA: | ||
222 | j += 2; | ||
223 | break; | ||
224 | |||
225 | default: | ||
226 | pCon->appendOutput( (char)ESC[0] ); | ||
227 | pCon->appendOutput( (char)DONT ); | ||
228 | pCon->appendOutput( lpInStr[j+2] ); | ||
229 | //printf("unknown do command used! (%d)\n", lpInStr[j+2] ); | ||
230 | j += 2; | ||
231 | break; | ||
232 | } | ||
233 | // pCon->usedInput( 3 ); | ||
234 | break; | ||
235 | |||
236 | case DONT: // DONT: Indicates the demand that the other party stop performing | ||
237 | switch( lpInStr[j+2] ) | ||
238 | { | ||
239 | case ECHO: | ||
240 | j += 2; | ||
241 | // pCon->usedInput( 3 ); | ||
242 | break; | ||
243 | |||
244 | default: | ||
245 | printf("unknown dont command used! (%d)\n", lpInStr[j+2] ); | ||
246 | j += 2; | ||
247 | break; | ||
248 | } | ||
249 | break; | ||
250 | } | ||
251 | break; | ||
252 | |||
253 | default: | ||
254 | fbEdited.appendData( lpInStr[j] ); | ||
255 | if( bEchoOn ) pCon->appendOutput( lpInStr[j] ); | ||
256 | break; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | pCon->usedInput( pCon->getInputAmnt() ); | ||
261 | |||
262 | return true; | ||
263 | } | ||
264 | |||
265 | char *ProtocolTelnet::getLine( bool bFullOnly ) | ||
266 | { | ||
267 | int i = fbEdited.findChar('\n'); | ||
268 | |||
269 | if( i < 0 ) | ||
270 | { | ||
271 | if( bFullOnly == false ) | ||
272 | { | ||
273 | i = fbEdited.getLength(); | ||
274 | } | ||
275 | else | ||
276 | { | ||
277 | return NULL; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | char *lpStr = new char[i+1]; | ||
282 | strncpy( lpStr, fbEdited.getData(), i ); | ||
283 | lpStr[i] = '\0'; | ||
284 | |||
285 | fbEdited.usedData( i+1 ); | ||
286 | |||
287 | return lpStr; | ||
288 | } | ||
289 | |||
290 | char *ProtocolTelnet::peekLine( bool bFullOnly ) | ||
291 | { | ||
292 | int i = fbEdited.findChar('\n'); | ||
293 | |||
294 | if( i < 0 ) | ||
295 | { | ||
296 | if( bFullOnly == false ) | ||
297 | { | ||
298 | i = fbEdited.getLength(); | ||
299 | } | ||
300 | else | ||
301 | { | ||
302 | return NULL; | ||
303 | } | ||
304 | } | ||
305 | |||
306 | char *lpStr = new char[i+1]; | ||
307 | strncpy( lpStr, fbEdited.getData(), i ); | ||
308 | lpStr[i] = '\0'; | ||
309 | |||
310 | return lpStr; | ||
311 | } | ||
312 | |||
313 | void ProtocolTelnet::setEcho( bool bEchoOn ) | ||
314 | { | ||
315 | this->bEchoOn = bEchoOn; | ||
316 | } | ||
diff --git a/src/old/protocoltelnet.h b/src/old/protocoltelnet.h new file mode 100644 index 0000000..a6d2e49 --- /dev/null +++ b/src/old/protocoltelnet.h | |||
@@ -0,0 +1,77 @@ | |||
1 | #ifndef PROTOCOLTELNET_H | ||
2 | #define PROTOCOLTELNET_H | ||
3 | |||
4 | #include "protocol.h" | ||
5 | #include "flexbuf.h" | ||
6 | |||
7 | #define ESC "\x1B" /**< A telnet escape code. */ | ||
8 | |||
9 | /** Handles all specialized protocol actions related to the telnet protocol. | ||
10 | * This includes setting modes, non-scrollable regions, and so on. | ||
11 | *@author Mike Buland | ||
12 | */ | ||
13 | class ProtocolTelnet : public Protocol | ||
14 | { | ||
15 | public: | ||
16 | ProtocolTelnet(); | ||
17 | virtual ~ProtocolTelnet(); | ||
18 | |||
19 | bool onNewData(); | ||
20 | bool onNewConnection(); | ||
21 | |||
22 | char *getLine( bool bFullOnly = true ); | ||
23 | char *peekLine( bool bFullOnly = true ); | ||
24 | |||
25 | void setEcho( bool bEchoOn = true ); | ||
26 | |||
27 | enum | ||
28 | { | ||
29 | termUnInited, | ||
30 | termRaw, | ||
31 | termUnknown, | ||
32 | termVT220, | ||
33 | termXTerm | ||
34 | }; | ||
35 | |||
36 | enum | ||
37 | { | ||
38 | SE = 240, // SE: End of subnegotiation parameters. | ||
39 | NOP = 241, // NOP: No operation | ||
40 | DM = 242, // DM: Data mark. Indicates the position of a Synch event within the data stream. This should always be accompanied by a TCP urgent notification. | ||
41 | BRK = 243, // BRK: Break. Indicates that the "break" or "attention" key was hit. | ||
42 | IP = 244, // IP: Suspend, interrupt or abort the process to which the NVT is connected. | ||
43 | AO = 245, // AO: Abort output. Allows the current process to run to completion but do not send its output to the user. | ||
44 | AYT = 246, // AYT: Are you there. Send back to the NVT some visible evidence that the AYT was received. | ||
45 | EC = 247, // EC: Erase character. The receiver should delete the last preceding undeleted character from the data stream. | ||
46 | EL = 248, // EL: Erase line. Delete characters from the data stream back to but not including the previous CRLF. | ||
47 | GA = 249, // GA: Go ahead. Used, under certain circumstances, to tell the other end that it can transmit. | ||
48 | SB = 250, // SB: Subnegotiation of the indicated option follows. | ||
49 | WILL = 251, // WILL: Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option. | ||
50 | WONT = 252, // WONT: Indicates the refusal to perform, or continue performing, the indicated option. | ||
51 | DO = 253, // DO: Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option. | ||
52 | DONT = 254, // DONT: Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option. | ||
53 | IAC = 255 // IAC: Interpret as command | ||
54 | }; | ||
55 | |||
56 | enum | ||
57 | { | ||
58 | ECHO = 1, // Explain who'll echo | ||
59 | SUPPRESSGA = 3, // Suppress Go Ahead | ||
60 | TERMTYPE = 24, // Terminal Type | ||
61 | NAWS = 31, // Window size | ||
62 | TERMSPEED = 32, // Terminal Speed | ||
63 | LINEMODE = 34 // Linemode | ||
64 | }; | ||
65 | |||
66 | private: | ||
67 | int nTermType; | ||
68 | |||
69 | int nTermWidth; | ||
70 | int nTermHeight; | ||
71 | |||
72 | FlexBuf fbEdited; | ||
73 | |||
74 | bool bEchoOn; | ||
75 | }; | ||
76 | |||
77 | #endif | ||
diff --git a/src/old/queue.cpp b/src/old/queue.cpp new file mode 100644 index 0000000..42999fe --- /dev/null +++ b/src/old/queue.cpp | |||
@@ -0,0 +1,26 @@ | |||
1 | #include "queue.h" | ||
2 | |||
3 | void Queue::enqueue( void *data ) | ||
4 | { | ||
5 | lQueueData.append( data ); | ||
6 | } | ||
7 | |||
8 | void *Queue::dequeue() | ||
9 | { | ||
10 | void *dat = lQueueData[0]; | ||
11 | if( dat != NULL ) | ||
12 | { | ||
13 | lQueueData.deleteAt( 0 ); | ||
14 | } | ||
15 | return dat; | ||
16 | } | ||
17 | |||
18 | bool Queue::isEmpty() | ||
19 | { | ||
20 | return lQueueData.isEmpty(); | ||
21 | } | ||
22 | |||
23 | void Queue::empty() | ||
24 | { | ||
25 | lQueueData.empty(); | ||
26 | } | ||
diff --git a/src/old/queue.h b/src/old/queue.h new file mode 100644 index 0000000..692f5d8 --- /dev/null +++ b/src/old/queue.h | |||
@@ -0,0 +1,45 @@ | |||
1 | #ifndef QUEUE_H | ||
2 | #define QUEUE_H | ||
3 | #include "linkedlist.h" | ||
4 | |||
5 | /** | ||
6 | * An ultra-simple queue implementation. It just uses a linked list as it's | ||
7 | * container so we don't have to worry about anything! | ||
8 | *@author Mike Buland | ||
9 | */ | ||
10 | class Queue | ||
11 | { | ||
12 | public: | ||
13 | /** | ||
14 | * Puts a new item at the end of the queue. | ||
15 | *@param data A new value to put at the end of the queue. | ||
16 | */ | ||
17 | void enqueue( void *data ); | ||
18 | |||
19 | /** | ||
20 | * Gets the begining item of the queue off and returns it. | ||
21 | *@returns The value at the front of the queue. | ||
22 | */ | ||
23 | void *dequeue(); | ||
24 | |||
25 | /** | ||
26 | * Checks if the queueu is empty. | ||
27 | *@returns True if the queueu is empty, and false if it has things in it. | ||
28 | */ | ||
29 | bool isEmpty(); | ||
30 | |||
31 | /** | ||
32 | * Empty the queue. | ||
33 | */ | ||
34 | void empty(); | ||
35 | |||
36 | /** | ||
37 | * Get a pointer to the internal list object. | ||
38 | *@returns A pointer to the internal list object. | ||
39 | */ | ||
40 | LinkedList *getList() { return &lQueueData; }; | ||
41 | |||
42 | private: | ||
43 | LinkedList lQueueData; /**< Where all of the real data is stored. */ | ||
44 | }; | ||
45 | #endif | ||
diff --git a/src/old/ringlist.cpp b/src/old/ringlist.cpp new file mode 100644 index 0000000..9efbbc4 --- /dev/null +++ b/src/old/ringlist.cpp | |||
@@ -0,0 +1,106 @@ | |||
1 | // | ||
2 | // C++ Implementation: ringlist | ||
3 | // | ||
4 | // Description: | ||
5 | // | ||
6 | // | ||
7 | // Author: Mike Buland <eichlan@yf-soft.com>, (C) 2005 | ||
8 | // | ||
9 | // Copyright: See COPYING file that comes with this distribution | ||
10 | // | ||
11 | // | ||
12 | #include <stdlib.h> | ||
13 | |||
14 | #include "ringlist.h" | ||
15 | |||
16 | RingList::RingList( int nInitSize ) | ||
17 | : List() | ||
18 | { | ||
19 | nFirstIndex = 0; | ||
20 | nRealLength = nInitSize; | ||
21 | nDataLength = 0; | ||
22 | apData = new void*[nInitSize]; | ||
23 | pPushBuf = NULL; | ||
24 | } | ||
25 | |||
26 | RingList::~RingList() | ||
27 | { | ||
28 | delete[] apData; | ||
29 | } | ||
30 | |||
31 | void *RingList::getAt( int nIndex ) | ||
32 | { | ||
33 | if( nIndex < 0 || nIndex >= nDataLength ) | ||
34 | { | ||
35 | return NULL; | ||
36 | } | ||
37 | |||
38 | return apData[(nFirstIndex+nIndex)%nRealLength]; | ||
39 | } | ||
40 | |||
41 | void RingList::append( void *pData ) | ||
42 | { | ||
43 | int nIndex = (nFirstIndex+nDataLength)%nRealLength; | ||
44 | |||
45 | pPushBuf = apData[nIndex]; | ||
46 | apData[nIndex] = pData; | ||
47 | |||
48 | if( nDataLength == nRealLength ) | ||
49 | { | ||
50 | nFirstIndex = (nFirstIndex+1)%nRealLength; | ||
51 | } | ||
52 | else | ||
53 | { | ||
54 | nDataLength++; | ||
55 | // We really didn't need it this time... | ||
56 | pPushBuf = NULL; | ||
57 | } | ||
58 | } | ||
59 | |||
60 | void RingList::insertBefore( void *pData, int nPos ) | ||
61 | { | ||
62 | // Not implemented right now, don't even try it! | ||
63 | } | ||
64 | |||
65 | int RingList::getSize() | ||
66 | { | ||
67 | return nDataLength; | ||
68 | } | ||
69 | |||
70 | bool RingList::isEmpty() | ||
71 | { | ||
72 | return nDataLength==0; | ||
73 | } | ||
74 | |||
75 | void RingList::deleteAt( int nIndex ) | ||
76 | { | ||
77 | // Also not implemented yet | ||
78 | } | ||
79 | |||
80 | void RingList::empty() | ||
81 | { | ||
82 | nFirstIndex = 0; | ||
83 | nDataLength = 0; | ||
84 | } | ||
85 | |||
86 | void RingList::setSize( int nNewSize ) | ||
87 | { | ||
88 | if( apData ) | ||
89 | { | ||
90 | delete[] apData; | ||
91 | } | ||
92 | nFirstIndex = 0; | ||
93 | nRealLength = nNewSize; | ||
94 | nDataLength = 0; | ||
95 | apData = new void*[nNewSize]; | ||
96 | } | ||
97 | |||
98 | void RingList::setAt( int nIndex, void *pData ) | ||
99 | { | ||
100 | apData[(nIndex+nFirstIndex)%nRealLength] = pData; | ||
101 | } | ||
102 | |||
103 | void *RingList::getPushBuf() | ||
104 | { | ||
105 | return pPushBuf; | ||
106 | } | ||
diff --git a/src/old/ringlist.h b/src/old/ringlist.h new file mode 100644 index 0000000..bc069f3 --- /dev/null +++ b/src/old/ringlist.h | |||
@@ -0,0 +1,112 @@ | |||
1 | #ifndef RINGLIST_H | ||
2 | #define RINGLIST_H | ||
3 | |||
4 | #include "list.h" | ||
5 | |||
6 | /** | ||
7 | * A RingList or Ring Buffer implementation. This is a list that never grows in | ||
8 | * size once it is created, but instead once it is full new items added to the | ||
9 | * RingList replace the oldest items and the zero-index is virtually shifted. | ||
10 | * Since no data is actually moved when zero-index moves, this is very | ||
11 | * efficient. | ||
12 | * <br> | ||
13 | * The items removed are not actually deleted by the RingList, so instead they | ||
14 | * are first moved into a temporary "Push Buffer" that can be accessed so that | ||
15 | * elements pushed off the edge of the RingList can be accessed for cleanup. | ||
16 | *@author Mike Buland | ||
17 | */ | ||
18 | class RingList : public List | ||
19 | { | ||
20 | public: | ||
21 | /** | ||
22 | * Construct a RingList with a fixed initial size. This size never changes | ||
23 | * unless setSize is called later during normal operation. | ||
24 | *@param nInitSize The number of elements to allocate. | ||
25 | */ | ||
26 | RingList( int nInitSize ); | ||
27 | |||
28 | /** | ||
29 | * Clean up the data structures, but not the contained elements. | ||
30 | */ | ||
31 | virtual ~RingList(); | ||
32 | |||
33 | /** | ||
34 | * Get an element at the specified index. | ||
35 | *@param nIndex The index of the element to retreive. | ||
36 | *@returns A pointer to the requested element, or NULL if the element is | ||
37 | * not found or not initialized yet. | ||
38 | */ | ||
39 | void *getAt( int nIndex ); | ||
40 | |||
41 | /** | ||
42 | * Append an element to the end of the list, overwriting the begining if | ||
43 | * necesarry. | ||
44 | *@param pData The pointer to append to the RingList. | ||
45 | */ | ||
46 | void append( void *pData ); | ||
47 | |||
48 | /** | ||
49 | * Insert an element before another in the RingList, pushing all after it | ||
50 | * down the list. | ||
51 | *@param pData The data to insert. | ||
52 | *@param nPos The position that new the element should occupy in the list. | ||
53 | */ | ||
54 | void insertBefore( void *pData, int nPos = 0 ); | ||
55 | |||
56 | /** | ||
57 | * Get the size of the array. | ||
58 | */ | ||
59 | int getSize(); | ||
60 | |||
61 | /** | ||
62 | * Is the RingList empty? | ||
63 | *@returns True if it is empty, false otherwise. | ||
64 | */ | ||
65 | bool isEmpty(); | ||
66 | |||
67 | /** | ||
68 | * Delete an element in the list, moving all later elements down one index. | ||
69 | *@param nIndex The index of the element to delete. | ||
70 | */ | ||
71 | void deleteAt( int nIndex ); | ||
72 | |||
73 | /** | ||
74 | * Remove all elements from the RingList. | ||
75 | */ | ||
76 | void empty(); | ||
77 | |||
78 | /** | ||
79 | * Set a new size for the RingList. Be careful with this one, if shrinking | ||
80 | * this may quietly create a memory leak. | ||
81 | *@param nNewSize The new size to set the RingList to. | ||
82 | *@todo Either fix this memory leak somehow or remove this function. | ||
83 | */ | ||
84 | void setSize( int nNewSize ); | ||
85 | |||
86 | /** | ||
87 | * Set a specific element to a new value. | ||
88 | *@param nIndex The zero-based index to change the value of. | ||
89 | *@param pData The data to put at the location specified by nIndex. | ||
90 | */ | ||
91 | void setAt( int nIndex, void *pData ); | ||
92 | |||
93 | /** | ||
94 | * Retrieve the contents of the push buffer. This is the data that is | ||
95 | * pushed off the end of the array if you append data and the list is full. | ||
96 | * This should be checked after every append operation to be sure there | ||
97 | * isn't anything that needs deleting. | ||
98 | *@returns The last value pushed off the RingList, or NULL if nothing was | ||
99 | * pushed off. | ||
100 | */ | ||
101 | void *getPushBuf(); | ||
102 | |||
103 | private: | ||
104 | int nFirstIndex; /**< The index to be translated as zero. */ | ||
105 | int nRealLength; /**< The Amount of storage space available. */ | ||
106 | int nDataLength; /**< The number of elements filled in. */ | ||
107 | void **apData; /**< The actual data storage. */ | ||
108 | void *pPushBuf; /**< The push buffer. */ | ||
109 | |||
110 | }; | ||
111 | |||
112 | #endif | ||
diff --git a/src/old/sbuffer.cpp b/src/old/sbuffer.cpp new file mode 100644 index 0000000..f84f8a3 --- /dev/null +++ b/src/old/sbuffer.cpp | |||
@@ -0,0 +1,67 @@ | |||
1 | #include <string.h> | ||
2 | #include "sbuffer.h" | ||
3 | |||
4 | SBuffer::SBuffer() : | ||
5 | nPos( 0 ), | ||
6 | bOpen( true ) | ||
7 | { | ||
8 | } | ||
9 | |||
10 | SBuffer::~SBuffer() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | void SBuffer::close() | ||
15 | { | ||
16 | bOpen = false; | ||
17 | fbData.clearData(); | ||
18 | } | ||
19 | |||
20 | size_t SBuffer::read( char *pBuf, size_t nBytes ) | ||
21 | { | ||
22 | size_t nLeft = fbData.getLength() - nPos; | ||
23 | if( nBytes > nLeft ) | ||
24 | nBytes = nLeft; | ||
25 | |||
26 | if( nLeft == 0 ) | ||
27 | return 0; | ||
28 | |||
29 | memcpy( pBuf, fbData.getData()+nPos, nBytes ); | ||
30 | nPos += nBytes; | ||
31 | |||
32 | return nBytes; | ||
33 | } | ||
34 | |||
35 | size_t SBuffer::write( const char *pBuf, size_t nBytes ) | ||
36 | { | ||
37 | fbData.appendData( pBuf, nBytes ); | ||
38 | nPos += nBytes; | ||
39 | |||
40 | return nBytes; | ||
41 | } | ||
42 | |||
43 | long SBuffer::tell() | ||
44 | { | ||
45 | return nPos; | ||
46 | } | ||
47 | |||
48 | void SBuffer::seek( long offset ) | ||
49 | { | ||
50 | nPos += offset; | ||
51 | } | ||
52 | |||
53 | void SBuffer::setPos( long pos ) | ||
54 | { | ||
55 | nPos = pos; | ||
56 | } | ||
57 | |||
58 | void SBuffer::setPosEnd( long pos ) | ||
59 | { | ||
60 | nPos = fbData.getLength() - pos; | ||
61 | } | ||
62 | |||
63 | bool SBuffer::isEOS() | ||
64 | { | ||
65 | return nPos == fbData.getLength(); | ||
66 | } | ||
67 | |||
diff --git a/src/old/sbuffer.h b/src/old/sbuffer.h new file mode 100644 index 0000000..65feb71 --- /dev/null +++ b/src/old/sbuffer.h | |||
@@ -0,0 +1,40 @@ | |||
1 | #ifndef S_BUFFER_H | ||
2 | #define S_BUFFER_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | |||
6 | #include "stream.h" | ||
7 | #include "flexbuf.h" | ||
8 | |||
9 | class SBuffer : public Stream | ||
10 | { | ||
11 | public: | ||
12 | SBuffer(); | ||
13 | virtual ~SBuffer(); | ||
14 | |||
15 | virtual void close(); | ||
16 | virtual size_t read( char *pBuf, size_t nBytes ); | ||
17 | |||
18 | /** | ||
19 | *@todo Update this to write at nPos, not just append data. | ||
20 | */ | ||
21 | virtual size_t write( const char *pBuf, size_t nBytes ); | ||
22 | |||
23 | virtual long tell(); | ||
24 | virtual void seek( long offset ); | ||
25 | virtual void setPos( long pos ); | ||
26 | virtual void setPosEnd( long pos ); | ||
27 | virtual bool isEOS(); | ||
28 | |||
29 | FlexBuf &getBuffer() | ||
30 | { | ||
31 | return fbData; | ||
32 | } | ||
33 | |||
34 | private: | ||
35 | long nPos; | ||
36 | bool bOpen; | ||
37 | FlexBuf fbData; | ||
38 | }; | ||
39 | |||
40 | #endif | ||
diff --git a/src/old/serializable.cpp b/src/old/serializable.cpp new file mode 100644 index 0000000..fd50943 --- /dev/null +++ b/src/old/serializable.cpp | |||
@@ -0,0 +1,8 @@ | |||
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 new file mode 100644 index 0000000..06def29 --- /dev/null +++ b/src/old/serializable.h | |||
@@ -0,0 +1,34 @@ | |||
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.cpp b/src/old/serializer.cpp new file mode 100644 index 0000000..636224e --- /dev/null +++ b/src/old/serializer.cpp | |||
@@ -0,0 +1,338 @@ | |||
1 | #include "serializer.h" | ||
2 | #include "serializable.h" | ||
3 | #include <list> | ||
4 | |||
5 | Serializer::Serializer(bool bLoading): | ||
6 | bLoading(bLoading) | ||
7 | { | ||
8 | } | ||
9 | Serializer::~Serializer() | ||
10 | { | ||
11 | } | ||
12 | |||
13 | bool Serializer::isLoading() | ||
14 | { | ||
15 | return bLoading; | ||
16 | } | ||
17 | Serializer &Serializer::operator<<(bool p) | ||
18 | { | ||
19 | write( &p, sizeof(p) ); | ||
20 | return *this; | ||
21 | } | ||
22 | Serializer &Serializer::operator<<(int8_t p) | ||
23 | { | ||
24 | write( &p, sizeof(p) ); | ||
25 | return *this; | ||
26 | } | ||
27 | Serializer &Serializer::operator<<(int16_t p) | ||
28 | { | ||
29 | write( &p, sizeof(p) ); | ||
30 | return *this; | ||
31 | } | ||
32 | Serializer &Serializer::operator<<(int32_t p) | ||
33 | { | ||
34 | write( &p, sizeof(p) ); | ||
35 | return *this; | ||
36 | } | ||
37 | Serializer &Serializer::operator<<(int64_t p) | ||
38 | { | ||
39 | write( &p, sizeof(p) ); | ||
40 | return *this; | ||
41 | } | ||
42 | Serializer &Serializer::operator<<(uint8_t p) | ||
43 | { | ||
44 | write( &p, sizeof(p) ); | ||
45 | return *this; | ||
46 | } | ||
47 | Serializer &Serializer::operator<<(uint16_t p) | ||
48 | { | ||
49 | write( &p, sizeof(p) ); | ||
50 | return *this; | ||
51 | } | ||
52 | Serializer &Serializer::operator<<(uint32_t p) | ||
53 | { | ||
54 | write( &p, sizeof(p) ); | ||
55 | return *this; | ||
56 | } | ||
57 | Serializer &Serializer::operator<<(uint64_t p) | ||
58 | { | ||
59 | write( &p, sizeof(p) ); | ||
60 | return *this; | ||
61 | } | ||
62 | Serializer &Serializer::operator<<(long p) | ||
63 | { | ||
64 | write( &p, sizeof(p) ); | ||
65 | return *this; | ||
66 | } | ||
67 | Serializer &Serializer::operator<<(float p) | ||
68 | { | ||
69 | write( &p, sizeof(p) ); | ||
70 | return *this; | ||
71 | } | ||
72 | Serializer &Serializer::operator<<(double p) | ||
73 | { | ||
74 | write( &p, sizeof(p) ); | ||
75 | return *this; | ||
76 | } | ||
77 | Serializer &Serializer::operator<<(long double p) | ||
78 | { | ||
79 | write( &p, sizeof(p) ); | ||
80 | return *this; | ||
81 | } | ||
82 | |||
83 | Serializer &Serializer::operator>>(bool &p) | ||
84 | { | ||
85 | read( &p, sizeof(p) ); | ||
86 | return *this; | ||
87 | } | ||
88 | Serializer &Serializer::operator>>(int8_t &p) | ||
89 | { | ||
90 | read( &p, sizeof(p) ); | ||
91 | return *this; | ||
92 | } | ||
93 | Serializer &Serializer::operator>>(int16_t &p) | ||
94 | { | ||
95 | read( &p, sizeof(p) ); | ||
96 | return *this; | ||
97 | } | ||
98 | Serializer &Serializer::operator>>(int32_t &p) | ||
99 | { | ||
100 | read( &p, sizeof(p) ); | ||
101 | return *this; | ||
102 | } | ||
103 | Serializer &Serializer::operator>>(int64_t &p) | ||
104 | { | ||
105 | read( &p, sizeof(p) ); | ||
106 | return *this; | ||
107 | } | ||
108 | Serializer &Serializer::operator>>(uint8_t &p) | ||
109 | { | ||
110 | read( &p, sizeof(p) ); | ||
111 | return *this; | ||
112 | } | ||
113 | Serializer &Serializer::operator>>(uint16_t &p) | ||
114 | { | ||
115 | read( &p, sizeof(p) ); | ||
116 | return *this; | ||
117 | } | ||
118 | Serializer &Serializer::operator>>(uint32_t &p) | ||
119 | { | ||
120 | read( &p, sizeof(p) ); | ||
121 | return *this; | ||
122 | } | ||
123 | Serializer &Serializer::operator>>(uint64_t &p) | ||
124 | { | ||
125 | read( &p, sizeof(p) ); | ||
126 | return *this; | ||
127 | } | ||
128 | Serializer &Serializer::operator>>(long &p) | ||
129 | { | ||
130 | read( &p, sizeof(p) ); | ||
131 | return *this; | ||
132 | } | ||
133 | Serializer &Serializer::operator>>(float &p) | ||
134 | { | ||
135 | read( &p, sizeof(p) ); | ||
136 | return *this; | ||
137 | } | ||
138 | Serializer &Serializer::operator>>(double &p) | ||
139 | { | ||
140 | read( &p, sizeof(p) ); | ||
141 | return *this; | ||
142 | } | ||
143 | Serializer &Serializer::operator>>(long double &p) | ||
144 | { | ||
145 | read( &p, sizeof(p) ); | ||
146 | return *this; | ||
147 | } | ||
148 | |||
149 | Serializer &Serializer::operator&&(bool &p) | ||
150 | { | ||
151 | if (bLoading) | ||
152 | { | ||
153 | return *this >> p; | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | return *this << p; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | Serializer &Serializer::operator&&(int8_t &p) | ||
162 | { | ||
163 | if (bLoading) | ||
164 | { | ||
165 | return *this >> p; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | return *this << p; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | Serializer &Serializer::operator&&(int16_t &p) | ||
174 | { | ||
175 | if (bLoading) | ||
176 | { | ||
177 | return *this >> p; | ||
178 | } | ||
179 | else | ||
180 | { | ||
181 | return *this << p; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | Serializer &Serializer::operator&&(int32_t &p) | ||
186 | { | ||
187 | if (bLoading) | ||
188 | { | ||
189 | return *this >> p; | ||
190 | } | ||
191 | else | ||
192 | { | ||
193 | return *this << p; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | Serializer &Serializer::operator&&(int64_t &p) | ||
198 | { | ||
199 | if (bLoading) | ||
200 | { | ||
201 | return *this >> p; | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | return *this << p; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | Serializer &Serializer::operator&&(uint8_t &p) | ||
210 | { | ||
211 | if (bLoading) | ||
212 | { | ||
213 | return *this >> p; | ||
214 | } | ||
215 | else | ||
216 | { | ||
217 | return *this << p; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | Serializer &Serializer::operator&&(uint16_t &p) | ||
222 | { | ||
223 | if (bLoading) | ||
224 | { | ||
225 | return *this >> p; | ||
226 | } | ||
227 | else | ||
228 | { | ||
229 | return *this << p; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | Serializer &Serializer::operator&&(uint32_t &p) | ||
234 | { | ||
235 | if (bLoading) | ||
236 | { | ||
237 | return *this >> p; | ||
238 | } | ||
239 | else | ||
240 | { | ||
241 | return *this << p; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | Serializer &Serializer::operator&&(uint64_t &p) | ||
246 | { | ||
247 | if (bLoading) | ||
248 | { | ||
249 | return *this >> p; | ||
250 | } | ||
251 | else | ||
252 | { | ||
253 | return *this << p; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | Serializer &Serializer::operator&&(float &p) | ||
258 | { | ||
259 | if (bLoading) | ||
260 | { | ||
261 | return *this >> p; | ||
262 | } | ||
263 | else | ||
264 | { | ||
265 | return *this << p; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | Serializer &Serializer::operator&&(double &p) | ||
270 | { | ||
271 | if (bLoading) | ||
272 | { | ||
273 | return *this >> p; | ||
274 | } | ||
275 | else | ||
276 | { | ||
277 | return *this << p; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | Serializer &Serializer::operator&&(long double &p) | ||
282 | { | ||
283 | if (bLoading) | ||
284 | { | ||
285 | return *this >> p; | ||
286 | } | ||
287 | else | ||
288 | { | ||
289 | return *this << p; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | |||
294 | Serializer &operator<<(Serializer &s, Serializable &p) | ||
295 | { | ||
296 | p.serialize( s ); | ||
297 | return s; | ||
298 | } | ||
299 | |||
300 | Serializer &operator>>(Serializer &s, Serializable &p) | ||
301 | { | ||
302 | p.serialize( s ); | ||
303 | return s; | ||
304 | } | ||
305 | |||
306 | Serializer &operator&&(Serializer &s, Serializable &p) | ||
307 | { | ||
308 | if (s.isLoading()) | ||
309 | { | ||
310 | return s >> p; | ||
311 | } | ||
312 | else | ||
313 | { | ||
314 | return s << p; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | Serializer &operator<<( Serializer &ar, std::string &s ) | ||
319 | { | ||
320 | ar << (uint32_t)s.length(); | ||
321 | ar.write( s.c_str(), s.length() ); | ||
322 | |||
323 | return ar; | ||
324 | } | ||
325 | |||
326 | Serializer &operator>>( Serializer &ar, std::string &s ) | ||
327 | { | ||
328 | uint32_t l; | ||
329 | ar >> l; | ||
330 | char *tmp = new char[l+1]; | ||
331 | tmp[l] = '\0'; | ||
332 | ar.read( tmp, l ); | ||
333 | s = tmp; | ||
334 | delete[] tmp; | ||
335 | |||
336 | return ar; | ||
337 | } | ||
338 | |||
diff --git a/src/old/serializer.h b/src/old/serializer.h new file mode 100644 index 0000000..3af489c --- /dev/null +++ b/src/old/serializer.h | |||
@@ -0,0 +1,80 @@ | |||
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/serializerbinary.cpp b/src/old/serializerbinary.cpp new file mode 100644 index 0000000..ea7ed93 --- /dev/null +++ b/src/old/serializerbinary.cpp | |||
@@ -0,0 +1,63 @@ | |||
1 | #include "serializerbinary.h" | ||
2 | #include "serializable.h" | ||
3 | #include "exceptions.h" | ||
4 | |||
5 | SerializerBinary::SerializerBinary(FILE *fhFile, bool bLoading): | ||
6 | Serializer(bLoading), | ||
7 | fhFile(fhFile), | ||
8 | bCloseFile(false) | ||
9 | { | ||
10 | } | ||
11 | |||
12 | SerializerBinary::SerializerBinary(const char *sFileName, bool bLoading): | ||
13 | Serializer(bLoading), | ||
14 | bCloseFile(true) | ||
15 | { | ||
16 | if (bLoading) | ||
17 | { | ||
18 | fhFile = fopen(sFileName, "rb"); | ||
19 | if( fhFile == NULL ) | ||
20 | throw FileException("Unable to open file: %s", sFileName ); | ||
21 | } | ||
22 | else | ||
23 | { | ||
24 | fhFile = fopen(sFileName, "wb"); | ||
25 | if( fhFile == NULL ) | ||
26 | throw FileException("Unable to open file: %s", sFileName ); | ||
27 | } | ||
28 | } | ||
29 | |||
30 | SerializerBinary::~SerializerBinary() | ||
31 | { | ||
32 | close(); | ||
33 | } | ||
34 | |||
35 | void SerializerBinary::close() | ||
36 | { | ||
37 | if (fhFile != NULL && bCloseFile ) | ||
38 | { | ||
39 | fclose(fhFile); | ||
40 | fhFile = NULL; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | void SerializerBinary::write(const void * pData, int32_t nSize) | ||
45 | { | ||
46 | if( nSize == 0 ) | ||
47 | return; | ||
48 | |||
49 | fwrite(pData, nSize, 1, fhFile); | ||
50 | } | ||
51 | |||
52 | void SerializerBinary::read(void * pData, int32_t nSize) | ||
53 | { | ||
54 | if( nSize == 0 ) | ||
55 | return; | ||
56 | |||
57 | uint32_t nRead = fread(pData, nSize, 1, fhFile); | ||
58 | if( nRead < 1 ) | ||
59 | { | ||
60 | throw FileException( excodeEOF, "End of file read"); | ||
61 | } | ||
62 | } | ||
63 | |||
diff --git a/src/old/serializerbinary.h b/src/old/serializerbinary.h new file mode 100644 index 0000000..8510fcd --- /dev/null +++ b/src/old/serializerbinary.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef SERIALIZER_BINARY_H | ||
2 | #define SERIALIZER_BINARY_H | ||
3 | |||
4 | #include "serializer.h" | ||
5 | #include <stdio.h> | ||
6 | |||
7 | class SerializerBinary : public Serializer | ||
8 | { | ||
9 | public: | ||
10 | SerializerBinary(FILE *fhFile, bool bLoading); | ||
11 | SerializerBinary(const char *sFileName, bool bLoading); | ||
12 | virtual ~SerializerBinary(); | ||
13 | |||
14 | virtual void close(); | ||
15 | |||
16 | virtual void write(const void *, int32_t); | ||
17 | virtual void read(void *, int32_t); | ||
18 | |||
19 | private: | ||
20 | FILE *fhFile; | ||
21 | bool bCloseFile; | ||
22 | }; | ||
23 | |||
24 | #endif | ||
diff --git a/src/old/serializerbzip2.cpp b/src/old/serializerbzip2.cpp new file mode 100644 index 0000000..bafabc8 --- /dev/null +++ b/src/old/serializerbzip2.cpp | |||
@@ -0,0 +1,88 @@ | |||
1 | #include "serializerbzip2.h" | ||
2 | #include "serializable.h" | ||
3 | |||
4 | #include <bzlib.h> | ||
5 | |||
6 | SerializerBZip2::SerializerBZip2(FILE *fhFile, bool bLoading): | ||
7 | Serializer(bLoading), | ||
8 | fhFile(fhFile), | ||
9 | bCloseFile(false) | ||
10 | { | ||
11 | if( bLoading ) | ||
12 | { | ||
13 | bzFile = BZ2_bzReadOpen( &bzerror, fhFile, 0, 0, NULL, 0 ); | ||
14 | checkBZError(); | ||
15 | } | ||
16 | else | ||
17 | { | ||
18 | bzFile = BZ2_bzWriteOpen( &bzerror, fhFile, 9, 0, 0 ); | ||
19 | checkBZError(); | ||
20 | } | ||
21 | } | ||
22 | |||
23 | SerializerBZip2::SerializerBZip2(char *sFileName, bool bLoading): | ||
24 | Serializer(bLoading), | ||
25 | bCloseFile(true) | ||
26 | { | ||
27 | if (bLoading) | ||
28 | { | ||
29 | fhFile = fopen(sFileName, "rb"); | ||
30 | bzFile = BZ2_bzReadOpen( &bzerror, fhFile, 0, 0, NULL, 0 ); | ||
31 | checkBZError(); | ||
32 | } | ||
33 | else | ||
34 | { | ||
35 | fhFile = fopen(sFileName, "wb"); | ||
36 | bzFile = BZ2_bzWriteOpen( &bzerror, fhFile, 9, 0, 0 ); | ||
37 | checkBZError(); | ||
38 | } | ||
39 | } | ||
40 | |||
41 | SerializerBZip2::~SerializerBZip2() | ||
42 | { | ||
43 | close(); | ||
44 | } | ||
45 | |||
46 | void SerializerBZip2::checkBZError() | ||
47 | { | ||
48 | } | ||
49 | |||
50 | void SerializerBZip2::close() | ||
51 | { | ||
52 | if( bzFile != NULL ) | ||
53 | { | ||
54 | if( isLoading() ) | ||
55 | { | ||
56 | void *unused; | ||
57 | int nUnused; | ||
58 | BZ2_bzReadGetUnused( &bzerror, bzFile, &unused, &nUnused ); | ||
59 | BZ2_bzReadClose( &bzerror, bzFile ); | ||
60 | if( nUnused ) | ||
61 | fseek( fhFile, -nUnused, SEEK_CUR ); | ||
62 | } | ||
63 | else | ||
64 | { | ||
65 | BZ2_bzWriteClose( &bzerror, bzFile, 0, 0, 0 ); | ||
66 | } | ||
67 | checkBZError(); | ||
68 | bzFile = NULL; | ||
69 | } | ||
70 | if( fhFile != NULL && bCloseFile ) | ||
71 | { | ||
72 | fclose(fhFile); | ||
73 | fhFile = NULL; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | void SerializerBZip2::write(const void * pData, int32_t nSize) | ||
78 | { | ||
79 | BZ2_bzWrite( &bzerror, bzFile, (void *)pData, nSize ); | ||
80 | checkBZError(); | ||
81 | } | ||
82 | |||
83 | void SerializerBZip2::read(void * pData, int32_t nSize) | ||
84 | { | ||
85 | BZ2_bzRead( &bzerror, bzFile, pData, nSize ); | ||
86 | checkBZError(); | ||
87 | } | ||
88 | |||
diff --git a/src/old/serializerbzip2.h b/src/old/serializerbzip2.h new file mode 100644 index 0000000..4aeb22e --- /dev/null +++ b/src/old/serializerbzip2.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef SERIALIZER_BINARY_H | ||
2 | #define SERIALIZER_BINARY_H | ||
3 | |||
4 | #include "serializer.h" | ||
5 | #include <stdio.h> | ||
6 | |||
7 | class SerializerBZip2 : public Serializer | ||
8 | { | ||
9 | public: | ||
10 | SerializerBZip2(FILE *fhFile, bool bLoading); | ||
11 | SerializerBZip2(char *sFileName, bool bLoading); | ||
12 | virtual ~SerializerBZip2(); | ||
13 | |||
14 | virtual void close(); | ||
15 | |||
16 | virtual void write(const void *, int32_t); | ||
17 | virtual void read(void *, int32_t); | ||
18 | |||
19 | private: | ||
20 | void checkBZError(); | ||
21 | FILE *fhFile; | ||
22 | void *bzFile; | ||
23 | bool bCloseFile; | ||
24 | int bzerror; | ||
25 | }; | ||
26 | |||
27 | #endif | ||
diff --git a/src/old/serializerconnection.cpp b/src/old/serializerconnection.cpp new file mode 100644 index 0000000..2934c8b --- /dev/null +++ b/src/old/serializerconnection.cpp | |||
@@ -0,0 +1,15 @@ | |||
1 | #include "serializerconnection.h" | ||
2 | |||
3 | SerializerConnection::SerializerConnection( | ||
4 | Connection *pCon, bool bIO, int nTimeSec, int nTimeUSec ) : | ||
5 | Serializer( bIO ), | ||
6 | pCon( pCon ), | ||
7 | nTimeSec( nTimeSec ), | ||
8 | nTimeUSec( nTimeUSec ) | ||
9 | { | ||
10 | } | ||
11 | |||
12 | SerializerConnection::~SerializerConnection() | ||
13 | { | ||
14 | } | ||
15 | |||
diff --git a/src/old/serializerconnection.h b/src/old/serializerconnection.h new file mode 100644 index 0000000..e8d85c6 --- /dev/null +++ b/src/old/serializerconnection.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef SERIALIZER_CONNECTION_H | ||
2 | #define SERIALIZER_CONNECTION_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | |||
6 | #include "serializer.h" | ||
7 | #include "connection.h" | ||
8 | |||
9 | /** | ||
10 | * | ||
11 | */ | ||
12 | class SerializerConnection : public Serializer | ||
13 | { | ||
14 | public: | ||
15 | SerializerConnection( Connection *pCon, bool bIO, int nTimeSec, int nTimeUSec ); | ||
16 | virtual ~SerializerConnection(); | ||
17 | |||
18 | private: | ||
19 | Connection *pCon; | ||
20 | int nTimeSec; | ||
21 | int nTimeUSec; | ||
22 | }; | ||
23 | |||
24 | #endif | ||
diff --git a/src/old/serializertext.cpp b/src/old/serializertext.cpp new file mode 100644 index 0000000..9cf4394 --- /dev/null +++ b/src/old/serializertext.cpp | |||
@@ -0,0 +1,170 @@ | |||
1 | #include "serializertext.h" | ||
2 | |||
3 | SerializerText::SerializerText(FILE *fhFile, bool bLoading): | ||
4 | Serializer(bLoading), | ||
5 | fhFile(fhFile), | ||
6 | bCloseFile(false) | ||
7 | { | ||
8 | } | ||
9 | |||
10 | SerializerText::SerializerText(const char *sFileName, bool bLoading): | ||
11 | Serializer(bLoading), | ||
12 | bCloseFile(true) | ||
13 | { | ||
14 | if (bLoading) | ||
15 | { | ||
16 | fhFile = fopen(sFileName, "rt"); | ||
17 | } | ||
18 | else | ||
19 | { | ||
20 | fhFile = fopen(sFileName, "wt"); | ||
21 | } | ||
22 | } | ||
23 | |||
24 | SerializerText::~SerializerText() | ||
25 | { | ||
26 | close(); | ||
27 | } | ||
28 | |||
29 | void SerializerText::close() | ||
30 | { | ||
31 | if (fhFile != NULL) | ||
32 | { | ||
33 | fclose(fhFile); | ||
34 | fhFile = NULL; | ||
35 | } | ||
36 | } | ||
37 | |||
38 | void SerializerText::write(const void * pData, int32_t nSize) | ||
39 | { | ||
40 | fwrite(pData, nSize, 1, fhFile); | ||
41 | fprintf(fhFile, "\n"); | ||
42 | } | ||
43 | |||
44 | void SerializerText::read(void * pData, int32_t nSize) | ||
45 | { | ||
46 | fread(pData, nSize, 1, fhFile); | ||
47 | fgetc(fhFile); | ||
48 | } | ||
49 | |||
50 | Serializer &SerializerText::operator<<(bool p) | ||
51 | { | ||
52 | fprintf(fhFile, "%hhd\n", p); | ||
53 | return *this; | ||
54 | } | ||
55 | Serializer &SerializerText::operator<<(int8_t p) | ||
56 | { | ||
57 | fprintf(fhFile, "%hhd\n", p); | ||
58 | return *this; | ||
59 | } | ||
60 | Serializer &SerializerText::operator<<(int16_t p) | ||
61 | { | ||
62 | fprintf(fhFile, "%hd\n", p); | ||
63 | return *this; | ||
64 | } | ||
65 | Serializer &SerializerText::operator<<(int32_t p) | ||
66 | { | ||
67 | fprintf(fhFile, "%d\n", p); | ||
68 | return *this; | ||
69 | } | ||
70 | Serializer &SerializerText::operator<<(int64_t p) | ||
71 | { | ||
72 | fprintf(fhFile, "%lld\n", p); | ||
73 | return *this; | ||
74 | } | ||
75 | Serializer &SerializerText::operator<<(uint8_t p) | ||
76 | { | ||
77 | fprintf(fhFile, "%hhu\n", p); | ||
78 | return *this; | ||
79 | } | ||
80 | Serializer &SerializerText::operator<<(uint16_t p) | ||
81 | { | ||
82 | fprintf(fhFile, "%hu\n", p); | ||
83 | return *this; | ||
84 | } | ||
85 | Serializer &SerializerText::operator<<(uint32_t p) | ||
86 | { | ||
87 | fprintf(fhFile, "%u\n", p); | ||
88 | return *this; | ||
89 | } | ||
90 | Serializer &SerializerText::operator<<(uint64_t p) | ||
91 | { | ||
92 | fprintf(fhFile, "%llu\n", p); | ||
93 | return *this; | ||
94 | } | ||
95 | Serializer &SerializerText::operator<<(float p) | ||
96 | { | ||
97 | fprintf(fhFile, "%f\n", p); | ||
98 | return *this; | ||
99 | } | ||
100 | Serializer &SerializerText::operator<<(double p) | ||
101 | { | ||
102 | fprintf(fhFile, "%f\n", p); | ||
103 | return *this; | ||
104 | } | ||
105 | Serializer &SerializerText::operator<<(long double p) | ||
106 | { | ||
107 | fprintf(fhFile, "%Lf\n", p); | ||
108 | return *this; | ||
109 | } | ||
110 | |||
111 | Serializer &SerializerText::operator>>(bool &p) | ||
112 | { | ||
113 | fscanf(fhFile, "%hhd\n", ((signed char *)&p)); | ||
114 | return *this; | ||
115 | } | ||
116 | Serializer &SerializerText::operator>>(int8_t &p) | ||
117 | { | ||
118 | fscanf(fhFile, "%hhd\n", &p); | ||
119 | return *this; | ||
120 | } | ||
121 | Serializer &SerializerText::operator>>(int16_t &p) | ||
122 | { | ||
123 | fscanf(fhFile, "%hd\n", &p); | ||
124 | return *this; | ||
125 | } | ||
126 | Serializer &SerializerText::operator>>(int32_t &p) | ||
127 | { | ||
128 | fscanf(fhFile, "%d\n", &p); | ||
129 | return *this; | ||
130 | } | ||
131 | Serializer &SerializerText::operator>>(int64_t &p) | ||
132 | { | ||
133 | fscanf(fhFile, "%lld\n", &p); | ||
134 | return *this; | ||
135 | } | ||
136 | Serializer &SerializerText::operator>>(uint8_t &p) | ||
137 | { | ||
138 | fscanf(fhFile, "%hhu\n", &p); | ||
139 | return *this; | ||
140 | } | ||
141 | Serializer &SerializerText::operator>>(uint16_t &p) | ||
142 | { | ||
143 | fscanf(fhFile, "%hu\n", &p); | ||
144 | return *this; | ||
145 | } | ||
146 | Serializer &SerializerText::operator>>(uint32_t &p) | ||
147 | { | ||
148 | fscanf(fhFile, "%u\n", &p); | ||
149 | return *this; | ||
150 | } | ||
151 | Serializer &SerializerText::operator>>(uint64_t &p) | ||
152 | { | ||
153 | fscanf(fhFile, "%llu\n", &p); | ||
154 | return *this; | ||
155 | } | ||
156 | Serializer &SerializerText::operator>>(float &p) | ||
157 | { | ||
158 | fscanf(fhFile, "%f\n", &p); | ||
159 | return *this; | ||
160 | } | ||
161 | Serializer &SerializerText::operator>>(double &p) | ||
162 | { | ||
163 | fscanf(fhFile, "%lf\n", &p); | ||
164 | return *this; | ||
165 | } | ||
166 | Serializer &SerializerText::operator>>(long double &p) | ||
167 | { | ||
168 | fscanf(fhFile, "%Lf\n", &p); | ||
169 | return *this; | ||
170 | } | ||
diff --git a/src/old/serializertext.h b/src/old/serializertext.h new file mode 100644 index 0000000..01b7f7b --- /dev/null +++ b/src/old/serializertext.h | |||
@@ -0,0 +1,49 @@ | |||
1 | #ifndef SERIALIZER_TEXT_H | ||
2 | #define SERIALIZER_TEXT_H | ||
3 | |||
4 | #include "serializer.h" | ||
5 | #include <stdio.h> | ||
6 | |||
7 | class SerializerText : public Serializer | ||
8 | { | ||
9 | public: | ||
10 | SerializerText(FILE *fhFile, bool bLoading); | ||
11 | SerializerText(const char *sFileName, bool bLoading); | ||
12 | virtual ~SerializerText(); | ||
13 | |||
14 | virtual void close(); | ||
15 | |||
16 | virtual void write(const void *, int32_t); | ||
17 | virtual void read(void *, int32_t); | ||
18 | |||
19 | virtual Serializer &operator<<(bool); | ||
20 | virtual Serializer &operator<<(int8_t); | ||
21 | virtual Serializer &operator<<(int16_t); | ||
22 | virtual Serializer &operator<<(int32_t); | ||
23 | virtual Serializer &operator<<(int64_t); | ||
24 | virtual Serializer &operator<<(uint8_t); | ||
25 | virtual Serializer &operator<<(uint16_t); | ||
26 | virtual Serializer &operator<<(uint32_t); | ||
27 | virtual Serializer &operator<<(uint64_t); | ||
28 | virtual Serializer &operator<<(float); | ||
29 | virtual Serializer &operator<<(double); | ||
30 | virtual Serializer &operator<<(long double); | ||
31 | |||
32 | virtual Serializer &operator>>(bool &); | ||
33 | virtual Serializer &operator>>(int8_t &); | ||
34 | virtual Serializer &operator>>(int16_t &); | ||
35 | virtual Serializer &operator>>(int32_t &); | ||
36 | virtual Serializer &operator>>(int64_t &); | ||
37 | virtual Serializer &operator>>(uint8_t &); | ||
38 | virtual Serializer &operator>>(uint16_t &); | ||
39 | virtual Serializer &operator>>(uint32_t &); | ||
40 | virtual Serializer &operator>>(uint64_t &); | ||
41 | virtual Serializer &operator>>(float &); | ||
42 | virtual Serializer &operator>>(double &); | ||
43 | virtual Serializer &operator>>(long double &); | ||
44 | private: | ||
45 | FILE *fhFile; | ||
46 | bool bCloseFile; | ||
47 | }; | ||
48 | |||
49 | #endif | ||
diff --git a/src/old/sfile.cpp b/src/old/sfile.cpp new file mode 100644 index 0000000..f1de03c --- /dev/null +++ b/src/old/sfile.cpp | |||
@@ -0,0 +1,74 @@ | |||
1 | #include "sfile.h" | ||
2 | #include "exceptions.h" | ||
3 | |||
4 | SFile::SFile( const char *sName, const char *sFlags ) | ||
5 | { | ||
6 | fh = fopen( sName, sFlags ); | ||
7 | } | ||
8 | |||
9 | SFile::~SFile() | ||
10 | { | ||
11 | } | ||
12 | |||
13 | void SFile::close() | ||
14 | { | ||
15 | if( fh ) | ||
16 | { | ||
17 | fclose( fh ); | ||
18 | fh = NULL; | ||
19 | } | ||
20 | } | ||
21 | |||
22 | size_t SFile::read( char *pBuf, size_t nBytes ) | ||
23 | { | ||
24 | if( !fh ) | ||
25 | throw FileException("File not open."); | ||
26 | |||
27 | return fread( pBuf, 1, nBytes, fh ); | ||
28 | } | ||
29 | |||
30 | size_t SFile::write( const char *pBuf, size_t nBytes ) | ||
31 | { | ||
32 | if( !fh ) | ||
33 | throw FileException("File not open."); | ||
34 | |||
35 | return fwrite( pBuf, 1, nBytes, fh ); | ||
36 | } | ||
37 | |||
38 | long SFile::tell() | ||
39 | { | ||
40 | if( !fh ) | ||
41 | throw FileException("File not open."); | ||
42 | |||
43 | return ftell( fh ); | ||
44 | } | ||
45 | |||
46 | void SFile::seek( long offset ) | ||
47 | { | ||
48 | if( !fh ) | ||
49 | throw FileException("File not open."); | ||
50 | |||
51 | fseek( fh, offset, SEEK_CUR ); | ||
52 | } | ||
53 | |||
54 | void SFile::setPos( long pos ) | ||
55 | { | ||
56 | if( !fh ) | ||
57 | throw FileException("File not open."); | ||
58 | |||
59 | fseek( fh, pos, SEEK_SET ); | ||
60 | } | ||
61 | |||
62 | void SFile::setPosEnd( long pos ) | ||
63 | { | ||
64 | if( !fh ) | ||
65 | throw FileException("File not open."); | ||
66 | |||
67 | fseek( fh, pos, SEEK_END ); | ||
68 | } | ||
69 | |||
70 | bool SFile::isEOS() | ||
71 | { | ||
72 | return feof( fh ); | ||
73 | } | ||
74 | |||
diff --git a/src/old/sfile.h b/src/old/sfile.h new file mode 100644 index 0000000..b51e5bc --- /dev/null +++ b/src/old/sfile.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef SFILE_H | ||
2 | #define SFILE_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | |||
6 | #include "stream.h" | ||
7 | |||
8 | class SFile : public Stream | ||
9 | { | ||
10 | public: | ||
11 | SFile( const char *sName, const char *sFlags ); | ||
12 | virtual ~SFile(); | ||
13 | |||
14 | virtual void close(); | ||
15 | virtual size_t read( char *pBuf, size_t nBytes ); | ||
16 | virtual size_t write( const char *pBuf, size_t nBytes ); | ||
17 | |||
18 | virtual long tell(); | ||
19 | virtual void seek( long offset ); | ||
20 | virtual void setPos( long pos ); | ||
21 | virtual void setPosEnd( long pos ); | ||
22 | virtual bool isEOS(); | ||
23 | |||
24 | private: | ||
25 | FILE *fh; | ||
26 | |||
27 | }; | ||
28 | |||
29 | #endif | ||
diff --git a/src/old/sha1.cpp b/src/old/sha1.cpp new file mode 100644 index 0000000..8270c3b --- /dev/null +++ b/src/old/sha1.cpp | |||
@@ -0,0 +1,161 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | #include <stdlib.h> | ||
4 | |||
5 | #include "sha1.h" | ||
6 | |||
7 | Sha1::Sha1() : | ||
8 | H0( 0x67452301 ), | ||
9 | H1( 0xefcdab89 ), | ||
10 | H2( 0x98badcfe ), | ||
11 | H3( 0x10325476 ), | ||
12 | H4( 0xc3d2e1f0 ), | ||
13 | unprocessedBytes( 0 ), | ||
14 | size( 0 ) | ||
15 | { | ||
16 | } | ||
17 | |||
18 | Sha1::~Sha1() | ||
19 | { | ||
20 | } | ||
21 | |||
22 | void Sha1::process() | ||
23 | { | ||
24 | int t; | ||
25 | uint32_t a, b, c, d, e, K, f, W[80]; | ||
26 | |||
27 | // starting values | ||
28 | a = H0; | ||
29 | b = H1; | ||
30 | c = H2; | ||
31 | d = H3; | ||
32 | e = H4; | ||
33 | |||
34 | // copy and expand the message block | ||
35 | for( t = 0; t < 16; t++ ) W[t] = (bytes[t*4] << 24) | ||
36 | +(bytes[t*4 + 1] << 16) | ||
37 | +(bytes[t*4 + 2] << 8) | ||
38 | + bytes[t*4 + 3]; | ||
39 | for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 ); | ||
40 | |||
41 | /* main loop */ | ||
42 | uint32_t temp; | ||
43 | for( t = 0; t < 80; t++ ) | ||
44 | { | ||
45 | if( t < 20 ) { | ||
46 | K = 0x5a827999; | ||
47 | f = (b & c) | ((~b) & d); | ||
48 | } else if( t < 40 ) { | ||
49 | K = 0x6ed9eba1; | ||
50 | f = b ^ c ^ d; | ||
51 | } else if( t < 60 ) { | ||
52 | K = 0x8f1bbcdc; | ||
53 | f = (b & c) | (b & d) | (c & d); | ||
54 | } else { | ||
55 | K = 0xca62c1d6; | ||
56 | f = b ^ c ^ d; | ||
57 | } | ||
58 | temp = lrot(a,5) + f + e + W[t] + K; | ||
59 | e = d; | ||
60 | d = c; | ||
61 | c = lrot(b,30); | ||
62 | b = a; | ||
63 | a = temp; | ||
64 | //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e ); | ||
65 | } | ||
66 | |||
67 | /* add variables */ | ||
68 | H0 += a; | ||
69 | H1 += b; | ||
70 | H2 += c; | ||
71 | H3 += d; | ||
72 | H4 += e; | ||
73 | |||
74 | //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); | ||
75 | /* all bytes have been processed */ | ||
76 | unprocessedBytes = 0; | ||
77 | } | ||
78 | |||
79 | void Sha1::update( const char* data, int num ) | ||
80 | { | ||
81 | // add these bytes to the running total | ||
82 | size += num; | ||
83 | |||
84 | // repeat until all data is processed | ||
85 | while( num > 0 ) | ||
86 | { | ||
87 | // number of bytes required to complete block | ||
88 | int needed = 64 - unprocessedBytes; | ||
89 | |||
90 | // number of bytes to copy (use smaller of two) | ||
91 | int toCopy = (num < needed) ? num : needed; | ||
92 | |||
93 | // Copy the bytes | ||
94 | memcpy( bytes + unprocessedBytes, data, toCopy ); | ||
95 | |||
96 | // Bytes have been copied | ||
97 | num -= toCopy; | ||
98 | data += toCopy; | ||
99 | unprocessedBytes += toCopy; | ||
100 | |||
101 | // there is a full block | ||
102 | if( unprocessedBytes == 64 ) process(); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | unsigned char* Sha1::getDigest() | ||
107 | { | ||
108 | // save the message size | ||
109 | uint32_t totalBitsL = size << 3; | ||
110 | uint32_t totalBitsH = size >> 29; | ||
111 | |||
112 | // add 0x80 to the message | ||
113 | update( "\x80", 1 ); | ||
114 | |||
115 | unsigned char footer[64] = { | ||
116 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
117 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
118 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
119 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
120 | |||
121 | // block has no room for 8-byte filesize, so finish it | ||
122 | if( unprocessedBytes > 56 ) | ||
123 | update( (char*)footer, 64 - unprocessedBytes); | ||
124 | |||
125 | // how many zeros do we need | ||
126 | int neededZeros = 56 - unprocessedBytes; | ||
127 | |||
128 | // store file size (in bits) in big-endian format | ||
129 | toBigEndian( totalBitsH, footer + neededZeros ); | ||
130 | toBigEndian( totalBitsL, footer + neededZeros + 4 ); | ||
131 | |||
132 | // finish the final block | ||
133 | update( (char*)footer, neededZeros + 8 ); | ||
134 | |||
135 | // allocate memory for the digest bytes | ||
136 | unsigned char* digest = new unsigned char[20]; | ||
137 | |||
138 | // copy the digest bytes | ||
139 | toBigEndian( H0, digest ); | ||
140 | toBigEndian( H1, digest + 4 ); | ||
141 | toBigEndian( H2, digest + 8 ); | ||
142 | toBigEndian( H3, digest + 12 ); | ||
143 | toBigEndian( H4, digest + 16 ); | ||
144 | |||
145 | // return the digest | ||
146 | return digest; | ||
147 | } | ||
148 | |||
149 | uint32_t Sha1::lrot( uint32_t x, int bits ) | ||
150 | { | ||
151 | return (x<<bits) | (x>>(32 - bits)); | ||
152 | }; | ||
153 | |||
154 | void Sha1::toBigEndian( uint32_t num, unsigned char* byte ) | ||
155 | { | ||
156 | byte[0] = (unsigned char)(num>>24); | ||
157 | byte[1] = (unsigned char)(num>>16); | ||
158 | byte[2] = (unsigned char)(num>>8); | ||
159 | byte[3] = (unsigned char)num; | ||
160 | } | ||
161 | |||
diff --git a/src/old/sha1.h b/src/old/sha1.h new file mode 100644 index 0000000..ab6081d --- /dev/null +++ b/src/old/sha1.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* sha1.h | ||
2 | |||
3 | Copyright (c) 2005 Michael D. Leonhard | ||
4 | |||
5 | http://tamale.net/ | ||
6 | |||
7 | This file is licensed under the terms described in the | ||
8 | accompanying LICENSE file. | ||
9 | */ | ||
10 | |||
11 | #ifndef SHA1_H | ||
12 | #define SHA1_H | ||
13 | |||
14 | #include <stdint.h> | ||
15 | |||
16 | /** | ||
17 | * Calculates SHA-1 sums. This is based strongly on code from Michael D. | ||
18 | * Leonhard who released his code under the terms of the MIT license, thank you! | ||
19 | */ | ||
20 | class Sha1 | ||
21 | { | ||
22 | public: | ||
23 | Sha1(); | ||
24 | ~Sha1(); | ||
25 | |||
26 | void update( const char* data, int num ); | ||
27 | unsigned char* getDigest(); | ||
28 | |||
29 | // utility methods | ||
30 | static uint32_t lrot( uint32_t x, int bits ); | ||
31 | static void toBigEndian( uint32_t in, unsigned char* out ); | ||
32 | |||
33 | private: | ||
34 | // fields | ||
35 | uint32_t H0, H1, H2, H3, H4; | ||
36 | unsigned char bytes[64]; | ||
37 | int unprocessedBytes; | ||
38 | uint32_t size; | ||
39 | void process(); | ||
40 | }; | ||
41 | |||
42 | #endif | ||
diff --git a/src/old/singleton.h b/src/old/singleton.h new file mode 100644 index 0000000..47adbd5 --- /dev/null +++ b/src/old/singleton.h | |||
@@ -0,0 +1,59 @@ | |||
1 | #ifndef SINGLETON_H | ||
2 | #define SINGLETON_H | ||
3 | |||
4 | #include <stdio.h> | ||
5 | |||
6 | /** | ||
7 | * Provides singleton functionality in a modular sort of way. Make this the | ||
8 | * base class of any other class and you immediately gain singleton | ||
9 | * functionality. Be sure to make your constructor and various functions use | ||
10 | * intellegent scoping. Cleanup and instantiation are performed automatically | ||
11 | * for you at first use and program exit. There are two things that you must | ||
12 | * do when using this template, first is to inherit from it with the name of | ||
13 | * your class filling in for T and then make this class a friend of your class. | ||
14 | *@code | ||
15 | * // Making the Single Singleton: | ||
16 | * class Single : public Singleton<Single> | ||
17 | * { | ||
18 | * friend class Singleton<Single>; | ||
19 | * protected: | ||
20 | * Single(); | ||
21 | * ... | ||
22 | * }; | ||
23 | @endcode | ||
24 | * You can still add public functions and variables to your new Singleton child | ||
25 | * class, but your constructor should be protected (hence the need for the | ||
26 | * friend decleration). | ||
27 | *@author Mike Buland | ||
28 | */ | ||
29 | template <class T> | ||
30 | class Singleton | ||
31 | { | ||
32 | protected: | ||
33 | /** | ||
34 | * Private constructor. This constructor is empty but has a body so that | ||
35 | * you can make your own override of it. Be sure that you're override is | ||
36 | * also protected. | ||
37 | */ | ||
38 | Singleton() {}; | ||
39 | |||
40 | private: | ||
41 | /** | ||
42 | * Copy constructor, defined so that you could write your own as well. | ||
43 | */ | ||
44 | Singleton( const Singleton& ); | ||
45 | |||
46 | public: | ||
47 | /** | ||
48 | * Get a handle to the contained instance of the contained class. It is | ||
49 | * a reference. | ||
50 | *@returns A reference to the contained object. | ||
51 | */ | ||
52 | static T &getInstance() | ||
53 | { | ||
54 | static T i; | ||
55 | return i; | ||
56 | } | ||
57 | }; | ||
58 | |||
59 | #endif | ||
diff --git a/src/old/sptr.cpp b/src/old/sptr.cpp new file mode 100644 index 0000000..7f5e894 --- /dev/null +++ b/src/old/sptr.cpp | |||
@@ -0,0 +1 @@ | |||
#include "sptr.h" | |||
diff --git a/src/old/sptr.h b/src/old/sptr.h new file mode 100644 index 0000000..deae94d --- /dev/null +++ b/src/old/sptr.h | |||
@@ -0,0 +1,99 @@ | |||
1 | #ifndef SPTR_H | ||
2 | #define SPTR_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | #include <stdio.h> | ||
6 | |||
7 | template<typename T> | ||
8 | class SPtr | ||
9 | { | ||
10 | public: | ||
11 | SPtr() : | ||
12 | pRefCnt( NULL ), | ||
13 | pData( NULL ) | ||
14 | { | ||
15 | } | ||
16 | |||
17 | ~SPtr() | ||
18 | { | ||
19 | decCount(); | ||
20 | } | ||
21 | |||
22 | SPtr( const SPtr<T> &src ) : | ||
23 | pRefCnt( src.pRefCnt ), | ||
24 | pData( src.pData ) | ||
25 | { | ||
26 | if( pRefCnt ) | ||
27 | (*pRefCnt) += 1; | ||
28 | } | ||
29 | |||
30 | SPtr( T *pSrc ) : | ||
31 | pRefCnt( NULL ), | ||
32 | pData( pSrc ) | ||
33 | { | ||
34 | pRefCnt = new int32_t; | ||
35 | (*pRefCnt) = 1; | ||
36 | } | ||
37 | |||
38 | int32_t count() | ||
39 | { | ||
40 | return *pRefCnt; | ||
41 | } | ||
42 | |||
43 | T *operator->() const | ||
44 | { | ||
45 | return pData; | ||
46 | } | ||
47 | |||
48 | T *operator*() const | ||
49 | { | ||
50 | return pData; | ||
51 | } | ||
52 | |||
53 | SPtr<T> operator=( const SPtr<T> &src ) | ||
54 | { | ||
55 | decCount(); | ||
56 | pRefCnt = src.pRefCnt; | ||
57 | pData = src.pData; | ||
58 | (*pRefCnt) += 1; | ||
59 | |||
60 | return *this; | ||
61 | } | ||
62 | |||
63 | bool operator==( const SPtr<T> &src ) | ||
64 | { | ||
65 | return pData == src.pData; | ||
66 | } | ||
67 | |||
68 | operator bool() | ||
69 | { | ||
70 | return pRefCnt != NULL; | ||
71 | } | ||
72 | |||
73 | bool isSet() | ||
74 | { | ||
75 | return pRefCnt != NULL; | ||
76 | } | ||
77 | |||
78 | private: | ||
79 | void decCount() | ||
80 | { | ||
81 | if( pRefCnt ) | ||
82 | { | ||
83 | (*pRefCnt) -= 1; | ||
84 | //printf("Decrementing ref-count to %d\n", *pRefCnt ); | ||
85 | if( (*pRefCnt) == 0 ) | ||
86 | { | ||
87 | delete pRefCnt; | ||
88 | delete pData; | ||
89 | pRefCnt = NULL; | ||
90 | pData = NULL; | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | int32_t *pRefCnt; | ||
96 | T *pData; | ||
97 | }; | ||
98 | |||
99 | #endif | ||
diff --git a/src/old/stack.cpp b/src/old/stack.cpp new file mode 100644 index 0000000..8d9565c --- /dev/null +++ b/src/old/stack.cpp | |||
@@ -0,0 +1,33 @@ | |||
1 | #include "stack.h" | ||
2 | |||
3 | void Stack::push( void *data ) | ||
4 | { | ||
5 | lStackData.append( data ); | ||
6 | } | ||
7 | |||
8 | void *Stack::top() | ||
9 | { | ||
10 | return lStackData.getAt( lStackData.getSize()-1 ); | ||
11 | } | ||
12 | |||
13 | void Stack::pop() | ||
14 | { | ||
15 | lStackData.deleteAt( lStackData.getSize()-1 ); | ||
16 | } | ||
17 | |||
18 | void *Stack::poptop() | ||
19 | { | ||
20 | void *dat = top(); | ||
21 | pop(); | ||
22 | return dat; | ||
23 | } | ||
24 | |||
25 | bool Stack::isEmpty() | ||
26 | { | ||
27 | return lStackData.isEmpty(); | ||
28 | } | ||
29 | |||
30 | void Stack::empty() | ||
31 | { | ||
32 | lStackData.empty(); | ||
33 | } | ||
diff --git a/src/old/stack.h b/src/old/stack.h new file mode 100644 index 0000000..30e2a19 --- /dev/null +++ b/src/old/stack.h | |||
@@ -0,0 +1,50 @@ | |||
1 | #ifndef STACK_H | ||
2 | #define STACK_H | ||
3 | #include "linkedlist.h" | ||
4 | |||
5 | /** An ultra-simple stack implementation that just uses a linked list. | ||
6 | *@author Mike Buland | ||
7 | */ | ||
8 | class Stack | ||
9 | { | ||
10 | public: | ||
11 | /** Pushes a new value onto the top of the stack. | ||
12 | *@param data A new value for the stack. | ||
13 | *@author Mike Buland | ||
14 | */ | ||
15 | void push( void *data ); | ||
16 | |||
17 | /** Returns the top value off of the stack, but doesn't remove it from the | ||
18 | * stack. | ||
19 | *@returns The value at the top of the stack. | ||
20 | *@author Mike Buland | ||
21 | */ | ||
22 | void *top(); | ||
23 | |||
24 | /** Pops the top item off of the stack. | ||
25 | *@author Mike Buland | ||
26 | */ | ||
27 | void pop(); | ||
28 | |||
29 | /** Gets the top item off of the stack, pops it off the stack, and returns | ||
30 | * it. | ||
31 | *@returns The value at the top of the stack. | ||
32 | *@author Mike Buland | ||
33 | */ | ||
34 | void *poptop(); | ||
35 | |||
36 | /** Checks if the stack is empty. | ||
37 | *@returns True if the stack is empty, and false if it has things in it. | ||
38 | *@author Mike Buland | ||
39 | */ | ||
40 | bool isEmpty(); | ||
41 | |||
42 | /** Empty the stack. | ||
43 | *@author Mike Buland | ||
44 | */ | ||
45 | void empty(); | ||
46 | |||
47 | private: | ||
48 | LinkedList lStackData; /**< The actual stack data. */ | ||
49 | }; | ||
50 | #endif | ||
diff --git a/src/old/staticstring.cpp b/src/old/staticstring.cpp new file mode 100644 index 0000000..60f130f --- /dev/null +++ b/src/old/staticstring.cpp | |||
@@ -0,0 +1,282 @@ | |||
1 | #include "staticstring.h" | ||
2 | #include "serializer.h" | ||
3 | |||
4 | #include <stdlib.h> | ||
5 | #include <stdio.h> | ||
6 | #include <string.h> | ||
7 | |||
8 | StaticString::StaticString() | ||
9 | { | ||
10 | lpStr = NULL; | ||
11 | nLen = 0; | ||
12 | } | ||
13 | |||
14 | StaticString::StaticString( int nLength ) | ||
15 | { | ||
16 | lpStr = new char[nLength+1]; | ||
17 | nLen = nLength; | ||
18 | memset( lpStr, 0, nLength+1 ); | ||
19 | } | ||
20 | |||
21 | StaticString::StaticString( const char *lpNewStr, int nNewLen ) | ||
22 | { | ||
23 | lpStr = NULL; | ||
24 | nLen = 0; | ||
25 | setString( lpNewStr, nNewLen ); | ||
26 | } | ||
27 | |||
28 | StaticString::StaticString( const char *lpNewStr ) | ||
29 | { | ||
30 | lpStr = NULL; | ||
31 | nLen = 0; | ||
32 | setString( lpNewStr, -1 ); | ||
33 | } | ||
34 | |||
35 | StaticString::StaticString( StaticString &xSrcStr, int nNewLen ) | ||
36 | { | ||
37 | lpStr = NULL; | ||
38 | nLen = 0; | ||
39 | setString( xSrcStr, nNewLen ); | ||
40 | } | ||
41 | |||
42 | StaticString::StaticString( StaticString &xSrcStr ) | ||
43 | { | ||
44 | lpStr = NULL; | ||
45 | nLen = 0; | ||
46 | setString( xSrcStr, -1 ); | ||
47 | } | ||
48 | |||
49 | StaticString::StaticString( const StaticString &xSrcStr ) | ||
50 | { | ||
51 | nLen = xSrcStr.getLength(); | ||
52 | lpStr = new char[nLen]; | ||
53 | memcpy( lpStr, xSrcStr.getString(), nLen ); | ||
54 | } | ||
55 | |||
56 | StaticString::~StaticString() | ||
57 | { | ||
58 | if( lpStr != NULL ) delete[] lpStr; | ||
59 | } | ||
60 | |||
61 | char *StaticString::getString() | ||
62 | { | ||
63 | return lpStr; | ||
64 | } | ||
65 | |||
66 | const char *StaticString::getString() const | ||
67 | { | ||
68 | return lpStr; | ||
69 | } | ||
70 | |||
71 | int StaticString::getLength() const | ||
72 | { | ||
73 | return nLen; | ||
74 | } | ||
75 | |||
76 | void StaticString::setLength( int nNewLength ) | ||
77 | { | ||
78 | char *lpNewStr = new char[nNewLength+1]; | ||
79 | if( lpStr != NULL ) | ||
80 | { | ||
81 | strncpy( lpNewStr, lpStr, nNewLength ); | ||
82 | } | ||
83 | lpNewStr[nNewLength] = '\0'; | ||
84 | if( lpStr ) | ||
85 | { | ||
86 | delete[] lpStr; | ||
87 | } | ||
88 | lpStr = lpNewStr; | ||
89 | nLen = nNewLength; | ||
90 | } | ||
91 | |||
92 | void StaticString::setString( const char *lpNewStr, int nNewLen ) | ||
93 | { | ||
94 | if( lpStr ) | ||
95 | { | ||
96 | delete[] lpStr; | ||
97 | lpStr = NULL; | ||
98 | nLen = 0; | ||
99 | } | ||
100 | if( nNewLen < 0 ) | ||
101 | { | ||
102 | if( lpNewStr == NULL ) return; | ||
103 | nLen = strlen( lpNewStr ); | ||
104 | lpStr = new char[nLen+1]; | ||
105 | strcpy( lpStr, lpNewStr ); | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | nLen = nNewLen; | ||
110 | lpStr = new char[nLen+1]; | ||
111 | memset( lpStr, 0, nLen+1 ); | ||
112 | if( lpNewStr ) | ||
113 | strncpy( lpStr, lpNewStr, nNewLen ); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | void StaticString::setString( StaticString &sNewStr, int nNewLen ) | ||
118 | { | ||
119 | if( lpStr ) | ||
120 | { | ||
121 | delete[] lpStr; | ||
122 | lpStr = NULL; | ||
123 | nLen = 0; | ||
124 | } | ||
125 | if( nNewLen < 0 ) | ||
126 | { | ||
127 | if( sNewStr.lpStr == NULL ) return; | ||
128 | nLen = sNewStr.nLen; | ||
129 | lpStr = new char[nLen+1]; | ||
130 | strcpy( lpStr, sNewStr.lpStr ); | ||
131 | } | ||
132 | else | ||
133 | { | ||
134 | nLen = nNewLen; | ||
135 | lpStr = new char[nLen+1]; | ||
136 | memset( lpStr, 0, nLen+1 ); | ||
137 | if( sNewStr.lpStr ) | ||
138 | strncpy( lpStr, sNewStr.lpStr, nNewLen ); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | StaticString &StaticString::operator=( StaticString &lpOtherStr ) | ||
143 | { | ||
144 | setString( lpOtherStr ); | ||
145 | |||
146 | return *this; | ||
147 | } | ||
148 | |||
149 | StaticString &StaticString::operator=( std::string &lpOtherStr ) | ||
150 | { | ||
151 | setString( lpOtherStr.c_str() ); | ||
152 | |||
153 | return *this; | ||
154 | } | ||
155 | |||
156 | StaticString &StaticString::operator=( const char *lpNewStr ) | ||
157 | { | ||
158 | setString( lpNewStr ); | ||
159 | |||
160 | return *this; | ||
161 | } | ||
162 | |||
163 | StaticString::operator const char *() | ||
164 | { | ||
165 | return lpStr; | ||
166 | } | ||
167 | |||
168 | char StaticString::getAt( unsigned int nIndex ) | ||
169 | { | ||
170 | if( nIndex < 0 || nIndex >= nLen ) | ||
171 | return '\0'; | ||
172 | |||
173 | return lpStr[nIndex]; | ||
174 | } | ||
175 | |||
176 | void StaticString::setAt( unsigned int nIndex, char cVal ) | ||
177 | { | ||
178 | if( nIndex < 0 || nIndex >= nLen ) | ||
179 | return; | ||
180 | |||
181 | lpStr[nIndex] = cVal; | ||
182 | } | ||
183 | |||
184 | char &StaticString::operator[]( unsigned int nIndex ) | ||
185 | { | ||
186 | if( nIndex < 0 || nIndex >= nLen ) | ||
187 | return lpStr[0]; | ||
188 | |||
189 | return lpStr[nIndex]; | ||
190 | } | ||
191 | |||
192 | StaticString::operator int() | ||
193 | { | ||
194 | return nLen; | ||
195 | } | ||
196 | |||
197 | char *StaticString::operator+( int nAmnt ) | ||
198 | { | ||
199 | return lpStr + nAmnt; | ||
200 | } | ||
201 | |||
202 | char *StaticString::operator-( int nAmnt ) | ||
203 | { | ||
204 | return lpStr - nAmnt; | ||
205 | } | ||
206 | |||
207 | void StaticString::clear() | ||
208 | { | ||
209 | memset( lpStr, 0, nLen+1 ); | ||
210 | } | ||
211 | |||
212 | void StaticString::serialize( Serializer &ar ) | ||
213 | { | ||
214 | if( ar.isLoading() ) | ||
215 | { | ||
216 | ar >> nLen; | ||
217 | setLength( nLen ); | ||
218 | ar.read( lpStr, nLen ); | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | ar << nLen; | ||
223 | ar.write( lpStr, nLen ); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | bool StaticString::operator==( const char *str ) | ||
228 | { | ||
229 | const char *a = str, *b = lpStr; | ||
230 | for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return true; | ||
231 | return false; | ||
232 | } | ||
233 | |||
234 | bool StaticString::operator==( StaticString &str ) | ||
235 | { | ||
236 | const char *a = str.lpStr, *b = lpStr; | ||
237 | for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return true; | ||
238 | return false; | ||
239 | } | ||
240 | |||
241 | bool StaticString::operator!=( const char *str ) | ||
242 | { | ||
243 | const char *a = str, *b = lpStr; | ||
244 | for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return false; | ||
245 | return true; | ||
246 | } | ||
247 | |||
248 | bool StaticString::operator!=( StaticString &str ) | ||
249 | { | ||
250 | const char *a = str.lpStr, *b = lpStr; | ||
251 | for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return false; | ||
252 | return true; | ||
253 | } | ||
254 | /* | ||
255 | unsigned long int StaticString::getHashCode() | ||
256 | { | ||
257 | unsigned long int nPos = nLen; | ||
258 | unsigned long int j = 0; | ||
259 | for( const char *s = (const char *)lpStr; j< nLen; s++, j++ ) | ||
260 | { | ||
261 | nPos = *s + (nPos << 6) + (nPos << 16) - nPos; | ||
262 | } | ||
263 | return nPos; | ||
264 | } | ||
265 | |||
266 | bool StaticString::compareForHash( Hashable &other ) | ||
267 | { | ||
268 | if( ((StaticString &)other).nLen != nLen ) | ||
269 | return false; | ||
270 | |||
271 | const char *a = ((StaticString &)other).lpStr; | ||
272 | const char *b = lpStr; | ||
273 | if( a == b ) | ||
274 | return true; | ||
275 | |||
276 | for( unsigned long j = 0; j < nLen; j++, a++, b++ ) | ||
277 | if( *a != *b ) | ||
278 | return false; | ||
279 | |||
280 | return true; | ||
281 | } | ||
282 | */ | ||
diff --git a/src/old/staticstring.h b/src/old/staticstring.h new file mode 100644 index 0000000..4c3f7b8 --- /dev/null +++ b/src/old/staticstring.h | |||
@@ -0,0 +1,63 @@ | |||
1 | #ifndef STATIC_STRING_H | ||
2 | #define STATIC_STRING_H | ||
3 | |||
4 | #include <string> | ||
5 | #include "serializable.h" | ||
6 | //#include "hashable.h" | ||
7 | |||
8 | /** | ||
9 | * Simple string managing class. Allows for dynamically allocated string data | ||
10 | * along with some minor caching to speed things up when accessing your | ||
11 | * string data. Really designed for making copies of strings easy and safe, | ||
12 | * and making accessing meta-info like length fast and reliable as well. | ||
13 | *@author Mike Buland | ||
14 | */ | ||
15 | class StaticString : public Serializable/*, public Hashable*/ | ||
16 | { | ||
17 | public: | ||
18 | StaticString(); | ||
19 | StaticString( const char *lpNewStr, int nNewLen ); | ||
20 | StaticString( const char *lpNewStr ); | ||
21 | StaticString( StaticString &xSrcStr, int nNewLen ); | ||
22 | StaticString( StaticString &xSrcStr ); | ||
23 | StaticString( const StaticString &xSrcStr ); | ||
24 | StaticString( int nLength ); | ||
25 | virtual ~StaticString(); | ||
26 | |||
27 | char *getString(); | ||
28 | const char *getString() const; | ||
29 | int getLength() const; | ||
30 | void setLength( int nNewLength ); | ||
31 | |||
32 | void setString( const char *lpNewStr, int nNewLen=-1 ); | ||
33 | void setString( StaticString &sNewStr, int nNewLen=-1 ); | ||
34 | |||
35 | char getAt( unsigned int nIndex ); | ||
36 | void setAt( unsigned int nIndex, char cVal ); | ||
37 | |||
38 | class StaticString &operator=( class StaticString &lpOtherStr ); | ||
39 | class StaticString &operator=( std::string &lpOtherStr ); | ||
40 | class StaticString &operator=( const char *lpNewStr ); | ||
41 | operator const char *(); | ||
42 | char &operator[]( unsigned int nIndex ); | ||
43 | operator int(); | ||
44 | char *operator+( int nAmnt ); | ||
45 | char *operator-( int nAmnt ); | ||
46 | bool operator==( const char *str ); | ||
47 | bool operator==( StaticString &str ); | ||
48 | bool operator!=( const char *str ); | ||
49 | bool operator!=( StaticString &str ); | ||
50 | |||
51 | void clear(); | ||
52 | |||
53 | virtual void serialize( class Serializer &ar ); | ||
54 | |||
55 | //virtual unsigned long int getHashCode(); | ||
56 | //virtual bool compareForHash( Hashable &other ); | ||
57 | |||
58 | private: | ||
59 | char *lpStr; | ||
60 | uint32_t nLen; | ||
61 | }; | ||
62 | |||
63 | #endif | ||
diff --git a/src/old/stream.cpp b/src/old/stream.cpp new file mode 100644 index 0000000..856a58d --- /dev/null +++ b/src/old/stream.cpp | |||
@@ -0,0 +1,10 @@ | |||
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 new file mode 100644 index 0000000..e086e28 --- /dev/null +++ b/src/old/stream.h | |||
@@ -0,0 +1,27 @@ | |||
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/old/stringrep.cpp b/src/old/stringrep.cpp new file mode 100644 index 0000000..a505f8a --- /dev/null +++ b/src/old/stringrep.cpp | |||
@@ -0,0 +1,19 @@ | |||
1 | #include "stringrep.h" | ||
2 | |||
3 | int32_t stringlen( const char *s ) | ||
4 | { | ||
5 | for( int32_t i = 0;; i++ ) | ||
6 | if( !s[i] ) | ||
7 | return i; | ||
8 | } | ||
9 | |||
10 | char *stringdup( const char *s ) | ||
11 | { | ||
12 | int len = stringlen( s ); | ||
13 | char *r = new char[len+1]; | ||
14 | for( int j = 0; j <= len; j++ ) | ||
15 | r[j] = s[j]; | ||
16 | |||
17 | return r; | ||
18 | } | ||
19 | |||
diff --git a/src/old/stringrep.h b/src/old/stringrep.h new file mode 100644 index 0000000..eaa4a12 --- /dev/null +++ b/src/old/stringrep.h | |||
@@ -0,0 +1,17 @@ | |||
1 | #ifndef STRING_REP_H | ||
2 | #define STRING_REP_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | |||
6 | /** | ||
7 | * Calculates the length of a string. | ||
8 | */ | ||
9 | int32_t stringlen( const char *s ); | ||
10 | |||
11 | /** | ||
12 | * Identicle to strdup, which isn't available everywhere, but uses c++ memory | ||
13 | * facilities. Remember to use delete[] when freeing the returned string. | ||
14 | */ | ||
15 | char *stringdup( const char *s ); | ||
16 | |||
17 | #endif | ||
diff --git a/src/old/tests/clistress.cpp b/src/old/tests/clistress.cpp new file mode 100644 index 0000000..6b0ac66 --- /dev/null +++ b/src/old/tests/clistress.cpp | |||
@@ -0,0 +1,20 @@ | |||
1 | #include "connection.h" | ||
2 | |||
3 | int main() | ||
4 | { | ||
5 | Connection c; | ||
6 | |||
7 | c.open("localhost", 4001 ); | ||
8 | |||
9 | c.appendOutput("w"); | ||
10 | c.writeOutput(); | ||
11 | |||
12 | c.waitForInput( 6, 5, 0 ); | ||
13 | |||
14 | printf("read: %s\n", c.getInput() ); | ||
15 | |||
16 | c.close(); | ||
17 | |||
18 | return 0; | ||
19 | } | ||
20 | |||
diff --git a/src/old/tests/confpair.cpp b/src/old/tests/confpair.cpp new file mode 100644 index 0000000..fb1b0d3 --- /dev/null +++ b/src/old/tests/confpair.cpp | |||
@@ -0,0 +1,19 @@ | |||
1 | #include "confpair.h" | ||
2 | #include <iostream> | ||
3 | |||
4 | using namespace std; | ||
5 | |||
6 | int main() | ||
7 | { | ||
8 | ConfPair<float> p1("DebugMode"); | ||
9 | p1.value() = 12; | ||
10 | cout << p1.value() << "\n"; | ||
11 | p1.value() = 55; | ||
12 | cout << p1.value() << "\n"; | ||
13 | |||
14 | ConfPairBase &p = p1; | ||
15 | |||
16 | p = "33.12"; | ||
17 | cout << p.getAsString(); | ||
18 | } | ||
19 | |||
diff --git a/src/old/tests/connect.cpp b/src/old/tests/connect.cpp new file mode 100644 index 0000000..a9fca64 --- /dev/null +++ b/src/old/tests/connect.cpp | |||
@@ -0,0 +1,38 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <unistd.h> | ||
4 | #include <fcntl.h> | ||
5 | #include "connection.h" | ||
6 | |||
7 | int main() | ||
8 | { | ||
9 | Connection c; | ||
10 | c.open("127.0.0.1", 12457 ); | ||
11 | |||
12 | { | ||
13 | int newSocket = c.getSocket(); | ||
14 | int flags; | ||
15 | |||
16 | flags = fcntl(newSocket, F_GETFL, 0); | ||
17 | flags |= O_NONBLOCK; | ||
18 | if (fcntl(newSocket, F_SETFL, flags) < 0) | ||
19 | { | ||
20 | return false; | ||
21 | } | ||
22 | } | ||
23 | |||
24 | for( int i = 0; i < 50; i++ ) | ||
25 | { | ||
26 | usleep( 100000 ); | ||
27 | int nbytes = c.readInput(); | ||
28 | if( nbytes == 0 ) | ||
29 | printf("0 bytes, EOF?\n"); | ||
30 | else | ||
31 | printf("Got %d bytes, whacky...\n", nbytes ); | ||
32 | } | ||
33 | |||
34 | c.close(); | ||
35 | |||
36 | return 0; | ||
37 | } | ||
38 | |||
diff --git a/src/old/tests/exception.cpp b/src/old/tests/exception.cpp new file mode 100644 index 0000000..6417692 --- /dev/null +++ b/src/old/tests/exception.cpp | |||
@@ -0,0 +1,16 @@ | |||
1 | #include <iostream> | ||
2 | #include "exceptions.h" | ||
3 | |||
4 | int main() | ||
5 | { | ||
6 | try | ||
7 | { | ||
8 | throw ExceptionBase( 42, "There was an error on line: %d", __LINE__ ); | ||
9 | } | ||
10 | catch( ExceptionBase &e ) | ||
11 | { | ||
12 | std::cout << "Error "<< e.getErrorCode() << ": " << e.what() << "\n"; | ||
13 | } | ||
14 | |||
15 | throw ExceptionBase( 112, "This exception wasn't caught!"); | ||
16 | } | ||
diff --git a/src/old/tests/formula.cpp b/src/old/tests/formula.cpp new file mode 100644 index 0000000..976b039 --- /dev/null +++ b/src/old/tests/formula.cpp | |||
@@ -0,0 +1,13 @@ | |||
1 | #include "formula.h" | ||
2 | |||
3 | int main( int argc, char *argv[] ) | ||
4 | { | ||
5 | if( argc < 2 ) return 0; | ||
6 | |||
7 | Formula f; | ||
8 | double dOut = f.run( argv[1] ); | ||
9 | printf("%s = %f\n", argv[1], dOut ); | ||
10 | |||
11 | return 0; | ||
12 | } | ||
13 | |||
diff --git a/src/old/tests/fstring.cpp b/src/old/tests/fstring.cpp new file mode 100644 index 0000000..271738c --- /dev/null +++ b/src/old/tests/fstring.cpp | |||
@@ -0,0 +1,48 @@ | |||
1 | #include "hash.h" | ||
2 | #include "fstring.h" | ||
3 | |||
4 | FString genThing() | ||
5 | { | ||
6 | FString bob; | ||
7 | bob.append("ab "); | ||
8 | bob += "cd "; | ||
9 | bob += "efg"; | ||
10 | |||
11 | printf("---bob------\n%08X: %s\n", (unsigned int)bob.c_str(), bob.c_str() ); | ||
12 | return bob; | ||
13 | } | ||
14 | |||
15 | void thing( FString str ) | ||
16 | { | ||
17 | printf("Hey: %s\n", str.c_str() ); | ||
18 | } | ||
19 | |||
20 | #define pem printf("---------\n%08X: %s\n%08X: %s\n", (unsigned int)str.c_str(), str.c_str(), (unsigned int)str2.c_str(), str2.c_str() ); | ||
21 | int main( int argc, char *argv ) | ||
22 | { | ||
23 | FString str("th"); | ||
24 | |||
25 | str.prepend("Hello "); | ||
26 | str.append("ere."); | ||
27 | |||
28 | FString str2( str ); | ||
29 | pem; | ||
30 | str += " What's up?"; | ||
31 | pem; | ||
32 | str2 += " How are you?"; | ||
33 | pem; | ||
34 | str = str2; | ||
35 | pem; | ||
36 | |||
37 | str2 = genThing(); | ||
38 | pem; | ||
39 | |||
40 | str = str2; | ||
41 | pem; | ||
42 | |||
43 | thing( str2 ); | ||
44 | thing("test."); | ||
45 | |||
46 | printf("%d == %d\n", __calcHashCode( str ), __calcHashCode( str.c_str() ) ); | ||
47 | } | ||
48 | |||
diff --git a/src/old/tests/hash.cpp b/src/old/tests/hash.cpp new file mode 100644 index 0000000..2fc6968 --- /dev/null +++ b/src/old/tests/hash.cpp | |||
@@ -0,0 +1,116 @@ | |||
1 | #include "hash.h" | ||
2 | #include "staticstring.h" | ||
3 | |||
4 | int main() | ||
5 | { | ||
6 | const char *names[]={ | ||
7 | "Homer the Great", | ||
8 | "And Maggie Makes Three", | ||
9 | "Bart's Comet", | ||
10 | "Homie The Clown", | ||
11 | "Bart Vs Australia", | ||
12 | "Homer vs Patty and Selma", | ||
13 | "A star is burns", | ||
14 | "Lisa's Wedding", | ||
15 | "Two Dozen and One Greyhounds", | ||
16 | "The PTA Disbands", | ||
17 | "Round Springfield", | ||
18 | "The Springfield connection", | ||
19 | "Lemon of Troy", | ||
20 | "Who Shot Mr. Burns (Pt. 1)", | ||
21 | "Who Shot Mr. Burns (pt. 2)", | ||
22 | "Radioactive Man", | ||
23 | "Home Sweet Homediddly-dum-doodly", | ||
24 | "Bart Sells His Soul", | ||
25 | "Lisa the Vegetarian", | ||
26 | "Treehouse of horror VI", | ||
27 | "King Size Homer", | ||
28 | "Mother Simpson", | ||
29 | "Sideshow Bob's Last Gleaming", | ||
30 | "The Simpson's 138th Show Spectacular", | ||
31 | "Marge Be Not Proud", | ||
32 | "Team Homer", | ||
33 | "Two Bad Neighbors", | ||
34 | "Scenes From the Class Struggle in Springfield", | ||
35 | "Bart the Fink", | ||
36 | "Lisa the Iconoclast", | ||
37 | "Homer the Smithers", | ||
38 | "The Day the Violence Died", | ||
39 | "A Fish Called Selma", | ||
40 | "Bart on the road", | ||
41 | "22 Short Films about Springfield", | ||
42 | "The Curse of the Flying Hellfish", | ||
43 | "Much Apu about Nothing", | ||
44 | "Homerpalooza", | ||
45 | "The Summer of 4 Ft 2", | ||
46 | "Treehouse of Horror VII", | ||
47 | "You Only Move Twice", | ||
48 | "The Homer They Fall", | ||
49 | "Burns Baby Burns", | ||
50 | "Bart After Dark", | ||
51 | "A Millhouse Divided", | ||
52 | "Lisas Date With Destiny", | ||
53 | "Hurricane Neddy", | ||
54 | "The Mysterious Voyage of Our Homer", | ||
55 | "The Springfield Files", | ||
56 | "The Twisted World of Marge Simpson", | ||
57 | "Mountain of Madness", | ||
58 | NULL | ||
59 | }; | ||
60 | |||
61 | Hash<const char *, int> sTest; | ||
62 | |||
63 | printf("Inserting\n-------------------\n\n"); | ||
64 | for( int j = 0; j < 33; j++ ) | ||
65 | { | ||
66 | sTest[names[j]] = j; | ||
67 | } | ||
68 | |||
69 | printf("Test1: %d, Test2: %d\n", sTest.has("Lemon of Troy"), sTest.has(std::string("Lemon of Troy").c_str() ) ); | ||
70 | |||
71 | sTest.has(std::string("Lemon of Troy").c_str() ); | ||
72 | |||
73 | printf("Getting\n-------------------\n\n"); | ||
74 | |||
75 | sTest.erase("Homer the Great"); | ||
76 | sTest["Bart's Comet"].erase(); | ||
77 | |||
78 | for( Hash<const char *, int>::iterator i = sTest.begin(); | ||
79 | i != sTest.end(); i++ ) | ||
80 | { | ||
81 | Hash<const char *, int>::iterator j = i; | ||
82 | printf("%d: %s\n", (*j).second, (*j).first ); | ||
83 | } | ||
84 | |||
85 | printf("Testing\n-------------------\n\n"); | ||
86 | for( int j = 0; j < 33; j++ ) | ||
87 | { | ||
88 | if( sTest.has(names[j]) ) | ||
89 | { | ||
90 | if( sTest[names[j]] != j ) | ||
91 | { | ||
92 | printf("'%s' should be %d, is %d\n", | ||
93 | names[j], j, | ||
94 | sTest[names[j]].value() | ||
95 | ); | ||
96 | } | ||
97 | } | ||
98 | else | ||
99 | { | ||
100 | printf("Missing element %d, '%s'\n", j, names[j] ); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | printf("Clearing\n-------------------\n\n"); | ||
105 | |||
106 | sTest.clear(); | ||
107 | |||
108 | for( Hash<const char *, int>::iterator i = sTest.begin(); | ||
109 | i != sTest.end(); i++ ) | ||
110 | { | ||
111 | Hash<const char *, int>::iterator j = i; | ||
112 | printf("%d: %s\n", (*j).second, (*j).first ); | ||
113 | } | ||
114 | |||
115 | } | ||
116 | |||
diff --git a/src/old/tests/hashtest.cpp b/src/old/tests/hashtest.cpp new file mode 100644 index 0000000..eaa84a0 --- /dev/null +++ b/src/old/tests/hashtest.cpp | |||
@@ -0,0 +1,107 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <iostream> | ||
3 | #include "hashtable.h" | ||
4 | #include "hashfunctioncasestring.h" | ||
5 | |||
6 | int main() | ||
7 | { | ||
8 | const char *names[]={ | ||
9 | "Homer the Great", | ||
10 | "And Maggie Makes Three", | ||
11 | "Bart's Comet", | ||
12 | "Homie The Clown", | ||
13 | "Bart Vs Australia", | ||
14 | "Homer vs Patty and Selma", | ||
15 | "A star is burns", | ||
16 | "Lisa's Wedding", | ||
17 | "Two Dozen and One Greyhounds", | ||
18 | "The PTA Disbands", | ||
19 | "Round Springfield", | ||
20 | "The Springfield connection", | ||
21 | "Lemon of Troy", | ||
22 | "Who Shot Mr. Burns (Pt. 1)", | ||
23 | "Who Shot Mr. Burns (pt. 2)", | ||
24 | "Radioactive Man", | ||
25 | "Home Sweet Homediddly-dum-doodly", | ||
26 | "Bart Sells His Soul", | ||
27 | "Lisa the Vegetarian", | ||
28 | "Treehouse of horror VI", | ||
29 | "King Size Homer", | ||
30 | "Mother Simpson", | ||
31 | "Sideshow Bob's Last Gleaming", | ||
32 | "The Simpson's 138th Show Spectacular", | ||
33 | "Marge Be Not Proud", | ||
34 | "Team Homer", | ||
35 | "Two Bad Neighbors", | ||
36 | "Scenes From the Class Struggle in Springfield", | ||
37 | "Bart the Fink", | ||
38 | "Lisa the Iconoclast", | ||
39 | "Homer the Smithers", | ||
40 | "The Day the Violence Died", | ||
41 | "A Fish Called Selma", | ||
42 | "Bart on the road", | ||
43 | "22 Short Films about Springfield", | ||
44 | "The Curse of the Flying Hellfish", | ||
45 | "Much Apu about Nothing", | ||
46 | "Homerpalooza", | ||
47 | "The Summer of 4 Ft 2", | ||
48 | "Treehouse of Horror VII", | ||
49 | "You Only Move Twice", | ||
50 | "The Homer They Fall", | ||
51 | "Burns Baby Burns", | ||
52 | "Bart After Dark", | ||
53 | "A Millhouse Divided", | ||
54 | "Lisas Date With Destiny", | ||
55 | "Hurricane Neddy", | ||
56 | "The Mysterious Voyage of Our Homer", | ||
57 | "The Springfield Files", | ||
58 | "The Twisted World of Marge Simpson", | ||
59 | "Mountain of Madness", | ||
60 | NULL | ||
61 | }; | ||
62 | |||
63 | HashTable h( new HashFunctionCaseString(), 5, false ); | ||
64 | |||
65 | int j; | ||
66 | printf("Inserting...\n"); | ||
67 | for( j = 0; j < 10; j++ ) | ||
68 | { | ||
69 | h.insert( names[j], (void *)(j+1) ); | ||
70 | h.insert( names[j], (void *)(j+1) ); | ||
71 | printf("Capacity: %lu, Size: %lu, Load: %f\n", | ||
72 | h.getCapacity(), | ||
73 | h.getSize(), | ||
74 | h.getLoad() | ||
75 | ); | ||
76 | } | ||
77 | |||
78 | for( j = 0; j < 10; j++ ) | ||
79 | { | ||
80 | printf("\"%s\" = %d\n", names[j], (int)h[names[j]] ); | ||
81 | } | ||
82 | |||
83 | printf("\nDeleting some...\n"); | ||
84 | |||
85 | for( int k = 0; k < 7; k++ ) | ||
86 | { | ||
87 | h.del( names[k] ); | ||
88 | //h.insert( names[j], (void *)(j+1) ); | ||
89 | printf("Capacity: %lu, Size: %lu, Load: %f\n", | ||
90 | h.getCapacity(), | ||
91 | h.getSize(), | ||
92 | h.getLoad() | ||
93 | ); | ||
94 | } | ||
95 | |||
96 | printf("\nInserting more...\n"); | ||
97 | |||
98 | for( ; names[j] != NULL; j++ ) | ||
99 | { | ||
100 | h.insert( names[j], (void *)(j+1) ); | ||
101 | printf("Capacity: %lu, Size: %lu, Load: %f\n", | ||
102 | h.getCapacity(), | ||
103 | h.getSize(), | ||
104 | h.getLoad() | ||
105 | ); | ||
106 | } | ||
107 | } | ||
diff --git a/src/old/tests/hashtest2.cpp b/src/old/tests/hashtest2.cpp new file mode 100644 index 0000000..74700fd --- /dev/null +++ b/src/old/tests/hashtest2.cpp | |||
@@ -0,0 +1,15 @@ | |||
1 | #include "hash.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | int main() | ||
5 | { | ||
6 | char *a, *b; | ||
7 | a = new char[10]; | ||
8 | b = new char[10]; | ||
9 | strcpy( a, "Hey there"); | ||
10 | strcpy( b, "Hey there"); | ||
11 | printf("Same: %s\n", __cmpHashKeys( a, b )?"yes":"no"); | ||
12 | |||
13 | return 0; | ||
14 | } | ||
15 | |||
diff --git a/src/old/tests/httpsrv/httpconnectionmonitor.cpp b/src/old/tests/httpsrv/httpconnectionmonitor.cpp new file mode 100644 index 0000000..51d82f3 --- /dev/null +++ b/src/old/tests/httpsrv/httpconnectionmonitor.cpp | |||
@@ -0,0 +1,88 @@ | |||
1 | #include "httpconnectionmonitor.h" | ||
2 | #include "http.h" | ||
3 | #include "exceptions.h" | ||
4 | #include <sys/stat.h> | ||
5 | |||
6 | HttpConnectionMonitor::HttpConnectionMonitor() | ||
7 | { | ||
8 | } | ||
9 | |||
10 | HttpConnectionMonitor::~HttpConnectionMonitor() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | bool HttpConnectionMonitor::onNewConnection( Connection *pCon, int nPort ) | ||
15 | { | ||
16 | printf("Got connection on port %d\n", nPort ); | ||
17 | |||
18 | try | ||
19 | { | ||
20 | pCon->readInput( 60, 0 ); | ||
21 | printf("#######################\n%s\n#######################\n", pCon->getInput() ); | ||
22 | |||
23 | Http hp( pCon ); | ||
24 | while( hp.parseRequest() == false ); | ||
25 | printf("Done parsing.\n\n"); | ||
26 | |||
27 | if( hp.getRequestType() == Http::reqGet ) | ||
28 | { | ||
29 | printf("\"\"\"%s\"\"\"\n", hp.getRequestURI() ); | ||
30 | if( !strcmp( hp.getRequestURI(), "/" ) ) | ||
31 | { | ||
32 | std::string content("<html><head><title>Server Test</test></head><body>This is a test of a new system where all the pages will be more or less dynamic...<br>If you want to try to login, you can do that here:<br><form method=\"post\" action=\"showvars\" enctype=\"multipart/form-data\">Name: <input type=\"text\" name=\"name\"><br>Password: <input type=\"password\" name=\"pass\"><br><input type=\"submit\" name=\"action\" value=\"login\"></form></body></html>"); | ||
33 | hp.buildResponse(); | ||
34 | hp.setResponseContent( | ||
35 | "text/html", | ||
36 | content.c_str(), | ||
37 | content.size() | ||
38 | ); | ||
39 | hp.sendResponse(); | ||
40 | } | ||
41 | else | ||
42 | { | ||
43 | std::string content("<html><head><title>URL Not Found</test></head><body>There is no content mapped to the URL you requested. Please try another one.</body></html>"); | ||
44 | hp.buildResponse( 404, "File not found."); | ||
45 | hp.setResponseContent( | ||
46 | "text/html", | ||
47 | content.c_str(), | ||
48 | content.size() | ||
49 | ); | ||
50 | hp.sendResponse(); | ||
51 | } | ||
52 | } | ||
53 | else | ||
54 | { | ||
55 | printf("Non get: %s\n", hp.getRequestTypeStr() ); | ||
56 | pCon->appendOutput("HTTP/1.1 100 Continue\r\n\r\n"); | ||
57 | } | ||
58 | pCon->writeOutput(); | ||
59 | //for( int j = 0; j < 50; j++ ) | ||
60 | { | ||
61 | pCon->readInput( 1, 0 ); | ||
62 | //printf("Size so far: %d\n", pCon->getInputAmnt() ); | ||
63 | } | ||
64 | |||
65 | if( pCon->hasInput() ) | ||
66 | { | ||
67 | std::string s( pCon->getInput(), pCon->getInputAmnt() ); | ||
68 | |||
69 | pCon->printInputDebug(); | ||
70 | //printf("Reamining data\n==============\n%s\n==============\n", | ||
71 | // s.c_str() ); | ||
72 | } | ||
73 | |||
74 | pCon->disconnect(); | ||
75 | } | ||
76 | catch( ConnectionException &e ) | ||
77 | { | ||
78 | printf("Connection: %s\n", e.what() ); | ||
79 | } | ||
80 | |||
81 | return true; | ||
82 | } | ||
83 | |||
84 | bool HttpConnectionMonitor::onClosedConnection( Connection *pCon ) | ||
85 | { | ||
86 | return true; | ||
87 | } | ||
88 | |||
diff --git a/src/old/tests/httpsrv/httpconnectionmonitor.h b/src/old/tests/httpsrv/httpconnectionmonitor.h new file mode 100644 index 0000000..30c0afd --- /dev/null +++ b/src/old/tests/httpsrv/httpconnectionmonitor.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef HTTPCONNECTIONMONITOR_H | ||
2 | #define HTTPCONNECTIONMONITOR_H | ||
3 | |||
4 | #include "connectionmonitor.h" | ||
5 | |||
6 | class HttpConnectionMonitor : public ConnectionMonitor | ||
7 | { | ||
8 | public: | ||
9 | HttpConnectionMonitor(); | ||
10 | ~HttpConnectionMonitor(); | ||
11 | |||
12 | bool onNewConnection( Connection *pCon, int nPort ); | ||
13 | bool onClosedConnection( Connection *pCon ); | ||
14 | }; | ||
15 | |||
16 | #endif | ||
diff --git a/src/old/tests/httpsrv/main.cpp b/src/old/tests/httpsrv/main.cpp new file mode 100644 index 0000000..2f1563c --- /dev/null +++ b/src/old/tests/httpsrv/main.cpp | |||
@@ -0,0 +1,22 @@ | |||
1 | #include "connectionmanager.h" | ||
2 | #include "httpconnectionmonitor.h" | ||
3 | |||
4 | int main() | ||
5 | { | ||
6 | printf("Starting server...\n"); | ||
7 | |||
8 | ConnectionManager srv; | ||
9 | HttpConnectionMonitor http; | ||
10 | |||
11 | srv.setConnectionMonitor( &http ); | ||
12 | |||
13 | printf("Listening on port 7331\n"); | ||
14 | srv.startServer( 7331 ); | ||
15 | |||
16 | for(;;) | ||
17 | { | ||
18 | srv.scanConnections( 5000, false ); | ||
19 | } | ||
20 | |||
21 | return 0; | ||
22 | } | ||
diff --git a/src/old/tests/log.cpp b/src/old/tests/log.cpp new file mode 100644 index 0000000..d7cfa0b --- /dev/null +++ b/src/old/tests/log.cpp | |||
@@ -0,0 +1,29 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <iostream> | ||
4 | #include "multilog.h" | ||
5 | #include "multilogtext.h" | ||
6 | |||
7 | class Test | ||
8 | { | ||
9 | public: | ||
10 | Test() | ||
11 | { | ||
12 | MultiLineLog( 4, "Test init'd\n"); | ||
13 | } | ||
14 | }; | ||
15 | |||
16 | int main() | ||
17 | { | ||
18 | MultiLog &xLog = MultiLog::getInstance(); | ||
19 | |||
20 | xLog.LineLog( 2, "Hello again"); | ||
21 | |||
22 | MultiLog::getInstance().addChannel( | ||
23 | new MultiLogText( STDOUT_FILENO, "%02y-%02m-%02d %02h:%02M:%02s: %t" ) | ||
24 | ); | ||
25 | |||
26 | MultiLineLog( MultiLog::LError, "Hi there!"); | ||
27 | Test t; | ||
28 | } | ||
29 | |||
diff --git a/src/old/tests/md5test.cpp b/src/old/tests/md5test.cpp new file mode 100644 index 0000000..6f832df --- /dev/null +++ b/src/old/tests/md5test.cpp | |||
@@ -0,0 +1,19 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | #include "md5.h" | ||
4 | |||
5 | int main() | ||
6 | { | ||
7 | md5 mproc; | ||
8 | md5sum sum; | ||
9 | char hexstr[33]; | ||
10 | |||
11 | memset( hexstr, 0, 33 ); | ||
12 | |||
13 | mproc.sumString( &sum, "qwertyuiopasdfgh" ); | ||
14 | mproc.sumToHex( &sum, hexstr ); | ||
15 | printf("sum: %s\n", hexstr ); | ||
16 | printf("chk: 1ebfc043d8880b758b13ddc8aa1638ef\n"); | ||
17 | |||
18 | return 0; | ||
19 | } | ||
diff --git a/src/old/tests/ordhash.cpp b/src/old/tests/ordhash.cpp new file mode 100644 index 0000000..f1d96ec --- /dev/null +++ b/src/old/tests/ordhash.cpp | |||
@@ -0,0 +1,48 @@ | |||
1 | #include "ordhash.h" | ||
2 | #include <string> | ||
3 | |||
4 | typedef struct eldef | ||
5 | { | ||
6 | eldef( int a, int b, const std::string &c ) : | ||
7 | id( a ), nSequence( b ), sName( c ) {} | ||
8 | int id; | ||
9 | int nSequence; | ||
10 | std::string sName; | ||
11 | } eldef; | ||
12 | |||
13 | struct seqcmp | ||
14 | { | ||
15 | bool operator()( eldef **a, eldef **b ) | ||
16 | { | ||
17 | return (*a)->nSequence < (*b)->nSequence; | ||
18 | } | ||
19 | }; | ||
20 | |||
21 | struct namcmp | ||
22 | { | ||
23 | bool operator()( eldef **a, eldef **b ) | ||
24 | { | ||
25 | return (*a)->sName < (*b)->sName; | ||
26 | } | ||
27 | }; | ||
28 | |||
29 | typedef OrdHash<int, eldef, seqcmp> AHash; | ||
30 | //typedef OrdHash<int, eldef, namcmp> AHash; | ||
31 | |||
32 | int main() | ||
33 | { | ||
34 | AHash hsh; | ||
35 | hsh[1] = eldef( 0, 43, "Bob"); | ||
36 | hsh[4] = eldef( 1, 443, "Abby"); | ||
37 | hsh[2] = eldef( 2, 1, "Name"); | ||
38 | hsh[5] = eldef( 3, 0, "Catagory"); | ||
39 | hsh[32] = eldef( 4, 12, "Epilogue"); | ||
40 | |||
41 | for( AHash::iterator i = hsh.begin(); i != hsh.end(); i++ ) | ||
42 | { | ||
43 | eldef e = (*i).second; | ||
44 | printf("%d, %d, %s\n", e.id, e.nSequence, e.sName.c_str() ); | ||
45 | } | ||
46 | |||
47 | } | ||
48 | |||
diff --git a/src/old/tests/param.cpp b/src/old/tests/param.cpp new file mode 100644 index 0000000..a4d2824 --- /dev/null +++ b/src/old/tests/param.cpp | |||
@@ -0,0 +1,46 @@ | |||
1 | #include "param.h" | ||
2 | #include <stdio.h> | ||
3 | |||
4 | Param::Param() | ||
5 | { | ||
6 | addHelpBanner("param - A test of the libbu++ parameter systems\n" | ||
7 | "Enjoy with care and caution\n\nTest stuff:\n"); | ||
8 | addParam( "name", 's', mkproc( Param::printStuff ), &str, "Test a param param" ); | ||
9 | //addParam( "name", &str ); | ||
10 | addParam( "job", 'U', mkproc( Param::printStuff ), "Test a paramless param" ); | ||
11 | |||
12 | addHelpBanner("\nInformational:\n"); | ||
13 | addParam( "help", mkproc( ParamProc::help ), "Help!" ); | ||
14 | |||
15 | addHelpBanner("\nThanks for trying my test!\n\n"); | ||
16 | } | ||
17 | |||
18 | Param::~Param() | ||
19 | { | ||
20 | } | ||
21 | |||
22 | int Param::printStuff( int argc, char *argv[] ) | ||
23 | { | ||
24 | printf("------------%02d-------------\n", argc ); | ||
25 | for( int j = 0; j < argc; j++ ) | ||
26 | { | ||
27 | printf("%d: %s\n", j, argv[j] ); | ||
28 | } | ||
29 | printf("---------------------------\n" ); | ||
30 | printf("SETVAR===\"%s\"\n", str.c_str() ); | ||
31 | |||
32 | return 1; | ||
33 | } | ||
34 | |||
35 | int main( int argc, char *argv[] ) | ||
36 | { | ||
37 | if( argc == 1 ) | ||
38 | { | ||
39 | printf("You have to enter some parameter, try '--help'\n\n"); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | Param p; | ||
44 | p.process( argc, argv ); | ||
45 | } | ||
46 | |||
diff --git a/src/old/tests/param.h b/src/old/tests/param.h new file mode 100644 index 0000000..2756b69 --- /dev/null +++ b/src/old/tests/param.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef PARAM_H | ||
2 | #define PARAM_H | ||
3 | |||
4 | #include <stdint.h> | ||
5 | |||
6 | #include "paramproc.h" | ||
7 | |||
8 | class Param : public ParamProc | ||
9 | { | ||
10 | public: | ||
11 | Param(); | ||
12 | virtual ~Param(); | ||
13 | |||
14 | private: | ||
15 | int printStuff( int argc, char *argv[] ); | ||
16 | |||
17 | std::string str; | ||
18 | uint32_t uint32; | ||
19 | }; | ||
20 | |||
21 | #endif | ||
diff --git a/src/old/tests/plugin/main.cpp b/src/old/tests/plugin/main.cpp new file mode 100644 index 0000000..51c8390 --- /dev/null +++ b/src/old/tests/plugin/main.cpp | |||
@@ -0,0 +1,14 @@ | |||
1 | #include "plugger.h" | ||
2 | #include "plugin.h" | ||
3 | |||
4 | int main() | ||
5 | { | ||
6 | Plugger<Plugin> p; | ||
7 | |||
8 | p.registerExternalPlugin( "./guy.so", "Guy" ); | ||
9 | |||
10 | Plugin *t = p.instantiate( "Guy" ); | ||
11 | |||
12 | p.destroy( t ); | ||
13 | } | ||
14 | |||
diff --git a/src/old/tests/plugin/plugin.cpp b/src/old/tests/plugin/plugin.cpp new file mode 100644 index 0000000..ea558fd --- /dev/null +++ b/src/old/tests/plugin/plugin.cpp | |||
@@ -0,0 +1,10 @@ | |||
1 | #include "plugin.h" | ||
2 | |||
3 | Plugin::Plugin() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | Plugin::~Plugin() | ||
8 | { | ||
9 | } | ||
10 | |||
diff --git a/src/old/tests/plugin/plugin.h b/src/old/tests/plugin/plugin.h new file mode 100644 index 0000000..f726867 --- /dev/null +++ b/src/old/tests/plugin/plugin.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef PLUGIN_H | ||
2 | #define PLUGIN_H | ||
3 | |||
4 | class Plugin | ||
5 | { | ||
6 | public: | ||
7 | Plugin(); | ||
8 | virtual ~Plugin(); | ||
9 | |||
10 | private: | ||
11 | |||
12 | }; | ||
13 | |||
14 | #endif | ||
diff --git a/src/old/tests/qsort.cpp b/src/old/tests/qsort.cpp new file mode 100644 index 0000000..28c6f03 --- /dev/null +++ b/src/old/tests/qsort.cpp | |||
@@ -0,0 +1,228 @@ | |||
1 | #define _QSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t))) | ||
2 | |||
3 | /* Discontinue quicksort algorithm when partition gets below this size. | ||
4 | This particular magic number was chosen to work best on a Sun 4/260. */ | ||
5 | #define _QSORT_MAX_THRESH 4 | ||
6 | |||
7 | /* Stack node declarations used to store unfulfilled partition obligations | ||
8 | * (inlined in QSORT). | ||
9 | typedef struct { | ||
10 | QSORT_TYPE *_lo, *_hi; | ||
11 | } qsort_stack_node; | ||
12 | */ | ||
13 | |||
14 | /* The next 4 #defines implement a very fast in-line stack abstraction. */ | ||
15 | /* The stack needs log (total_elements) entries (we could even subtract | ||
16 | log(MAX_THRESH)). Since total_elements has type unsigned, we get as | ||
17 | upper bound for log (total_elements): | ||
18 | bits per byte (CHAR_BIT) * sizeof(unsigned). */ | ||
19 | #define _QSORT_STACK_SIZE (8 * sizeof(unsigned)) | ||
20 | #define _QSORT_PUSH(top, low, high) \ | ||
21 | (((top->_lo = (low)), (top->_hi = (high)), ++top)) | ||
22 | #define _QSORT_POP(low, high, top) \ | ||
23 | ((--top, (low = top->_lo), (high = top->_hi))) | ||
24 | #define _QSORT_STACK_NOT_EMPTY (_stack < _top) | ||
25 | |||
26 | |||
27 | /* Order size using quicksort. This implementation incorporates | ||
28 | four optimizations discussed in Sedgewick: | ||
29 | |||
30 | 1. Non-recursive, using an explicit stack of pointer that store the | ||
31 | next array partition to sort. To save time, this maximum amount | ||
32 | of space required to store an array of SIZE_MAX is allocated on the | ||
33 | stack. Assuming a 32-bit (64 bit) integer for size_t, this needs | ||
34 | only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). | ||
35 | Pretty cheap, actually. | ||
36 | |||
37 | 2. Chose the pivot element using a median-of-three decision tree. | ||
38 | This reduces the probability of selecting a bad pivot value and | ||
39 | eliminates certain extraneous comparisons. | ||
40 | |||
41 | 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving | ||
42 | insertion sort to order the MAX_THRESH items within each partition. | ||
43 | This is a big win, since insertion sort is faster for small, mostly | ||
44 | sorted array segments. | ||
45 | |||
46 | 4. The larger of the two sub-partitions is always pushed onto the | ||
47 | stack first, with the algorithm then concentrating on the | ||
48 | smaller partition. This *guarantees* no more than log (total_elems) | ||
49 | stack size is needed (actually O(1) in this case)! */ | ||
50 | |||
51 | /* The main code starts here... */ | ||
52 | |||
53 | template<typename QSORT_TYPE, typename QSORT_LTT> | ||
54 | void qsrt( QSORT_TYPE *QSORT_BASE, int QSORT_NELT ) | ||
55 | { | ||
56 | QSORT_LTT QSORT_LT; | ||
57 | QSORT_TYPE *const _base = (QSORT_BASE); | ||
58 | const unsigned _elems = (QSORT_NELT); | ||
59 | QSORT_TYPE _hold; | ||
60 | |||
61 | /* Don't declare two variables of type QSORT_TYPE in a single | ||
62 | * statement: eg `TYPE a, b;', in case if TYPE is a pointer, | ||
63 | * expands to `type* a, b;' wich isn't what we want. | ||
64 | */ | ||
65 | |||
66 | if (_elems > _QSORT_MAX_THRESH) { | ||
67 | QSORT_TYPE *_lo = _base; | ||
68 | QSORT_TYPE *_hi = _lo + _elems - 1; | ||
69 | struct { | ||
70 | QSORT_TYPE *_hi; QSORT_TYPE *_lo; | ||
71 | } _stack[_QSORT_STACK_SIZE], *_top = _stack + 1; | ||
72 | |||
73 | while (_QSORT_STACK_NOT_EMPTY) { | ||
74 | QSORT_TYPE *_left_ptr; QSORT_TYPE *_right_ptr; | ||
75 | |||
76 | /* Select median value from among LO, MID, and HI. Rearrange | ||
77 | LO and HI so the three values are sorted. This lowers the | ||
78 | probability of picking a pathological pivot value and | ||
79 | skips a comparison for both the LEFT_PTR and RIGHT_PTR in | ||
80 | the while loops. */ | ||
81 | |||
82 | QSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); | ||
83 | |||
84 | if (QSORT_LT (_mid, _lo)) | ||
85 | _QSORT_SWAP (_mid, _lo, _hold); | ||
86 | if (QSORT_LT (_hi, _mid)) | ||
87 | _QSORT_SWAP (_mid, _hi, _hold); | ||
88 | else | ||
89 | goto _jump_over; | ||
90 | if (QSORT_LT (_mid, _lo)) | ||
91 | _QSORT_SWAP (_mid, _lo, _hold); | ||
92 | _jump_over:; | ||
93 | |||
94 | _left_ptr = _lo + 1; | ||
95 | _right_ptr = _hi - 1; | ||
96 | |||
97 | /* Here's the famous ``collapse the walls'' section of quicksort. | ||
98 | Gotta like those tight inner loops! They are the main reason | ||
99 | that this algorithm runs much faster than others. */ | ||
100 | do { | ||
101 | while (QSORT_LT (_left_ptr, _mid)) | ||
102 | ++_left_ptr; | ||
103 | |||
104 | while (QSORT_LT (_mid, _right_ptr)) | ||
105 | --_right_ptr; | ||
106 | |||
107 | if (_left_ptr < _right_ptr) { | ||
108 | _QSORT_SWAP (_left_ptr, _right_ptr, _hold); | ||
109 | if (_mid == _left_ptr) | ||
110 | _mid = _right_ptr; | ||
111 | else if (_mid == _right_ptr) | ||
112 | _mid = _left_ptr; | ||
113 | ++_left_ptr; | ||
114 | --_right_ptr; | ||
115 | } | ||
116 | else if (_left_ptr == _right_ptr) { | ||
117 | ++_left_ptr; | ||
118 | --_right_ptr; | ||
119 | break; | ||
120 | } | ||
121 | } while (_left_ptr <= _right_ptr); | ||
122 | |||
123 | /* Set up pointers for next iteration. First determine whether | ||
124 | left and right partitions are below the threshold size. If so, | ||
125 | ignore one or both. Otherwise, push the larger partition's | ||
126 | bounds on the stack and continue sorting the smaller one. */ | ||
127 | |||
128 | if (_right_ptr - _lo <= _QSORT_MAX_THRESH) { | ||
129 | if (_hi - _left_ptr <= _QSORT_MAX_THRESH) | ||
130 | /* Ignore both small partitions. */ | ||
131 | _QSORT_POP (_lo, _hi, _top); | ||
132 | else | ||
133 | /* Ignore small left partition. */ | ||
134 | _lo = _left_ptr; | ||
135 | } | ||
136 | else if (_hi - _left_ptr <= _QSORT_MAX_THRESH) | ||
137 | /* Ignore small right partition. */ | ||
138 | _hi = _right_ptr; | ||
139 | else if (_right_ptr - _lo > _hi - _left_ptr) { | ||
140 | /* Push larger left partition indices. */ | ||
141 | _QSORT_PUSH (_top, _lo, _right_ptr); | ||
142 | _lo = _left_ptr; | ||
143 | } | ||
144 | else { | ||
145 | /* Push larger right partition indices. */ | ||
146 | _QSORT_PUSH (_top, _left_ptr, _hi); | ||
147 | _hi = _right_ptr; | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /* Once the BASE array is partially sorted by quicksort the rest | ||
153 | is completely sorted using insertion sort, since this is efficient | ||
154 | for partitions below MAX_THRESH size. BASE points to the | ||
155 | beginning of the array to sort, and END_PTR points at the very | ||
156 | last element in the array (*not* one beyond it!). */ | ||
157 | |||
158 | { | ||
159 | QSORT_TYPE *const _end_ptr = _base + _elems - 1; | ||
160 | QSORT_TYPE *_tmp_ptr = _base; | ||
161 | register QSORT_TYPE *_run_ptr; | ||
162 | QSORT_TYPE *_thresh; | ||
163 | |||
164 | _thresh = _base + _QSORT_MAX_THRESH; | ||
165 | if (_thresh > _end_ptr) | ||
166 | _thresh = _end_ptr; | ||
167 | |||
168 | /* Find smallest element in first threshold and place it at the | ||
169 | array's beginning. This is the smallest array element, | ||
170 | and the operation speeds up insertion sort's inner loop. */ | ||
171 | |||
172 | for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) | ||
173 | if (QSORT_LT (_run_ptr, _tmp_ptr)) | ||
174 | _tmp_ptr = _run_ptr; | ||
175 | |||
176 | if (_tmp_ptr != _base) | ||
177 | _QSORT_SWAP (_tmp_ptr, _base, _hold); | ||
178 | |||
179 | /* Insertion sort, running from left-hand-side | ||
180 | * up to right-hand-side. */ | ||
181 | |||
182 | _run_ptr = _base + 1; | ||
183 | while (++_run_ptr <= _end_ptr) { | ||
184 | _tmp_ptr = _run_ptr - 1; | ||
185 | while (QSORT_LT (_run_ptr, _tmp_ptr)) | ||
186 | --_tmp_ptr; | ||
187 | |||
188 | ++_tmp_ptr; | ||
189 | if (_tmp_ptr != _run_ptr) { | ||
190 | QSORT_TYPE *_trav = _run_ptr + 1; | ||
191 | while (--_trav >= _run_ptr) { | ||
192 | QSORT_TYPE *_hi; QSORT_TYPE *_lo; | ||
193 | _hold = *_trav; | ||
194 | |||
195 | for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) | ||
196 | *_hi = *_lo; | ||
197 | *_hi = _hold; | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | |||
203 | } | ||
204 | |||
205 | |||
206 | struct cc | ||
207 | { | ||
208 | bool operator()( int *a, int *b ) | ||
209 | { | ||
210 | return *a < *b; | ||
211 | } | ||
212 | }; | ||
213 | |||
214 | #include <stdio.h> | ||
215 | |||
216 | int main() | ||
217 | { | ||
218 | int lst[] = { 43, 1, 342, 12, 491, 32, 12321, 32, 3, -3 }; | ||
219 | |||
220 | for( int j = 0; j < 10; j++ ) | ||
221 | printf("%s%d", (j>0)?", ":"", lst[j] ); | ||
222 | printf("\n"); | ||
223 | qsrt<int, cc>( lst, 10 ); | ||
224 | for( int j = 0; j < 10; j++ ) | ||
225 | printf("%s%d", (j>0)?", ":"", lst[j] ); | ||
226 | printf("\n"); | ||
227 | } | ||
228 | |||
diff --git a/src/old/tests/sbuffer.cpp b/src/old/tests/sbuffer.cpp new file mode 100644 index 0000000..02798cb --- /dev/null +++ b/src/old/tests/sbuffer.cpp | |||
@@ -0,0 +1,27 @@ | |||
1 | #include "sbuffer.h" | ||
2 | |||
3 | int main() | ||
4 | { | ||
5 | SBuffer buf; | ||
6 | |||
7 | buf.write("abcdefg", 7 ); | ||
8 | |||
9 | printf("tell: %ld\n", buf.tell() ); | ||
10 | |||
11 | char abuf[6]; | ||
12 | int nRead; | ||
13 | nRead = buf.read( abuf, 5 ); | ||
14 | abuf[nRead] = '\0'; | ||
15 | printf("Read %d bytes \"%s\"\n", nRead, abuf ); | ||
16 | |||
17 | buf.setPos( 0 ); | ||
18 | nRead = buf.read( abuf, 5 ); | ||
19 | abuf[nRead] = '\0'; | ||
20 | printf("Read %d bytes \"%s\"\n", nRead, abuf ); | ||
21 | |||
22 | nRead = buf.read( abuf, 5 ); | ||
23 | abuf[nRead] = '\0'; | ||
24 | printf("Read %d bytes \"%s\"\n", nRead, abuf ); | ||
25 | |||
26 | } | ||
27 | |||
diff --git a/src/old/tests/serialize.cpp b/src/old/tests/serialize.cpp new file mode 100644 index 0000000..e233704 --- /dev/null +++ b/src/old/tests/serialize.cpp | |||
@@ -0,0 +1,30 @@ | |||
1 | #include "serializerbinary.h" | ||
2 | #include "staticstring.h" | ||
3 | #include <stdio.h> | ||
4 | #include <string> | ||
5 | |||
6 | int main() | ||
7 | { | ||
8 | int32_t one; | ||
9 | double two; | ||
10 | bool three; | ||
11 | StaticString s("Test string!"); | ||
12 | std::string ss("Another test string"); | ||
13 | SerializerBinary ar("hello.dat", false); | ||
14 | ar << (int)85; | ||
15 | ar << (double)2.63434; | ||
16 | ar << false; | ||
17 | ar << ss; | ||
18 | ar.close(); | ||
19 | |||
20 | one = 0; two = 0; three = true; s = "die"; | ||
21 | |||
22 | SerializerBinary ar2("hello.dat", true); | ||
23 | ar2 >> one; | ||
24 | ar2 >> two; | ||
25 | ar2 >> three; | ||
26 | ar2 >> s; | ||
27 | |||
28 | printf("we got %d - %f - %s - \"%s\"\n", one, two, (three ? "true":"false"), s.getString() ); | ||
29 | return 0; | ||
30 | } | ||
diff --git a/src/old/tests/serializetext.cpp b/src/old/tests/serializetext.cpp new file mode 100644 index 0000000..f6be7d3 --- /dev/null +++ b/src/old/tests/serializetext.cpp | |||
@@ -0,0 +1,28 @@ | |||
1 | #include "serializertext.h" | ||
2 | #include "staticstring.h" | ||
3 | #include <iostream> | ||
4 | |||
5 | int main() | ||
6 | { | ||
7 | StaticString s("You're a dog!!"); | ||
8 | SerializerText ar("hello.dat", false); | ||
9 | |||
10 | ar << 4 << 3.993 << true << s; | ||
11 | |||
12 | ar.close(); | ||
13 | |||
14 | int one=0;float two=0.0;bool three=false; s = ""; | ||
15 | |||
16 | SerializerText ar2("hello.dat", true); | ||
17 | |||
18 | ar2 >> one; | ||
19 | ar2 >> two; | ||
20 | ar2 >> three; | ||
21 | ar2 >> s; | ||
22 | |||
23 | //printf("out: %d, %f, %s, \"%s\"\n", one, two, (three ? "true" : "false"), s.getString()); | ||
24 | std::cout << one << ", " << two << ", " << three << ", " << s.getString() << "\n"; | ||
25 | |||
26 | return 0; | ||
27 | } | ||
28 | |||
diff --git a/src/old/tests/sha1.cpp b/src/old/tests/sha1.cpp new file mode 100644 index 0000000..df3113c --- /dev/null +++ b/src/old/tests/sha1.cpp | |||
@@ -0,0 +1,44 @@ | |||
1 | #include "sha1.h" | ||
2 | #include "sfile.h" | ||
3 | |||
4 | #define BS 1024 | ||
5 | |||
6 | int main( int argc, char *argv[] ) | ||
7 | { | ||
8 | argc--; argv++; | ||
9 | |||
10 | if( argc == 0 ) | ||
11 | { | ||
12 | printf("Provide a filename.\n"); | ||
13 | return 0; | ||
14 | } | ||
15 | |||
16 | char buf[BS]; | ||
17 | |||
18 | Sha1 s; | ||
19 | SFile fin( *argv, "rb" ); | ||
20 | for(;;) | ||
21 | { | ||
22 | int nRead = fin.read( buf, BS ); | ||
23 | if( nRead == 0 ) | ||
24 | break; | ||
25 | |||
26 | s.update( buf, nRead ); | ||
27 | if( nRead < BS ) | ||
28 | break; | ||
29 | } | ||
30 | |||
31 | unsigned char *dig = s.getDigest(); | ||
32 | |||
33 | char val[]={"0123456789ABCDEF"}; | ||
34 | |||
35 | for( int j = 0; j < 20; j++ ) | ||
36 | { | ||
37 | putchar( val[dig[j]>>4] ); | ||
38 | putchar( val[dig[j]&0x0F] ); | ||
39 | } | ||
40 | putchar('\n'); | ||
41 | |||
42 | delete[] dig; | ||
43 | } | ||
44 | |||
diff --git a/src/old/tests/sptr.cpp b/src/old/tests/sptr.cpp new file mode 100644 index 0000000..38d3675 --- /dev/null +++ b/src/old/tests/sptr.cpp | |||
@@ -0,0 +1,55 @@ | |||
1 | #include <stdio.h> | ||
2 | #include "sptr.h" | ||
3 | |||
4 | class Annoy | ||
5 | { | ||
6 | public: | ||
7 | Annoy() : nCnt( 0 ) | ||
8 | { | ||
9 | printf("Created.\n"); | ||
10 | } | ||
11 | |||
12 | ~Annoy() | ||
13 | { | ||
14 | printf("Destroyed.\n"); | ||
15 | } | ||
16 | |||
17 | void go() | ||
18 | { | ||
19 | printf("%d: I'm annoying.\n", ++nCnt); | ||
20 | } | ||
21 | |||
22 | int nCnt; | ||
23 | }; | ||
24 | |||
25 | void beAnnoying( SPtr<Annoy> bob ) | ||
26 | { | ||
27 | printf("bob-Count: %d\n", bob.count() ); | ||
28 | bob->go(); | ||
29 | } | ||
30 | |||
31 | int main() | ||
32 | { | ||
33 | SPtr<Annoy> pt( new Annoy ); | ||
34 | printf("Count: %d\n", pt.count() ); | ||
35 | pt->go(); | ||
36 | |||
37 | { | ||
38 | SPtr<Annoy> pt2 = pt; | ||
39 | printf("Count: %d\n", pt2.count() ); | ||
40 | |||
41 | pt2->go(); | ||
42 | |||
43 | { | ||
44 | SPtr<Annoy> pt3( pt2 ); | ||
45 | printf("Count: %d\n", pt3.count() ); | ||
46 | |||
47 | pt3->go(); | ||
48 | |||
49 | beAnnoying( pt3 ); | ||
50 | } | ||
51 | printf("Count: %d\n", pt.count() ); | ||
52 | } | ||
53 | printf("Count: %d\n", pt.count() ); | ||
54 | } | ||
55 | |||
diff --git a/src/old/tests/srvstress.cpp b/src/old/tests/srvstress.cpp new file mode 100644 index 0000000..d9a9a1c --- /dev/null +++ b/src/old/tests/srvstress.cpp | |||
@@ -0,0 +1,91 @@ | |||
1 | #include "connectionmanager.h" | ||
2 | #include "programlink.h" | ||
3 | #include "linkedlist.h" | ||
4 | #include "protocol.h" | ||
5 | |||
6 | class StressProtocol : public Protocol | ||
7 | { | ||
8 | public: | ||
9 | bool onNewData() | ||
10 | { | ||
11 | switch( getConnection()->getInput()[0] ) | ||
12 | { | ||
13 | case 'd': | ||
14 | throw "Hello"; | ||
15 | break; | ||
16 | |||
17 | case 'w': | ||
18 | getConnection()->appendOutput("Hello"); | ||
19 | break; | ||
20 | }; | ||
21 | |||
22 | return true; | ||
23 | } | ||
24 | |||
25 | bool onNewConnection() | ||
26 | { | ||
27 | return true; | ||
28 | } | ||
29 | }; | ||
30 | |||
31 | class StressMonitor : public ConnectionMonitor, public ProgramLink | ||
32 | { | ||
33 | public: | ||
34 | bool init() | ||
35 | { | ||
36 | return true; | ||
37 | } | ||
38 | |||
39 | bool deInit() | ||
40 | { | ||
41 | return true; | ||
42 | } | ||
43 | |||
44 | bool timeSlice() | ||
45 | { | ||
46 | return true; | ||
47 | } | ||
48 | |||
49 | bool onNewConnection( Connection *pCon, int nPort ) | ||
50 | { | ||
51 | StressProtocol *sp = new StressProtocol(); | ||
52 | pCon->setProtocol( sp ); | ||
53 | |||
54 | printf(" sys: New connection: socket(%d), port(%d)\n", | ||
55 | pCon->getSocket(), nPort ); | ||
56 | |||
57 | return true; | ||
58 | } | ||
59 | |||
60 | bool onClosedConnection( Connection *pCon ) | ||
61 | { | ||
62 | printf(" sys: Closed connection: socket(%d)\n", | ||
63 | pCon->getSocket() ); | ||
64 | |||
65 | return true; | ||
66 | } | ||
67 | |||
68 | LinkMessage *processIRM( LinkMessage *pMsg ) | ||
69 | { | ||
70 | return NULL; | ||
71 | } | ||
72 | }; | ||
73 | |||
74 | int main() | ||
75 | { | ||
76 | printf("Starting server...\n"); | ||
77 | |||
78 | ConnectionManager srv; | ||
79 | StressMonitor telnet; | ||
80 | |||
81 | srv.setConnectionMonitor( &telnet ); | ||
82 | |||
83 | srv.startServer( 4001 ); | ||
84 | |||
85 | for(;;) | ||
86 | { | ||
87 | srv.scanConnections( 5000, false ); | ||
88 | } | ||
89 | |||
90 | return 0; | ||
91 | } | ||
diff --git a/src/old/tests/strhash.cpp b/src/old/tests/strhash.cpp new file mode 100644 index 0000000..f6528ca --- /dev/null +++ b/src/old/tests/strhash.cpp | |||
@@ -0,0 +1,12 @@ | |||
1 | #include <stdio.h> | ||
2 | #include "hashfunctionstring.h" | ||
3 | |||
4 | int main( int argc, char *argv[] ) | ||
5 | { | ||
6 | HashFunctionString h; | ||
7 | |||
8 | printf("\"%s\": %lu\n", argv[1], h.hash( argv[1] ) ); | ||
9 | |||
10 | return 0; | ||
11 | } | ||
12 | |||
diff --git a/src/old/tests/teltest/main.cpp b/src/old/tests/teltest/main.cpp new file mode 100644 index 0000000..5d3ec26 --- /dev/null +++ b/src/old/tests/teltest/main.cpp | |||
@@ -0,0 +1,21 @@ | |||
1 | #include "connectionmanager.h" | ||
2 | #include "telnetmonitor.h" | ||
3 | |||
4 | int main() | ||
5 | { | ||
6 | printf("Starting server...\n"); | ||
7 | |||
8 | ConnectionManager srv; | ||
9 | TelnetMonitor telnet; | ||
10 | |||
11 | srv.setConnectionMonitor( &telnet ); | ||
12 | |||
13 | srv.startServer( 4001 ); | ||
14 | |||
15 | for(;;) | ||
16 | { | ||
17 | srv.scanConnections( 5000, false ); | ||
18 | } | ||
19 | |||
20 | return 0; | ||
21 | } | ||
diff --git a/src/old/tests/teltest/telnetmonitor.cpp b/src/old/tests/teltest/telnetmonitor.cpp new file mode 100644 index 0000000..65954eb --- /dev/null +++ b/src/old/tests/teltest/telnetmonitor.cpp | |||
@@ -0,0 +1,54 @@ | |||
1 | #include "telnetmonitor.h" | ||
2 | #include "protocoltelnet.h" | ||
3 | #include <sys/stat.h> | ||
4 | |||
5 | TelnetMonitor::TelnetMonitor() | ||
6 | { | ||
7 | } | ||
8 | |||
9 | TelnetMonitor::~TelnetMonitor() | ||
10 | { | ||
11 | } | ||
12 | |||
13 | bool TelnetMonitor::init() | ||
14 | { | ||
15 | return true; | ||
16 | } | ||
17 | |||
18 | bool TelnetMonitor::deInit() | ||
19 | { | ||
20 | return true; | ||
21 | } | ||
22 | |||
23 | bool TelnetMonitor::timeSlice() | ||
24 | { | ||
25 | for( int j = 0; j < lCon.getSize(); j++ ) | ||
26 | { | ||
27 | if( ((Connection *)lCon[j])->hasInput() ) | ||
28 | { | ||
29 | printf("%s\n", ((Connection *)lCon[j])->getInput() ); | ||
30 | } | ||
31 | } | ||
32 | return true; | ||
33 | } | ||
34 | |||
35 | LinkMessage* TelnetMonitor::processIRM( LinkMessage *pMsg ) | ||
36 | { | ||
37 | return NULL; | ||
38 | } | ||
39 | |||
40 | bool TelnetMonitor::onNewConnection( Connection *pCon, int nPort ) | ||
41 | { | ||
42 | ProtocolTelnet *pt = new ProtocolTelnet(); | ||
43 | pCon->setProtocol( pt ); | ||
44 | |||
45 | lCon.append( pt ); | ||
46 | |||
47 | return true; | ||
48 | } | ||
49 | |||
50 | bool TelnetMonitor::onClosedConnection( Connection *pCon ) | ||
51 | { | ||
52 | return true; | ||
53 | } | ||
54 | |||
diff --git a/src/old/tests/teltest/telnetmonitor.h b/src/old/tests/teltest/telnetmonitor.h new file mode 100644 index 0000000..ba5761e --- /dev/null +++ b/src/old/tests/teltest/telnetmonitor.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #ifndef HTTPCONNECTIONMONITOR_H | ||
2 | #define HTTPCONNECTIONMONITOR_H | ||
3 | |||
4 | #include "connectionmonitor.h" | ||
5 | #include "programlink.h" | ||
6 | #include "linkedlist.h" | ||
7 | |||
8 | class TelnetMonitor : public ConnectionMonitor, public ProgramLink | ||
9 | { | ||
10 | public: | ||
11 | TelnetMonitor(); | ||
12 | ~TelnetMonitor(); | ||
13 | |||
14 | bool init(); | ||
15 | bool deInit(); | ||
16 | bool timeSlice(); | ||
17 | LinkMessage* processIRM( LinkMessage *pMsgIn ); | ||
18 | |||
19 | bool onNewConnection( Connection *pCon, int nPort ); | ||
20 | bool onClosedConnection( Connection *pCon ); | ||
21 | |||
22 | private: | ||
23 | LinkedList lCon; | ||
24 | }; | ||
25 | |||
26 | #endif | ||
diff --git a/src/old/tests/xmlreadtest.cpp b/src/old/tests/xmlreadtest.cpp new file mode 100644 index 0000000..d061810 --- /dev/null +++ b/src/old/tests/xmlreadtest.cpp | |||
@@ -0,0 +1,29 @@ | |||
1 | #include "xmlfilereader.h" | ||
2 | #include "xmlstringreader.h" | ||
3 | #include "xmlfilewriter.h" | ||
4 | |||
5 | int main( int argc, char *argv[] ) | ||
6 | { | ||
7 | if( argc < 4 ) | ||
8 | { | ||
9 | printf("Usage: %s f <file in> <file out>\n", argv[0] ); | ||
10 | printf(" %s s <xml string> <file out>\n\n", argv[0] ); | ||
11 | return 0; | ||
12 | } | ||
13 | |||
14 | if( argv[1][0] == 'f' ) | ||
15 | { | ||
16 | XmlFileReader r( argv[2], true ); | ||
17 | // XmlFileWriter w( argv[3], "\t", r.detatchRoot() ); | ||
18 | // w.write(); | ||
19 | } | ||
20 | else if( argv[1][0] == 's' ) | ||
21 | { | ||
22 | XmlStringReader r( argv[2], true ); | ||
23 | XmlFileWriter w(stdout, "\t", r.detatchRoot() ); | ||
24 | w.write(); | ||
25 | } | ||
26 | |||
27 | return 0; | ||
28 | } | ||
29 | |||
diff --git a/src/old/tests/xmlrepltest.cpp b/src/old/tests/xmlrepltest.cpp new file mode 100644 index 0000000..9667705 --- /dev/null +++ b/src/old/tests/xmlrepltest.cpp | |||
@@ -0,0 +1,31 @@ | |||
1 | #include "xmlwriter.h" | ||
2 | |||
3 | int main() | ||
4 | { | ||
5 | printf("Testing Xml Replacement...\n"); | ||
6 | XmlDocument w; | ||
7 | |||
8 | w.addNode("text"); | ||
9 | w.setContent("this text is before the node. "); | ||
10 | w.addNode("keepme", "This one we keep...", true ); | ||
11 | w.setContent("this text is after."); | ||
12 | w.addNode("deleteme", "This one we don't...", true ); | ||
13 | w.setContent("this is last..." ); | ||
14 | w.closeNode(); | ||
15 | |||
16 | //XmlWriter::writeNode( stdout, w.getRoot(), 0, NULL ); | ||
17 | |||
18 | printf("\n\n"); | ||
19 | |||
20 | //XmlNode *xNode = w.getRoot()->detatchNode( 1 ); | ||
21 | |||
22 | //XmlWriter::writeNode( stdout, w.getRoot(), 0, NULL ); | ||
23 | |||
24 | printf("\n\n"); | ||
25 | |||
26 | //XmlWriter::writeNode( stdout, xNode, 0, NULL ); | ||
27 | |||
28 | printf("\n\n"); | ||
29 | |||
30 | return 0; | ||
31 | } | ||
diff --git a/src/old/tests/xmlwritetest.cpp b/src/old/tests/xmlwritetest.cpp new file mode 100644 index 0000000..a22d19d --- /dev/null +++ b/src/old/tests/xmlwritetest.cpp | |||
@@ -0,0 +1,48 @@ | |||
1 | #include "xmlfilewriter.h" | ||
2 | #include "xmlstringwriter.h" | ||
3 | #include "xmlstringreader.h" | ||
4 | |||
5 | void fillItIn( XmlWriter &w ) | ||
6 | { | ||
7 | w.addNode("thinglist"); | ||
8 | |||
9 | w.addNode("thing"); | ||
10 | w.addProperty("type", " ±î´<M-F6><M-F6>³¸®°êòì¯"); | ||
11 | |||
12 | w.addNode("id", "Klophin²³±¹¸·µ´äêíëã Staff", true ); | ||
13 | w.addNode("name", "Klophin Staff", true ); | ||
14 | w.addNode("durability", "0.01", true ); | ||
15 | w.addNode("size", "0.1", true ); | ||
16 | |||
17 | w.addNode("config"); | ||
18 | w.addNode("damage", "3d6+4", true ); | ||
19 | w.addNode("class", "melee", true ); | ||
20 | w.addNode("type", "bludgeon", true ); | ||
21 | w.addNode("damagedesc", "club/clubs", true ); | ||
22 | w.closeNode(); | ||
23 | |||
24 | w.closeNode(); | ||
25 | |||
26 | w.closeNode(); | ||
27 | } | ||
28 | |||
29 | int main() | ||
30 | { | ||
31 | printf("Testing XmlWriter...\n"); | ||
32 | |||
33 | //XmlStringReader *xsr = new XmlStringReader("<stuff/>"); | ||
34 | |||
35 | //printf("%08X\n%08X\n%08X\n", xsr, (XmlReader *)xsr, (XmlDocument *)xsr ); | ||
36 | |||
37 | //delete (XmlDocument *)xsr; | ||
38 | XmlFileWriter wf("test.xml", "\t"); | ||
39 | |||
40 | fillItIn( wf ); | ||
41 | |||
42 | XmlStringWriter ws("\t"); | ||
43 | fillItIn( ws ); | ||
44 | |||
45 | printf("Now the string version:\n\n%s\n", ws.getString().c_str() ); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
diff --git a/src/old/tokenstring.cpp b/src/old/tokenstring.cpp new file mode 100644 index 0000000..e57ba69 --- /dev/null +++ b/src/old/tokenstring.cpp | |||
@@ -0,0 +1,163 @@ | |||
1 | #include "tokenstring.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | TokenString::TokenString( const char *lpNewTokenString ) | ||
5 | { | ||
6 | lpTokenString = NULL; | ||
7 | if( lpNewTokenString ) | ||
8 | { | ||
9 | parseLine( lpNewTokenString ); | ||
10 | } | ||
11 | } | ||
12 | |||
13 | TokenString::~TokenString() | ||
14 | { | ||
15 | delete[] lpTokenString; | ||
16 | for( int j = 0; j < lToken.getSize(); j++ ) | ||
17 | { | ||
18 | delete[] (((Token *)lToken[j])->lpToken); | ||
19 | delete ((Token *)lToken[j]); | ||
20 | } | ||
21 | } | ||
22 | |||
23 | void TokenString::parseLine( const char *lpNewTokenString ) | ||
24 | { | ||
25 | if( lpTokenString != NULL ) | ||
26 | { | ||
27 | delete[] lpTokenString; | ||
28 | lpTokenString = NULL; | ||
29 | for( int j = 0; j < lToken.getSize(); j++ ) | ||
30 | { | ||
31 | delete[] (((Token *)lToken[j])->lpToken); | ||
32 | delete ((Token *)lToken[j]); | ||
33 | } | ||
34 | lToken.empty(); | ||
35 | } | ||
36 | if( lpNewTokenString == NULL ) | ||
37 | { | ||
38 | lpTokenString = new char[1]; | ||
39 | lpTokenString[0] = '\0'; | ||
40 | lToken.setSize(0); | ||
41 | return; | ||
42 | } | ||
43 | // First order of business, make an internal copy so someone can get it | ||
44 | // if they want to. | ||
45 | int nLen = strlen(lpNewTokenString); | ||
46 | lpTokenString = new char[nLen+1]; | ||
47 | strcpy( lpTokenString, lpNewTokenString ); | ||
48 | |||
49 | // Now we do a preliminary parse. This could be effected by later | ||
50 | // editing and aliasing, but we'll see... | ||
51 | int nTkStart, nTkEnd; | ||
52 | int mode=0; // 0 = startSearch, 1=endSearch | ||
53 | for( int j = 0; j <= nLen; j++ ) | ||
54 | { | ||
55 | if( mode == 0 ) | ||
56 | { | ||
57 | if( lpTokenString[j] != ' ' && | ||
58 | lpTokenString[j] != '\t' ) | ||
59 | { | ||
60 | nTkStart = j; | ||
61 | mode = 1; | ||
62 | } | ||
63 | } | ||
64 | else | ||
65 | { | ||
66 | if( lpTokenString[j] == ' ' || | ||
67 | lpTokenString[j] == '\t' || | ||
68 | lpTokenString[j] == '\0' ) | ||
69 | { | ||
70 | nTkEnd = j-1; | ||
71 | mode = 0; | ||
72 | |||
73 | appendToken( nTkStart, nTkEnd ); | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | } | ||
78 | |||
79 | void TokenString::appendToken( int nStart, int nEnd ) | ||
80 | { | ||
81 | Token *pToken = new Token; | ||
82 | pToken->lpOrig = &lpTokenString[nStart]; | ||
83 | |||
84 | // nStart and nEnd are inclusive, we must add two for the end, and the null | ||
85 | pToken->lpToken = new char[nEnd-nStart+2]; | ||
86 | memcpy( pToken->lpToken, &lpTokenString[nStart], nEnd-nStart+1 ); | ||
87 | pToken->lpToken[nEnd-nStart+1] = '\0'; | ||
88 | |||
89 | // printf("%s\n", pToken->lpToken ); | ||
90 | lToken.append( pToken ); | ||
91 | } | ||
92 | |||
93 | void TokenString::insertToken( int nStart, int nEnd, char *lpOldOrig, const char *lpNewToken, int nIndex ) | ||
94 | { | ||
95 | Token *pToken = new Token; | ||
96 | pToken->lpOrig = lpOldOrig; | ||
97 | |||
98 | // nStart and nEnd are inclusive, we must add two for the end, and the null | ||
99 | pToken->lpToken = new char[nEnd-nStart+2]; | ||
100 | memcpy( pToken->lpToken, &lpNewToken[nStart], nEnd-nStart+1 ); | ||
101 | pToken->lpToken[nEnd-nStart+1] = '\0'; | ||
102 | |||
103 | lToken.insertBefore( pToken, nIndex ); | ||
104 | } | ||
105 | |||
106 | int TokenString::getNumTokens() | ||
107 | { | ||
108 | return lToken.getSize(); | ||
109 | } | ||
110 | |||
111 | char *TokenString::getToken( int nIndex ) | ||
112 | { | ||
113 | if( nIndex >= lToken.getSize() ) return NULL; | ||
114 | return (char *)(((Token *)lToken[nIndex])->lpToken); | ||
115 | } | ||
116 | |||
117 | char *TokenString::getTokenString( int nIndex ) | ||
118 | { | ||
119 | if( nIndex >= lToken.getSize() ) return NULL; | ||
120 | return (char *)(((Token *)lToken[nIndex])->lpOrig); | ||
121 | } | ||
122 | |||
123 | void TokenString::expandTokenTo( int nIndex, char *lpNewToken ) | ||
124 | { | ||
125 | // First, we delete the token at nIndex, then we keep inserting | ||
126 | // at that position... | ||
127 | // We also have to remember the index to the original string, | ||
128 | // since most of what we're expanding to won't be in the origingal | ||
129 | // we need to keep these indexes updated in order to make other parts | ||
130 | // of the system happy. | ||
131 | char *lpOldOrig = ((Token *)lToken[nIndex])->lpOrig; | ||
132 | delete[] ((Token *)lToken[nIndex])->lpToken; | ||
133 | delete ((Token *)lToken[nIndex]); | ||
134 | lToken.deleteAt( nIndex ); | ||
135 | |||
136 | // We'll do this just like we did above, but instead we'll | ||
137 | // do tricky things when we find tokens... | ||
138 | int nLen = strlen(lpNewToken); | ||
139 | int nTkStart, nTkEnd, nNewIndex=nIndex; | ||
140 | int mode=0; // 0 = startSearch, 1=endSearch | ||
141 | for( int j = 0; j <= nLen; j++ ) | ||
142 | { | ||
143 | if( mode == 0 ) | ||
144 | { | ||
145 | if( lpNewToken[j] != ' ' && lpNewToken[j] != '\t' ) | ||
146 | { | ||
147 | nTkStart = j; | ||
148 | mode = 1; | ||
149 | } | ||
150 | } | ||
151 | else | ||
152 | { | ||
153 | if( lpNewToken[j] == ' ' || lpNewToken[j] == '\t' || lpNewToken[j] == '\0' ) | ||
154 | { | ||
155 | nTkEnd = j-1; | ||
156 | mode = 0; | ||
157 | |||
158 | insertToken( nTkStart, nTkEnd, lpOldOrig, lpNewToken, nNewIndex ); | ||
159 | nNewIndex++; | ||
160 | } | ||
161 | } | ||
162 | } | ||
163 | } | ||
diff --git a/src/old/tokenstring.h b/src/old/tokenstring.h new file mode 100644 index 0000000..42f7309 --- /dev/null +++ b/src/old/tokenstring.h | |||
@@ -0,0 +1,114 @@ | |||
1 | #ifndef TOKENSTRING_H | ||
2 | #define TOKENSTRING_H | ||
3 | |||
4 | #include "linkedlist.h" | ||
5 | |||
6 | /** A single tokenized command line. Contains all information necesarry to | ||
7 | * nicely access a stand-alone command line and to perform alias expansion | ||
8 | * inside of that command line. | ||
9 | * When expanding a token, the original command line is left intact, so any | ||
10 | * command usng a command line verbatum (getTokenString not getToken) will get | ||
11 | * the original, and not the expanded version. | ||
12 | * Since indexing into the original command line is also done by token, it | ||
13 | * means that using getTokenString( 0 ) will not always get you the first | ||
14 | * character of the command line, it will get you the first non-whitespace | ||
15 | * character. | ||
16 | * Furthermore, when expanding the expantion string is tokenized as well, | ||
17 | * but since the original string is unchanged, all tokens that expand any | ||
18 | * given index will all retain the same index into the original command line. | ||
19 | *@todo Update this to allow it to break on different types of token | ||
20 | * delimiters. | ||
21 | *@author Mike Buland | ||
22 | */ | ||
23 | class TokenString{ | ||
24 | public: | ||
25 | /** Automatically call parseLine when created. | ||
26 | *@param lpNewTokenString The command line to tokenize | ||
27 | *@author Mike Buland | ||
28 | */ | ||
29 | TokenString( const char *lpNewTokenString=NULL ); | ||
30 | virtual ~TokenString(); | ||
31 | |||
32 | /** Performs a tokenizing parse on the given command line, setting it as | ||
33 | * the internal command line for all future tokenizing (excluding | ||
34 | * expansion) | ||
35 | *@param lpNewTokenString The new command line to set to this object. | ||
36 | *@author Mike Buland | ||
37 | */ | ||
38 | void parseLine( const char *lpNewTokenString ); | ||
39 | |||
40 | /** Appends a token to the list of available tokens. This references the | ||
41 | * internal pointer to the command line, so no token string must be | ||
42 | * specified. | ||
43 | *@param nStart The first character of the token to insert. | ||
44 | *@param nEnd The last character of the token to insert. | ||
45 | *@author Mike Buland | ||
46 | */ | ||
47 | void appendToken( int nStart, int nEnd ); | ||
48 | |||
49 | /** Gets the number of tokens. This is particularly useful post-aliasing | ||
50 | * since the number of tokens may not match what is percieved from the | ||
51 | * original command line. | ||
52 | *@returns The number of available tokens. | ||
53 | *@author Mike Buland | ||
54 | */ | ||
55 | int getNumTokens(); | ||
56 | |||
57 | /** Gets a processed token specified by index. | ||
58 | *@param nIndex The index of the token to retrieve. | ||
59 | *@returns A pointer to the requested token. Please note that these tokens | ||
60 | * may not match the original command line. | ||
61 | *@author Mike Buland | ||
62 | */ | ||
63 | char *getToken( int nIndex ); | ||
64 | |||
65 | /** Gets the original command line based on tokens. Use this if you want | ||
66 | * to perform your own processing on parts of the command line, without | ||
67 | * resorting to tokens. | ||
68 | * The first character in the returned string will always be | ||
69 | * non-whitespace. | ||
70 | *@param nIndex The index of the token to start at, zero gets you the whole | ||
71 | * command line. | ||
72 | *@returns A pointer to the internal original command line string, starting | ||
73 | * at the position of the first non-whitespace character of the token | ||
74 | * specified. | ||
75 | *@author Mike Buland | ||
76 | */ | ||
77 | char *getTokenString( int nIndex=0 ); | ||
78 | |||
79 | /** Expands a token, replacing it with the string lpNewToken, but | ||
80 | * processing the new string for tokens before performing the replacement | ||
81 | *@param nIndex Which token should be replaced. | ||
82 | *@param lpNewToken The string to replace the token with. | ||
83 | *@author Mike Buland | ||
84 | */ | ||
85 | void expandTokenTo( int nIndex, char *lpNewToken ); | ||
86 | |||
87 | /** Inserts a token at any position in the command line. This does not | ||
88 | * effect the original command line. | ||
89 | *@param nStart The start of the token in the string lpNewToken. (inclusive) | ||
90 | *@param nEnd The end of the token in the string lpToken. (inclusive) | ||
91 | *@param lpOldOrig The pointer to the position in the orginal command | ||
92 | * line where this new token should point. | ||
93 | *@param lpNewToken The string containing the new token. May contain more | ||
94 | * than just one token. | ||
95 | *@param nIndex The position to insert the token to. | ||
96 | *@author Mike Buland | ||
97 | */ | ||
98 | void insertToken( int nStart, int nEnd, char *lpOldOrig, const char *lpNewToken, int nIndex ); | ||
99 | |||
100 | private: | ||
101 | char *lpTokenString; /**< The original text that this string came from */ | ||
102 | LinkedList lToken; /**< The list of tokens. */ | ||
103 | |||
104 | /** | ||
105 | * A single token within the token string. | ||
106 | */ | ||
107 | typedef struct Token | ||
108 | { | ||
109 | char *lpOrig; /**< This is just a pointer back to lpTokenString */ | ||
110 | char *lpToken; /**< This is really a whole token */ | ||
111 | } Token; | ||
112 | }; | ||
113 | |||
114 | #endif | ||
diff --git a/src/old/tqsort.h b/src/old/tqsort.h new file mode 100644 index 0000000..c836b4f --- /dev/null +++ b/src/old/tqsort.h | |||
@@ -0,0 +1,207 @@ | |||
1 | #ifndef T_QSORT_H | ||
2 | #define T_QSORT_H | ||
3 | |||
4 | #define _QSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t))) | ||
5 | |||
6 | /* Discontinue quicksort algorithm when partition gets below this size. | ||
7 | This particular magic number was chosen to work best on a Sun 4/260. */ | ||
8 | #define _QSORT_MAX_THRESH 4 | ||
9 | |||
10 | /* Stack node declarations used to store unfulfilled partition obligations | ||
11 | * (inlined in QSORT). | ||
12 | typedef struct { | ||
13 | QSORT_TYPE *_lo, *_hi; | ||
14 | } qsort_stack_node; | ||
15 | */ | ||
16 | |||
17 | /* The next 4 #defines implement a very fast in-line stack abstraction. */ | ||
18 | /* The stack needs log (total_elements) entries (we could even subtract | ||
19 | log(MAX_THRESH)). Since total_elements has type unsigned, we get as | ||
20 | upper bound for log (total_elements): | ||
21 | bits per byte (CHAR_BIT) * sizeof(unsigned). */ | ||
22 | #define _QSORT_STACK_SIZE (8 * sizeof(unsigned)) | ||
23 | #define _QSORT_PUSH(top, low, high) \ | ||
24 | (((top->_lo = (low)), (top->_hi = (high)), ++top)) | ||
25 | #define _QSORT_POP(low, high, top) \ | ||
26 | ((--top, (low = top->_lo), (high = top->_hi))) | ||
27 | #define _QSORT_STACK_NOT_EMPTY (_stack < _top) | ||
28 | |||
29 | |||
30 | /* Order size using quicksort. This implementation incorporates | ||
31 | four optimizations discussed in Sedgewick: | ||
32 | |||
33 | 1. Non-recursive, using an explicit stack of pointer that store the | ||
34 | next array partition to sort. To save time, this maximum amount | ||
35 | of space required to store an array of SIZE_MAX is allocated on the | ||
36 | stack. Assuming a 32-bit (64 bit) integer for size_t, this needs | ||
37 | only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). | ||
38 | Pretty cheap, actually. | ||
39 | |||
40 | 2. Chose the pivot element using a median-of-three decision tree. | ||
41 | This reduces the probability of selecting a bad pivot value and | ||
42 | eliminates certain extraneous comparisons. | ||
43 | |||
44 | 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving | ||
45 | insertion sort to order the MAX_THRESH items within each partition. | ||
46 | This is a big win, since insertion sort is faster for small, mostly | ||
47 | sorted array segments. | ||
48 | |||
49 | 4. The larger of the two sub-partitions is always pushed onto the | ||
50 | stack first, with the algorithm then concentrating on the | ||
51 | smaller partition. This *guarantees* no more than log (total_elems) | ||
52 | stack size is needed (actually O(1) in this case)! */ | ||
53 | |||
54 | /* The main code starts here... */ | ||
55 | |||
56 | template<typename QSORT_TYPE, typename QSORT_LTT, typename CST> | ||
57 | void tqsort( QSORT_TYPE *QSORT_BASE, int QSORT_NELT ) | ||
58 | { | ||
59 | QSORT_LTT QSORT_LT; | ||
60 | QSORT_TYPE *const _base = (QSORT_BASE); | ||
61 | const unsigned _elems = (QSORT_NELT); | ||
62 | QSORT_TYPE _hold; | ||
63 | |||
64 | /* Don't declare two variables of type QSORT_TYPE in a single | ||
65 | * statement: eg `TYPE a, b;', in case if TYPE is a pointer, | ||
66 | * expands to `type* a, b;' wich isn't what we want. | ||
67 | */ | ||
68 | |||
69 | if (_elems > _QSORT_MAX_THRESH) { | ||
70 | QSORT_TYPE *_lo = _base; | ||
71 | QSORT_TYPE *_hi = _lo + _elems - 1; | ||
72 | struct { | ||
73 | QSORT_TYPE *_hi; QSORT_TYPE *_lo; | ||
74 | } _stack[_QSORT_STACK_SIZE], *_top = _stack + 1; | ||
75 | |||
76 | while (_QSORT_STACK_NOT_EMPTY) { | ||
77 | QSORT_TYPE *_left_ptr; QSORT_TYPE *_right_ptr; | ||
78 | |||
79 | /* Select median value from among LO, MID, and HI. Rearrange | ||
80 | LO and HI so the three values are sorted. This lowers the | ||
81 | probability of picking a pathological pivot value and | ||
82 | skips a comparison for both the LEFT_PTR and RIGHT_PTR in | ||
83 | the while loops. */ | ||
84 | |||
85 | QSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); | ||
86 | |||
87 | if (QSORT_LT ((CST)(_mid), (CST)(_lo))) | ||
88 | _QSORT_SWAP (_mid, _lo, _hold); | ||
89 | if (QSORT_LT ((CST)(_hi), (CST)(_mid))) | ||
90 | _QSORT_SWAP (_mid, _hi, _hold); | ||
91 | else | ||
92 | goto _jump_over; | ||
93 | if (QSORT_LT ((CST)(_mid), (CST)(_lo))) | ||
94 | _QSORT_SWAP (_mid, _lo, _hold); | ||
95 | _jump_over:; | ||
96 | |||
97 | _left_ptr = _lo + 1; | ||
98 | _right_ptr = _hi - 1; | ||
99 | |||
100 | /* Here's the famous ``collapse the walls'' section of quicksort. | ||
101 | Gotta like those tight inner loops! They are the main reason | ||
102 | that this algorithm runs much faster than others. */ | ||
103 | do { | ||
104 | while (QSORT_LT ((CST)(_left_ptr), (CST)(_mid))) | ||
105 | ++_left_ptr; | ||
106 | |||
107 | while (QSORT_LT ((CST)(_mid), (CST)(_right_ptr))) | ||
108 | --_right_ptr; | ||
109 | |||
110 | if (_left_ptr < _right_ptr) { | ||
111 | _QSORT_SWAP (_left_ptr, _right_ptr, _hold); | ||
112 | if (_mid == _left_ptr) | ||
113 | _mid = _right_ptr; | ||
114 | else if (_mid == _right_ptr) | ||
115 | _mid = _left_ptr; | ||
116 | ++_left_ptr; | ||
117 | --_right_ptr; | ||
118 | } | ||
119 | else if (_left_ptr == _right_ptr) { | ||
120 | ++_left_ptr; | ||
121 | --_right_ptr; | ||
122 | break; | ||
123 | } | ||
124 | } while (_left_ptr <= _right_ptr); | ||
125 | |||
126 | /* Set up pointers for next iteration. First determine whether | ||
127 | left and right partitions are below the threshold size. If so, | ||
128 | ignore one or both. Otherwise, push the larger partition's | ||
129 | bounds on the stack and continue sorting the smaller one. */ | ||
130 | |||
131 | if (_right_ptr - _lo <= _QSORT_MAX_THRESH) { | ||
132 | if (_hi - _left_ptr <= _QSORT_MAX_THRESH) | ||
133 | /* Ignore both small partitions. */ | ||
134 | _QSORT_POP (_lo, _hi, _top); | ||
135 | else | ||
136 | /* Ignore small left partition. */ | ||
137 | _lo = _left_ptr; | ||
138 | } | ||
139 | else if (_hi - _left_ptr <= _QSORT_MAX_THRESH) | ||
140 | /* Ignore small right partition. */ | ||
141 | _hi = _right_ptr; | ||
142 | else if (_right_ptr - _lo > _hi - _left_ptr) { | ||
143 | /* Push larger left partition indices. */ | ||
144 | _QSORT_PUSH (_top, _lo, _right_ptr); | ||
145 | _lo = _left_ptr; | ||
146 | } | ||
147 | else { | ||
148 | /* Push larger right partition indices. */ | ||
149 | _QSORT_PUSH (_top, _left_ptr, _hi); | ||
150 | _hi = _right_ptr; | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /* Once the BASE array is partially sorted by quicksort the rest | ||
156 | is completely sorted using insertion sort, since this is efficient | ||
157 | for partitions below MAX_THRESH size. BASE points to the | ||
158 | beginning of the array to sort, and END_PTR points at the very | ||
159 | last element in the array (*not* one beyond it!). */ | ||
160 | |||
161 | { | ||
162 | QSORT_TYPE *const _end_ptr = _base + _elems - 1; | ||
163 | QSORT_TYPE *_tmp_ptr = _base; | ||
164 | register QSORT_TYPE *_run_ptr; | ||
165 | QSORT_TYPE *_thresh; | ||
166 | |||
167 | _thresh = _base + _QSORT_MAX_THRESH; | ||
168 | if (_thresh > _end_ptr) | ||
169 | _thresh = _end_ptr; | ||
170 | |||
171 | /* Find smallest element in first threshold and place it at the | ||
172 | array's beginning. This is the smallest array element, | ||
173 | and the operation speeds up insertion sort's inner loop. */ | ||
174 | |||
175 | for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) | ||
176 | if (QSORT_LT ((CST)(_run_ptr), (CST)(_tmp_ptr))) | ||
177 | _tmp_ptr = _run_ptr; | ||
178 | |||
179 | if (_tmp_ptr != _base) | ||
180 | _QSORT_SWAP (_tmp_ptr, _base, _hold); | ||
181 | |||
182 | /* Insertion sort, running from left-hand-side | ||
183 | * up to right-hand-side. */ | ||
184 | |||
185 | _run_ptr = _base + 1; | ||
186 | while (++_run_ptr <= _end_ptr) { | ||
187 | _tmp_ptr = _run_ptr - 1; | ||
188 | while (QSORT_LT ((CST)(_run_ptr), (CST)(_tmp_ptr))) | ||
189 | --_tmp_ptr; | ||
190 | |||
191 | ++_tmp_ptr; | ||
192 | if (_tmp_ptr != _run_ptr) { | ||
193 | QSORT_TYPE *_trav = _run_ptr + 1; | ||
194 | while (--_trav >= _run_ptr) { | ||
195 | QSORT_TYPE *_hi; QSORT_TYPE *_lo; | ||
196 | _hold = *_trav; | ||
197 | |||
198 | for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) | ||
199 | *_hi = *_lo; | ||
200 | *_hi = _hold; | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | #endif | ||
diff --git a/src/old/unit/hashtable/hashtable.cpp b/src/old/unit/hashtable/hashtable.cpp new file mode 100644 index 0000000..b2e1cf5 --- /dev/null +++ b/src/old/unit/hashtable/hashtable.cpp | |||
@@ -0,0 +1,107 @@ | |||
1 | #include <cstdlib> | ||
2 | #include <cstring> | ||
3 | #include <iostream> | ||
4 | #include <cpptest.h> | ||
5 | #include <string.h> | ||
6 | #include <set> | ||
7 | #include <map> | ||
8 | |||
9 | #include "hashfunctionstring.h" | ||
10 | #include "hashfunctioncasestring.h" | ||
11 | #include "hashfunctionint.h" | ||
12 | |||
13 | class HashFunctionSuite : public Test::Suite | ||
14 | { | ||
15 | public: | ||
16 | HashFunctionSuite() | ||
17 | { | ||
18 | TEST_ADD( HashFunctionSuite::functionString ) | ||
19 | TEST_ADD( HashFunctionSuite::functionCaseString ) | ||
20 | TEST_ADD( HashFunctionSuite::functionInt ) | ||
21 | } | ||
22 | |||
23 | private: | ||
24 | void functionStringWorker( HashFunction &hf, std::set<unsigned long> &sCodes, char *str, int nLevel, int nMax ) | ||
25 | { | ||
26 | for( char let = 'A'; let <= 'z'; let += 3 ) | ||
27 | { | ||
28 | str[nLevel+1] = '\0'; | ||
29 | str[nLevel] = let; | ||
30 | unsigned long x = hf.hash( str ); | ||
31 | TEST_ASSERT( sCodes.find( x ) == sCodes.end() ); | ||
32 | TEST_ASSERT( hf.cmpIDs( str, str ) ); | ||
33 | sCodes.insert( x ); | ||
34 | |||
35 | if( nLevel < nMax ) | ||
36 | functionStringWorker( hf, sCodes, str, nLevel+1, nMax ); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | void functionString() | ||
41 | { | ||
42 | HashFunctionString hf; | ||
43 | char str[10]; | ||
44 | |||
45 | std::set<unsigned long> sCodes; | ||
46 | |||
47 | functionStringWorker( hf, sCodes, str, 0, 3 ); | ||
48 | } | ||
49 | |||
50 | void functionCaseStringWorker( HashFunction &hf, std::map<unsigned long, char *> &sCodes, char *str, int nLevel, int nMax ) | ||
51 | { | ||
52 | for( char let = 'A'; let <= 'z'; let += 3 ) | ||
53 | { | ||
54 | str[nLevel+1] = '\0'; | ||
55 | str[nLevel] = let; | ||
56 | unsigned long x = hf.hash( str ); | ||
57 | std::map<unsigned long, char *>::iterator i = sCodes.find( x ); | ||
58 | if( i == sCodes.end() ) | ||
59 | { | ||
60 | sCodes[x] = strdup( str ); | ||
61 | } | ||
62 | else | ||
63 | { | ||
64 | TEST_ASSERT( strcasecmp( (*i).second, str ) == 0 ); | ||
65 | TEST_ASSERT( hf.cmpIDs( (*i).second, str ) == true ); | ||
66 | } | ||
67 | |||
68 | if( nLevel < nMax ) | ||
69 | functionCaseStringWorker( hf, sCodes, str, nLevel+1, nMax ); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | void functionCaseString() | ||
74 | { | ||
75 | HashFunctionCaseString hf; | ||
76 | char str[10]; | ||
77 | |||
78 | std::map<unsigned long, char *> sCodes; | ||
79 | |||
80 | functionCaseStringWorker( hf, sCodes, str, 0, 3 ); | ||
81 | |||
82 | std::map<unsigned long, char *>::iterator i; | ||
83 | for( i = sCodes.begin(); i != sCodes.end(); i++ ) | ||
84 | { | ||
85 | free( (*i).second ); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | void functionInt() | ||
90 | { | ||
91 | HashFunctionInt hf; | ||
92 | |||
93 | for( long i = -100000; i <= 100000; i += 100 ) | ||
94 | { | ||
95 | TEST_ASSERT( ((long)hf.hash( (void *)i )) == i ); | ||
96 | TEST_ASSERT( ((long)hf.cmpIDs( (void *)i, (void *)i )) ); | ||
97 | } | ||
98 | } | ||
99 | }; | ||
100 | |||
101 | int main( int argc, char *argv[] ) | ||
102 | { | ||
103 | Test::TextOutput output( Test::TextOutput::Verbose ); | ||
104 | HashFunctionSuite ts; | ||
105 | return ts.run( output ) ? EXIT_SUCCESS : EXIT_FAILURE; | ||
106 | } | ||
107 | |||
diff --git a/src/old/unit/xml/xml.cpp b/src/old/unit/xml/xml.cpp new file mode 100644 index 0000000..e4d779c --- /dev/null +++ b/src/old/unit/xml/xml.cpp | |||
@@ -0,0 +1,59 @@ | |||
1 | #include <cstdlib> | ||
2 | #include <cstring> | ||
3 | #include <iostream> | ||
4 | #include <cpptest.h> | ||
5 | #include <string.h> | ||
6 | |||
7 | #include "xmlstringreader.h" | ||
8 | #include "xmlexception.h" | ||
9 | |||
10 | class XmlCoreTestSuite : public Test::Suite | ||
11 | { | ||
12 | public: | ||
13 | XmlCoreTestSuite() | ||
14 | { | ||
15 | TEST_ADD( XmlCoreTestSuite::badXml01 ) | ||
16 | TEST_ADD( XmlCoreTestSuite::badXml02 ) | ||
17 | TEST_ADD( XmlCoreTestSuite::badXml03 ) | ||
18 | |||
19 | TEST_ADD( XmlCoreTestSuite::entityBuiltin01 ) | ||
20 | |||
21 | TEST_ADD( XmlCoreTestSuite::entityDoc01 ) | ||
22 | } | ||
23 | |||
24 | private: | ||
25 | void badXml01() | ||
26 | { | ||
27 | TEST_THROWS( XmlStringReader r("<hello></bye>"), XmlException & ); | ||
28 | } | ||
29 | |||
30 | void badXml02() | ||
31 | { | ||
32 | TEST_THROWS( XmlStringReader r("<hello>"), XmlException & ); | ||
33 | } | ||
34 | |||
35 | void badXml03() | ||
36 | { | ||
37 | TEST_THROWS( XmlStringReader r("<hello param=\"stuff?"), XmlException & ); | ||
38 | } | ||
39 | |||
40 | void entityBuiltin01() | ||
41 | { | ||
42 | XmlStringReader r("<hello>><&'"</hello>"); | ||
43 | TEST_ASSERT( strcmp( r.getRoot()->getContent(), "><&\'\"" ) == 0 ); | ||
44 | } | ||
45 | |||
46 | void entityDoc01() | ||
47 | { | ||
48 | XmlStringReader r("<!ENTITY name \"bob the man\"><hello>"&name;"</hello>"); | ||
49 | TEST_ASSERT( strcmp( r.getRoot()->getContent(), "\"bob the man\"" ) == 0 ); | ||
50 | } | ||
51 | }; | ||
52 | |||
53 | int main( int argc, char *argv[] ) | ||
54 | { | ||
55 | Test::TextOutput output( Test::TextOutput::Verbose ); | ||
56 | XmlCoreTestSuite ts; | ||
57 | return ts.run( output ) ? EXIT_SUCCESS : EXIT_FAILURE; | ||
58 | } | ||
59 | |||
diff --git a/src/old/xmldocument.cpp b/src/old/xmldocument.cpp new file mode 100644 index 0000000..d7867d5 --- /dev/null +++ b/src/old/xmldocument.cpp | |||
@@ -0,0 +1,149 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "xmlwriter.h" | ||
4 | |||
5 | XmlDocument::XmlDocument( XmlNode *pRoot ) | ||
6 | { | ||
7 | this->pRoot = pRoot; | ||
8 | pCurrent = NULL; | ||
9 | bCompleted = (pRoot!=NULL); | ||
10 | } | ||
11 | |||
12 | XmlDocument::~XmlDocument() | ||
13 | { | ||
14 | if( pRoot ) | ||
15 | { | ||
16 | delete pRoot; | ||
17 | } | ||
18 | } | ||
19 | |||
20 | void XmlDocument::addNode( const char *sName, const char *sContent, bool bClose ) | ||
21 | { | ||
22 | if( pRoot == NULL ) | ||
23 | { | ||
24 | // This is the first node, so ignore position and just insert it. | ||
25 | pCurrent = pRoot = new XmlNode( sName, NULL, sContent ); | ||
26 | } | ||
27 | else | ||
28 | { | ||
29 | pCurrent = pCurrent->addChild( sName, sContent ); | ||
30 | } | ||
31 | |||
32 | if( bClose ) | ||
33 | { | ||
34 | closeNode(); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | void XmlDocument::setName( const char *sName ) | ||
39 | { | ||
40 | pCurrent->setName( sName ); | ||
41 | } | ||
42 | |||
43 | bool XmlDocument::isCompleted() | ||
44 | { | ||
45 | return bCompleted; | ||
46 | } | ||
47 | |||
48 | XmlNode *XmlDocument::getRoot() | ||
49 | { | ||
50 | return pRoot; | ||
51 | } | ||
52 | |||
53 | XmlNode *XmlDocument::detatchRoot() | ||
54 | { | ||
55 | XmlNode *pTemp = pRoot; | ||
56 | pRoot = NULL; | ||
57 | return pTemp; | ||
58 | } | ||
59 | |||
60 | XmlNode *XmlDocument::getCurrent() | ||
61 | { | ||
62 | return pCurrent; | ||
63 | } | ||
64 | |||
65 | void XmlDocument::closeNode() | ||
66 | { | ||
67 | if( pCurrent != NULL ) | ||
68 | { | ||
69 | pCurrent = pCurrent->getParent(); | ||
70 | |||
71 | if( pCurrent == NULL ) | ||
72 | { | ||
73 | bCompleted = true; | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | |||
78 | void XmlDocument::addProperty( const char *sName, const char *sValue ) | ||
79 | { | ||
80 | if( pCurrent ) | ||
81 | { | ||
82 | pCurrent->addProperty( sName, sValue ); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | void XmlDocument::addProperty( const char *sName, const unsigned char nValue ) | ||
87 | { | ||
88 | char buf[12]; | ||
89 | sprintf( buf, "%hhi", nValue ); | ||
90 | addProperty( sName, buf ); | ||
91 | } | ||
92 | |||
93 | void XmlDocument::addProperty( const char *sName, const char nValue ) | ||
94 | { | ||
95 | char buf[12]; | ||
96 | sprintf( buf, "%hhi", nValue ); | ||
97 | addProperty( sName, buf ); | ||
98 | } | ||
99 | |||
100 | void XmlDocument::addProperty( const char *sName, const unsigned short nValue ) | ||
101 | { | ||
102 | char buf[12]; | ||
103 | sprintf( buf, "%hi", nValue ); | ||
104 | addProperty( sName, buf ); | ||
105 | } | ||
106 | |||
107 | void XmlDocument::addProperty( const char *sName, const short nValue ) | ||
108 | { | ||
109 | char buf[12]; | ||
110 | sprintf( buf, "%hi", nValue ); | ||
111 | addProperty( sName, buf ); | ||
112 | } | ||
113 | |||
114 | void XmlDocument::addProperty( const char *sName, const int nValue ) | ||
115 | { | ||
116 | char buf[12]; | ||
117 | sprintf( buf, "%d", nValue ); | ||
118 | addProperty( sName, buf ); | ||
119 | } | ||
120 | |||
121 | void XmlDocument::addProperty( const char *sName, const unsigned long nValue ) | ||
122 | { | ||
123 | char buf[12]; | ||
124 | sprintf( buf, "%li", nValue ); | ||
125 | addProperty( sName, buf ); | ||
126 | } | ||
127 | |||
128 | void XmlDocument::addProperty( const char *sName, const long nValue ) | ||
129 | { | ||
130 | char buf[12]; | ||
131 | sprintf( buf, "%li", nValue ); | ||
132 | addProperty( sName, buf ); | ||
133 | } | ||
134 | |||
135 | void XmlDocument::addProperty( const char *sName, const double dValue ) | ||
136 | { | ||
137 | char buf[40]; | ||
138 | sprintf( buf, "%f", dValue ); | ||
139 | addProperty( sName, buf ); | ||
140 | } | ||
141 | |||
142 | void XmlDocument::setContent( const char *sContent ) | ||
143 | { | ||
144 | if( pCurrent ) | ||
145 | { | ||
146 | pCurrent->setContent( sContent ); | ||
147 | } | ||
148 | } | ||
149 | |||
diff --git a/src/old/xmldocument.h b/src/old/xmldocument.h new file mode 100644 index 0000000..6671c41 --- /dev/null +++ b/src/old/xmldocument.h | |||
@@ -0,0 +1,171 @@ | |||
1 | #ifndef XMLDOCUMENT | ||
2 | #define XMLDOCUMENT | ||
3 | |||
4 | #include "xmlnode.h" | ||
5 | |||
6 | /** | ||
7 | * Keeps track of an easily managed set of XmlNode information. Allows simple | ||
8 | * operations for logical writing to and reading from XML structures. Using | ||
9 | * already formed structures is simply done through the XmlNode structures, | ||
10 | * and the getRoot function here. Creation is performed through a simple set | ||
11 | * of operations that creates the data in a stream type format. | ||
12 | *@author Mike Buland | ||
13 | */ | ||
14 | class XmlDocument | ||
15 | { | ||
16 | public: | ||
17 | /** | ||
18 | * Construct either a blank XmlDocuemnt or construct a document around an | ||
19 | * existing XmlNode. Be careful, once an XmlNode is passed into a document | ||
20 | * the document takes over ownership and will delete it when the XmlDocument | ||
21 | * is deleted. | ||
22 | *@param pRoot The XmlNode to use as the root of this document, or NULL if | ||
23 | * you want to start a new document. | ||
24 | */ | ||
25 | XmlDocument( XmlNode *pRoot=NULL ); | ||
26 | |||
27 | /** | ||
28 | * Destroy all contained nodes. | ||
29 | */ | ||
30 | virtual ~XmlDocument(); | ||
31 | |||
32 | /** | ||
33 | * Add a new node to the document. The new node is appended to the end of | ||
34 | * the current context, i.e. XmlNode, and the new node, provided it isn't | ||
35 | * close as part of this operation, will become the current context. | ||
36 | *@param sName The name of the new node to add. | ||
37 | *@param sContent A content string to be placed inside of the new node. | ||
38 | *@param bClose Set this to true to close the node immediately after adding | ||
39 | * the node and setting the content and name. If this is set to true the | ||
40 | * node is appended, but the context node doesn't change. | ||
41 | */ | ||
42 | void addNode( const char *sName=NULL, const char *sContent=NULL, bool bClose=false ); | ||
43 | |||
44 | /** | ||
45 | * Set the name of the current node context. | ||
46 | *@param sName The new name of the node. | ||
47 | */ | ||
48 | void setName( const char *sName ); | ||
49 | |||
50 | /** | ||
51 | * Close the current node context. This will move the current context to | ||
52 | * the parent node of the former current node. If the current node was the | ||
53 | * root then the "completed" flag is set and no more operations are allowed. | ||
54 | */ | ||
55 | void closeNode(); | ||
56 | |||
57 | /** | ||
58 | * Change the content of the current node at the current position between | ||
59 | * nodes. | ||
60 | *@param sContent The new content of the current node. | ||
61 | */ | ||
62 | void setContent( const char *sContent ); | ||
63 | |||
64 | /** | ||
65 | * Add a named property to the current context node. | ||
66 | *@param sName The name of the property to add. | ||
67 | *@param sValue The string value of the property. | ||
68 | */ | ||
69 | void addProperty( const char *sName, const char *sValue ); | ||
70 | |||
71 | /** | ||
72 | * Add a named property to the current context node, converting the | ||
73 | * numerical parameter to text using standrd printf style conversion. | ||
74 | *@param sName The name of the property to add. | ||
75 | *@param nValue The numerical value to add. | ||
76 | */ | ||
77 | void addProperty( const char *sName, const unsigned char nValue ); | ||
78 | |||
79 | /** | ||
80 | * Add a named property to the current context node, converting the | ||
81 | * numerical parameter to text using standrd printf style conversion. | ||
82 | *@param sName The name of the property to add. | ||
83 | *@param nValue The numerical value to add. | ||
84 | */ | ||
85 | void addProperty( const char *sName, const char nValue ); | ||
86 | |||
87 | /** | ||
88 | * Add a named property to the current context node, converting the | ||
89 | * numerical parameter to text using standrd printf style conversion. | ||
90 | *@param sName The name of the property to add. | ||
91 | *@param nValue The numerical value to add. | ||
92 | */ | ||
93 | void addProperty( const char *sName, const unsigned short nValue ); | ||
94 | |||
95 | /** | ||
96 | * Add a named property to the current context node, converting the | ||
97 | * numerical parameter to text using standrd printf style conversion. | ||
98 | *@param sName The name of the property to add. | ||
99 | *@param nValue The numerical value to add. | ||
100 | */ | ||
101 | void addProperty( const char *sName, const short nValue ); | ||
102 | |||
103 | /** | ||
104 | * Add a named property to the current context node, converting the | ||
105 | * numerical parameter to text using standrd printf style conversion. | ||
106 | *@param sName The name of the property to add. | ||
107 | *@param nValue The numerical value to add. | ||
108 | */ | ||
109 | void addProperty( const char *sName, const unsigned long nValue ); | ||
110 | |||
111 | /** | ||
112 | * Add a named property to the current context node, converting the | ||
113 | * numerical parameter to text using standrd printf style conversion. | ||
114 | *@param sName The name of the property to add. | ||
115 | *@param nValue The numerical value to add. | ||
116 | */ | ||
117 | void addProperty( const char *sName, const long nValue ); | ||
118 | |||
119 | /** | ||
120 | * Add a named property to the current context node, converting the | ||
121 | * numerical parameter to text using standrd printf style conversion. | ||
122 | *@param sName The name of the property to add. | ||
123 | *@param nValue The numerical value to add. | ||
124 | */ | ||
125 | void addProperty( const char *sName, const int nValue ); | ||
126 | |||
127 | /** | ||
128 | * Add a named property to the current context node, converting the | ||
129 | * numerical parameter to text using standrd printf style conversion. | ||
130 | *@param sName The name of the property to add. | ||
131 | *@param dValue The numerical value to add. | ||
132 | */ | ||
133 | void addProperty( const char *sName, const double dValue ); | ||
134 | |||
135 | /** | ||
136 | * The XmlDocuemnt is considered completed if the root node has been closed. | ||
137 | * Once an XmlDocument has been completed, you can no longer perform | ||
138 | * operations on it. | ||
139 | *@return True if completed, false if still in progress. | ||
140 | */ | ||
141 | bool isCompleted(); | ||
142 | |||
143 | /** | ||
144 | * Get a pointer to the root object of this XmlDocument. | ||
145 | *@returns A pointer to an internally owned XmlNode. Do not delete this | ||
146 | * XmlNode. | ||
147 | */ | ||
148 | XmlNode *getRoot(); | ||
149 | |||
150 | /** | ||
151 | * Get a pointer to the root object of this XmlDocument, and remove the | ||
152 | * ownership from this object. | ||
153 | *@returns A pointer to an internally owned XmlNode. Do not delete this | ||
154 | * XmlNode. | ||
155 | */ | ||
156 | XmlNode *detatchRoot(); | ||
157 | |||
158 | /** | ||
159 | * Get the current context node, which could be the same as the root node. | ||
160 | *@returns A pointer to an internally owned XmlNode. Do not delete this | ||
161 | * XmlNode. | ||
162 | */ | ||
163 | XmlNode *getCurrent(); | ||
164 | |||
165 | private: | ||
166 | XmlNode *pRoot; /**< The root node. */ | ||
167 | XmlNode *pCurrent; /**< The current node. */ | ||
168 | bool bCompleted; /**< Is it completed? */ | ||
169 | }; | ||
170 | |||
171 | #endif | ||
diff --git a/src/old/xmlfilereader.cpp b/src/old/xmlfilereader.cpp new file mode 100644 index 0000000..ed674a8 --- /dev/null +++ b/src/old/xmlfilereader.cpp | |||
@@ -0,0 +1,58 @@ | |||
1 | #include "xmlfilereader.h" | ||
2 | #include "exceptions.h" | ||
3 | #include <string.h> | ||
4 | |||
5 | XmlFileReader::XmlFileReader( const char *sFile, bool bStrip ) | ||
6 | : XmlReader( bStrip ) | ||
7 | { | ||
8 | fh = fopen( sFile, "rt" ); | ||
9 | |||
10 | if( fh == NULL ) | ||
11 | { | ||
12 | throw XmlException("Couldn't open file: %s", sFile ); | ||
13 | //nError = 1; | ||
14 | } | ||
15 | else | ||
16 | { | ||
17 | buildDoc(); | ||
18 | } | ||
19 | } | ||
20 | |||
21 | XmlFileReader::~XmlFileReader() | ||
22 | { | ||
23 | } | ||
24 | |||
25 | char XmlFileReader::getChar( int nIndex ) | ||
26 | { | ||
27 | // Make sure we always have a little data left in the buffer | ||
28 | if( fbDataIn.getLength() <= nIndex+1 && fh ) | ||
29 | { | ||
30 | int nBytes = fbDataIn.getCapacity()-1; | ||
31 | char *buf = new char[nBytes]; | ||
32 | int nRead = fread( buf, 1, nBytes, fh ); | ||
33 | fbDataIn.appendData( buf, nRead ); | ||
34 | delete[] buf; | ||
35 | |||
36 | if( nRead < nBytes ) | ||
37 | { | ||
38 | fclose( fh ); | ||
39 | fh = NULL; | ||
40 | } | ||
41 | } | ||
42 | if( fbDataIn.getLength() >= nIndex+1 ) | ||
43 | { | ||
44 | return fbDataIn.getData()[nIndex]; | ||
45 | } | ||
46 | else | ||
47 | { | ||
48 | throw XmlException("End of XML stream read."); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | void XmlFileReader::usedChar( int nAmnt ) | ||
53 | { | ||
54 | if( fbDataIn.getLength()-nAmnt >= 0 ) | ||
55 | { | ||
56 | fbDataIn.usedData( nAmnt ); | ||
57 | } | ||
58 | } | ||
diff --git a/src/old/xmlfilereader.h b/src/old/xmlfilereader.h new file mode 100644 index 0000000..e3e02c2 --- /dev/null +++ b/src/old/xmlfilereader.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef XMLFILEREADER | ||
2 | #define XMLFILEREADER | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include "xmlreader.h" | ||
6 | #include "flexbuf.h" | ||
7 | |||
8 | /** | ||
9 | * Takes care of reading in xml formatted data from a file. This could/should | ||
10 | * be made more arbitrary in the future so that we can read the data from any | ||
11 | * source. This is actually made quite simple already since all data read in | ||
12 | * is handled by one single helper function and then palced into a FlexBuf for | ||
13 | * easy access by the other functions. The FlexBuf also allows for block | ||
14 | * reading from disk, which improves speed by a noticable amount. | ||
15 | * <br> | ||
16 | * There are also some extra features implemented that allow you to break the | ||
17 | * standard XML reader specs and eliminate leading and trailing whitespace in | ||
18 | * all read content. This is useful in situations where you allow additional | ||
19 | * whitespace in the files to make them easily human readable. The resturned | ||
20 | * content will be NULL in sitautions where all content between nodes was | ||
21 | * stripped. | ||
22 | *@author Mike Buland | ||
23 | */ | ||
24 | class XmlFileReader : public XmlReader | ||
25 | { | ||
26 | public: | ||
27 | /** | ||
28 | * Construct an XmlReader around an xml file on your file system. | ||
29 | *@param sFile The file to read. | ||
30 | *@param bStrip Set to true to strip out leading and trailing whitespace in | ||
31 | * node contents. | ||
32 | */ | ||
33 | XmlFileReader( const char *sFile, bool bStrip=false ); | ||
34 | |||
35 | /** | ||
36 | * Destroy the reader and cleanup. | ||
37 | */ | ||
38 | virtual ~XmlFileReader(); | ||
39 | |||
40 | private: | ||
41 | char getChar( int nIndex = 0 ); | ||
42 | void usedChar( int nAmnt = 1 ); | ||
43 | FILE *fh; /**< The file handle. */ | ||
44 | FlexBuf fbDataIn; /**< The input buffer. */ | ||
45 | }; | ||
46 | |||
47 | #endif | ||
diff --git a/src/old/xmlfilewriter.cpp b/src/old/xmlfilewriter.cpp new file mode 100644 index 0000000..3c6fb41 --- /dev/null +++ b/src/old/xmlfilewriter.cpp | |||
@@ -0,0 +1,28 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "xmlfilewriter.h" | ||
4 | |||
5 | XmlFileWriter::XmlFileWriter( const char *sFileName, const char *sIndent, XmlNode *pRoot ) : | ||
6 | XmlWriter( sIndent, pRoot ) | ||
7 | { | ||
8 | this->sFileName = sFileName; | ||
9 | fh = fopen( sFileName, "wt"); | ||
10 | fprintf( fh, "<?xml version=\"1.0\"?>\n"); | ||
11 | } | ||
12 | |||
13 | XmlFileWriter::XmlFileWriter( FILE *fh, const char *sIndent, XmlNode *pRoot ) : | ||
14 | XmlWriter( sIndent, pRoot ), | ||
15 | fh( fh ) | ||
16 | { | ||
17 | } | ||
18 | |||
19 | XmlFileWriter::~XmlFileWriter() | ||
20 | { | ||
21 | fclose( fh ); | ||
22 | } | ||
23 | |||
24 | void XmlFileWriter::writeString( const char *sString ) | ||
25 | { | ||
26 | fputs( sString, fh ); | ||
27 | } | ||
28 | |||
diff --git a/src/old/xmlfilewriter.h b/src/old/xmlfilewriter.h new file mode 100644 index 0000000..e328f96 --- /dev/null +++ b/src/old/xmlfilewriter.h | |||
@@ -0,0 +1,45 @@ | |||
1 | #ifndef XML_FILE_WRITER | ||
2 | #define XML_FILE_WRITER | ||
3 | |||
4 | #include "xmlnode.h" | ||
5 | #include "xmlwriter.h" | ||
6 | |||
7 | /** | ||
8 | * Implements xml writing in the XML standard format. Also allows you to | ||
9 | * break that format and auto-indent your exported xml data for ease of | ||
10 | * reading. The auto-indenting will only be applied to sections that | ||
11 | * have no content of their own already. This means that except for | ||
12 | * whitespace all of your data will be preserved perfectly. | ||
13 | * You can create an XmlWriter object around a file, or access the static | ||
14 | * write function directly and just hand it a filename and a root XmlNode. | ||
15 | * When using an XmlWriter object the interface is identicle to that of | ||
16 | * the XmlDocument class, so reference that class for API info. However | ||
17 | * when the initial (or root) node is closed, and the document is finished | ||
18 | * the file will be created and written to automatically. The user can | ||
19 | * check to see if this is actually true by calling the isFinished | ||
20 | * function in the XmlDocument class. | ||
21 | *@author Mike Buland | ||
22 | */ | ||
23 | class XmlFileWriter : public XmlWriter | ||
24 | { | ||
25 | public: | ||
26 | /** | ||
27 | * Construct a file writer around a given file. | ||
28 | *@param sFileName The file to create or overwrite and write XML into. | ||
29 | *@param sIndent The indent text to use, if any. | ||
30 | */ | ||
31 | XmlFileWriter( const char *sFileName, const char *sIndent=NULL, XmlNode *pRoot=NULL ); | ||
32 | XmlFileWriter( FILE *fh, const char *sIndent=NULL, XmlNode *pRoot=NULL ); | ||
33 | |||
34 | /** | ||
35 | * Destroy the writer. | ||
36 | */ | ||
37 | virtual ~XmlFileWriter(); | ||
38 | |||
39 | private: | ||
40 | void writeString( const char *sString ); | ||
41 | std::string sFileName; /**< The filename to write to. */ | ||
42 | FILE *fh; /**< The file handle to the open file. */ | ||
43 | }; | ||
44 | |||
45 | #endif | ||
diff --git a/src/old/xmlnode.cpp b/src/old/xmlnode.cpp new file mode 100644 index 0000000..b1ed9a9 --- /dev/null +++ b/src/old/xmlnode.cpp | |||
@@ -0,0 +1,445 @@ | |||
1 | #include "xmlnode.h" | ||
2 | #include "hashfunctionstring.h" | ||
3 | |||
4 | XmlNode::XmlNode( const char *sName, XmlNode *pParent, const char *sContent ) : | ||
5 | hProperties( new HashFunctionString(), 53, false ), | ||
6 | hChildren( new HashFunctionString(), 53, true ) | ||
7 | { | ||
8 | this->pParent = pParent; | ||
9 | if( sName != NULL ) | ||
10 | { | ||
11 | setName( sName ); | ||
12 | } | ||
13 | if( sContent != NULL ) | ||
14 | { | ||
15 | this->sPreContent = new std::string( sContent ); | ||
16 | } | ||
17 | else | ||
18 | { | ||
19 | this->sPreContent = NULL; | ||
20 | } | ||
21 | nCurContent = 0; | ||
22 | } | ||
23 | |||
24 | XmlNode::~XmlNode() | ||
25 | { | ||
26 | for( int j = 0; j < lChildren.getSize(); j++ ) | ||
27 | { | ||
28 | delete (XmlNode *)lChildren[j]; | ||
29 | } | ||
30 | for( int j = 0; j < lPropNames.getSize(); j++ ) | ||
31 | { | ||
32 | delete (std::string *)lPropNames[j]; | ||
33 | } | ||
34 | for( int j = 0; j < lPropValues.getSize(); j++ ) | ||
35 | { | ||
36 | delete (std::string *)lPropValues[j]; | ||
37 | } | ||
38 | for( int j = 0; j < lPostContent.getSize(); j++ ) | ||
39 | { | ||
40 | if( lPostContent[j] != NULL ) | ||
41 | { | ||
42 | delete (std::string *)lPostContent[j]; | ||
43 | } | ||
44 | } | ||
45 | if( sPreContent ) | ||
46 | { | ||
47 | delete sPreContent; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | void XmlNode::setName( const char *sName ) | ||
52 | { | ||
53 | if( pParent ) | ||
54 | { | ||
55 | if( this->sName.size() == 0 ) | ||
56 | { | ||
57 | // We're not in the hash yet, so add us | ||
58 | this->sName = sName; | ||
59 | pParent->hChildren.insert( this->sName.c_str(), this ); | ||
60 | } | ||
61 | else | ||
62 | { | ||
63 | // Slightly more tricky, delete us, then add us... | ||
64 | pParent->hChildren.del( this->sName.c_str() ); | ||
65 | this->sName = sName; | ||
66 | pParent->hChildren.insert( this->sName.c_str(), this ); | ||
67 | } | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | // If we have no parent, then just set the name string, we don't need | ||
72 | // to worry about hashing. | ||
73 | this->sName = sName; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | void XmlNode::setContent( const char *sContent, int nIndex ) | ||
78 | { | ||
79 | if( nIndex == -1 ) | ||
80 | { | ||
81 | nIndex = nCurContent; | ||
82 | } | ||
83 | if( nIndex == 0 ) | ||
84 | { | ||
85 | if( this->sPreContent ) | ||
86 | { | ||
87 | delete this->sPreContent; | ||
88 | } | ||
89 | |||
90 | this->sPreContent = new std::string( sContent ); | ||
91 | } | ||
92 | else | ||
93 | { | ||
94 | nIndex--; | ||
95 | if( lPostContent[nIndex] ) | ||
96 | { | ||
97 | delete (std::string *)lPostContent[nIndex]; | ||
98 | } | ||
99 | |||
100 | lPostContent.setAt( nIndex, new std::string( sContent ) ); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | const char *XmlNode::getContent( int nIndex ) | ||
105 | { | ||
106 | if( nIndex == 0 ) | ||
107 | { | ||
108 | if( sPreContent ) | ||
109 | { | ||
110 | return sPreContent->c_str(); | ||
111 | } | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | nIndex--; | ||
116 | if( lPostContent[nIndex] ) | ||
117 | { | ||
118 | return ((std::string *)lPostContent[nIndex])->c_str(); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | return NULL; | ||
123 | } | ||
124 | |||
125 | XmlNode *XmlNode::addChild( const char *sName, const char *sContent ) | ||
126 | { | ||
127 | return addChild( new XmlNode( sName, this, sContent ) ); | ||
128 | } | ||
129 | |||
130 | XmlNode *XmlNode::addChild( XmlNode *pNode ) | ||
131 | { | ||
132 | lChildren.append( pNode ); | ||
133 | lPostContent.append( NULL ); | ||
134 | nCurContent++; | ||
135 | pNode->pParent = this; | ||
136 | |||
137 | return pNode; | ||
138 | } | ||
139 | |||
140 | XmlNode *XmlNode::getParent() | ||
141 | { | ||
142 | return pParent; | ||
143 | } | ||
144 | |||
145 | void XmlNode::addProperty( const char *sName, const char *sValue ) | ||
146 | { | ||
147 | std::string *pName = new std::string( sName ); | ||
148 | std::string *pValue = new std::string( sValue ); | ||
149 | |||
150 | hProperties.insert( pName->c_str(), pValue->c_str() ); | ||
151 | lPropNames.append( pName ); | ||
152 | lPropValues.append( pValue ); | ||
153 | } | ||
154 | |||
155 | int XmlNode::getNumProperties() | ||
156 | { | ||
157 | return lPropNames.getSize(); | ||
158 | } | ||
159 | |||
160 | const char *XmlNode::getPropertyName( int nIndex ) | ||
161 | { | ||
162 | std::string *tmp = ((std::string *)lPropNames[nIndex]); | ||
163 | if( tmp == NULL ) | ||
164 | return NULL; | ||
165 | return tmp->c_str(); | ||
166 | } | ||
167 | |||
168 | const char *XmlNode::getProperty( int nIndex ) | ||
169 | { | ||
170 | std::string *tmp = ((std::string *)lPropValues[nIndex]); | ||
171 | if( tmp == NULL ) | ||
172 | return NULL; | ||
173 | return tmp->c_str(); | ||
174 | } | ||
175 | |||
176 | const char *XmlNode::getProperty( const char *sName ) | ||
177 | { | ||
178 | const char *tmp = (const char *)hProperties[sName]; | ||
179 | if( tmp == NULL ) | ||
180 | return NULL; | ||
181 | return tmp; | ||
182 | } | ||
183 | |||
184 | void XmlNode::deleteProperty( int nIndex ) | ||
185 | { | ||
186 | hProperties.del( ((std::string *)lPropNames[nIndex])->c_str() ); | ||
187 | |||
188 | delete (std::string *)lPropNames[nIndex]; | ||
189 | delete (std::string *)lPropValues[nIndex]; | ||
190 | |||
191 | lPropNames.deleteAt( nIndex ); | ||
192 | lPropValues.deleteAt( nIndex ); | ||
193 | } | ||
194 | |||
195 | bool XmlNode::hasChildren() | ||
196 | { | ||
197 | return lChildren.getSize()>0; | ||
198 | } | ||
199 | |||
200 | int XmlNode::getNumChildren() | ||
201 | { | ||
202 | return lChildren.getSize(); | ||
203 | } | ||
204 | |||
205 | XmlNode *XmlNode::getChild( int nIndex ) | ||
206 | { | ||
207 | return (XmlNode *)lChildren[nIndex]; | ||
208 | } | ||
209 | |||
210 | XmlNode *XmlNode::getChild( const char *sName, int nSkip ) | ||
211 | { | ||
212 | return (XmlNode *)hChildren.get( sName, nSkip ); | ||
213 | } | ||
214 | |||
215 | const char *XmlNode::getName() | ||
216 | { | ||
217 | return sName.c_str(); | ||
218 | } | ||
219 | |||
220 | void XmlNode::deleteNode( int nIndex, const char *sReplacementText ) | ||
221 | { | ||
222 | XmlNode *xRet = detatchNode( nIndex, sReplacementText ); | ||
223 | |||
224 | if( xRet != NULL ) | ||
225 | { | ||
226 | delete xRet; | ||
227 | } | ||
228 | } | ||
229 | |||
230 | XmlNode *XmlNode::detatchNode( int nIndex, const char *sReplacementText ) | ||
231 | { | ||
232 | if( nIndex < 0 || nIndex >= lChildren.getSize() ) | ||
233 | return NULL; | ||
234 | |||
235 | // The real trick when deleteing a node isn't actually deleting it, it's | ||
236 | // reforming the content around the node that's now missing...hmmm... | ||
237 | |||
238 | if( nIndex == 0 ) | ||
239 | { | ||
240 | // If the index is zero we have to deal with the pre-content | ||
241 | if( sReplacementText ) | ||
242 | { | ||
243 | if( sPreContent == NULL ) | ||
244 | { | ||
245 | sPreContent = new std::string( sReplacementText ); | ||
246 | } | ||
247 | else | ||
248 | { | ||
249 | *sPreContent += sReplacementText; | ||
250 | } | ||
251 | } | ||
252 | if( lPostContent.getSize() > 0 ) | ||
253 | { | ||
254 | if( lPostContent[0] != NULL ) | ||
255 | { | ||
256 | if( sPreContent == NULL ) | ||
257 | { | ||
258 | sPreContent = new std::string( | ||
259 | ((std::string *)lPostContent[0])->c_str() | ||
260 | ); | ||
261 | } | ||
262 | else | ||
263 | { | ||
264 | *sPreContent += | ||
265 | ((std::string *)lPostContent[0])->c_str(); | ||
266 | } | ||
267 | } | ||
268 | delete (std::string *)lPostContent[0]; | ||
269 | lPostContent.deleteAt( 0 ); | ||
270 | } | ||
271 | } | ||
272 | else | ||
273 | { | ||
274 | int nCont = nIndex-1; | ||
275 | // If it's above zero we deal with the post-content only | ||
276 | if( sReplacementText ) | ||
277 | { | ||
278 | if( lPostContent[nCont] == NULL ) | ||
279 | { | ||
280 | lPostContent.setAt( nCont, new std::string( sReplacementText ) ); | ||
281 | } | ||
282 | else | ||
283 | { | ||
284 | *((std::string *)lPostContent[nCont]) += sReplacementText; | ||
285 | } | ||
286 | } | ||
287 | if( lPostContent.getSize() > nIndex ) | ||
288 | { | ||
289 | if( lPostContent[nIndex] != NULL ) | ||
290 | { | ||
291 | if( lPostContent[nCont] == NULL ) | ||
292 | { | ||
293 | lPostContent.setAt( nCont, new std::string( | ||
294 | ((std::string *)lPostContent[nIndex])->c_str() | ||
295 | ) ); | ||
296 | } | ||
297 | else | ||
298 | { | ||
299 | *((std::string *)lPostContent[nCont]) += | ||
300 | ((std::string *)lPostContent[nIndex])->c_str(); | ||
301 | } | ||
302 | } | ||
303 | delete (std::string *)lPostContent[nIndex]; | ||
304 | lPostContent.deleteAt( nIndex ); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | XmlNode *xRet = (XmlNode *)lChildren[nIndex]; | ||
309 | hChildren.del( ((XmlNode *)lChildren[nIndex])->getName() ); | ||
310 | lChildren.deleteAt( nIndex ); | ||
311 | |||
312 | return xRet; | ||
313 | } | ||
314 | |||
315 | void XmlNode::replaceNode( int nIndex, XmlNode *pNewNode ) | ||
316 | { | ||
317 | if( nIndex < 0 || nIndex >= lChildren.getSize() ) | ||
318 | return; //TODO: throw an exception | ||
319 | |||
320 | delete (XmlNode *)lChildren[nIndex]; | ||
321 | lChildren.setAt( nIndex, pNewNode ); | ||
322 | pNewNode->pParent = this; | ||
323 | } | ||
324 | |||
325 | XmlNode *XmlNode::getCopy() | ||
326 | { | ||
327 | XmlNode *pNew = new XmlNode(); | ||
328 | |||
329 | pNew->sName = sName; | ||
330 | if( sPreContent ) | ||
331 | { | ||
332 | pNew->sPreContent = new std::string( sPreContent->c_str() ); | ||
333 | } | ||
334 | else | ||
335 | { | ||
336 | pNew->sPreContent = NULL; | ||
337 | } | ||
338 | pNew->nCurContent = 0; | ||
339 | |||
340 | int nSize = lPostContent.getSize(); | ||
341 | pNew->lPostContent.setSize( nSize ); | ||
342 | for( int j = 0; j < nSize; j++ ) | ||
343 | { | ||
344 | if( lPostContent[j] ) | ||
345 | { | ||
346 | pNew->lPostContent.setAt( | ||
347 | j, new std::string( | ||
348 | ((std::string *)lPostContent[j])->c_str() | ||
349 | ) | ||
350 | ); | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | pNew->lPostContent.setAt( j, NULL ); | ||
355 | } | ||
356 | } | ||
357 | |||
358 | nSize = lChildren.getSize(); | ||
359 | pNew->lChildren.setSize( nSize ); | ||
360 | for( int j = 0; j < nSize; j++ ) | ||
361 | { | ||
362 | XmlNode *pChild = ((XmlNode *)lChildren[j])->getCopy(); | ||
363 | pNew->lChildren.setAt( j, pChild ); | ||
364 | pChild->pParent = pNew; | ||
365 | pNew->hChildren.insert( pChild->getName(), pChild ); | ||
366 | } | ||
367 | |||
368 | nSize = lPropNames.getSize(); | ||
369 | pNew->lPropNames.setSize( nSize ); | ||
370 | pNew->lPropValues.setSize( nSize ); | ||
371 | for( int j = 0; j < nSize; j++ ) | ||
372 | { | ||
373 | std::string *pProp = new std::string( ((std::string *)lPropNames[j])->c_str() ); | ||
374 | std::string *pVal = new std::string( ((std::string *)lPropValues[j])->c_str() ); | ||
375 | pNew->lPropNames.setAt( j, pProp ); | ||
376 | pNew->lPropValues.setAt( j, pVal ); | ||
377 | pNew->hProperties.insert( pProp->c_str(), pVal->c_str() ); | ||
378 | pNew->nCurContent++; | ||
379 | } | ||
380 | |||
381 | return pNew; | ||
382 | } | ||
383 | |||
384 | void XmlNode::deleteNodeKeepChildren( int nIndex ) | ||
385 | { | ||
386 | // This is a tricky one...we need to do some patching to keep things all | ||
387 | // even... | ||
388 | XmlNode *xRet = (XmlNode *)lChildren[nIndex]; | ||
389 | |||
390 | if( xRet == NULL ) | ||
391 | { | ||
392 | return; | ||
393 | } | ||
394 | else | ||
395 | { | ||
396 | if( getContent( nIndex ) ) | ||
397 | { | ||
398 | std::string sBuf( getContent( nIndex ) ); | ||
399 | sBuf += xRet->getContent( 0 ); | ||
400 | setContent( sBuf.c_str(), nIndex ); | ||
401 | } | ||
402 | else | ||
403 | { | ||
404 | setContent( xRet->getContent( 0 ), nIndex ); | ||
405 | } | ||
406 | |||
407 | int nSize = xRet->lChildren.getSize(); | ||
408 | for( int j = 0; j < nSize; j++ ) | ||
409 | { | ||
410 | XmlNode *pCopy = ((XmlNode *)xRet->lChildren[j])->getCopy(); | ||
411 | pCopy->pParent = this; | ||
412 | lChildren.insertBefore( pCopy, nIndex+j ); | ||
413 | |||
414 | if( xRet->lPostContent[j] ) | ||
415 | { | ||
416 | lPostContent.insertBefore( | ||
417 | new std::string( ((std::string *)xRet->lPostContent[j])->c_str() ), | ||
418 | nIndex+j | ||
419 | ); | ||
420 | } | ||
421 | else | ||
422 | { | ||
423 | lPostContent.insertBefore( NULL, nIndex+j ); | ||
424 | } | ||
425 | } | ||
426 | |||
427 | if( getContent( nIndex+nSize ) ) | ||
428 | { | ||
429 | //SString sBuf( getContent( nIndex+nSize ) ); | ||
430 | //sBuf.catfrom( xRet->getContent( nSize ) ); | ||
431 | //setContent( sBuf, nIndex+nSize ); | ||
432 | } | ||
433 | else | ||
434 | { | ||
435 | setContent( xRet->getContent( nSize ), nIndex+nSize ); | ||
436 | } | ||
437 | |||
438 | deleteNode( nIndex+nSize ); | ||
439 | } | ||
440 | } | ||
441 | |||
442 | void XmlNode::replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ) | ||
443 | { | ||
444 | } | ||
445 | |||
diff --git a/src/old/xmlnode.h b/src/old/xmlnode.h new file mode 100644 index 0000000..7525306 --- /dev/null +++ b/src/old/xmlnode.h | |||
@@ -0,0 +1,236 @@ | |||
1 | #ifndef XMLNODE | ||
2 | #define XMLNODE | ||
3 | |||
4 | #include <iostream> | ||
5 | #include "linkedlist.h" | ||
6 | #include "hashtable.h" | ||
7 | |||
8 | /** | ||
9 | * Maintains all data pertient to an XML node, including sub-nodes and content. | ||
10 | * All child nodes can be accessed through index and through name via a hash | ||
11 | * table. This makes it very easy to gain simple and fast access to all of | ||
12 | * your data. For most applications, the memory footprint is also rather | ||
13 | * small. While XmlNode objects can be used directly to create XML structures | ||
14 | * it is highly reccomended that all operations be performed through the | ||
15 | * XmlDocument class. | ||
16 | *@author Mike Buland | ||
17 | */ | ||
18 | class XmlNode | ||
19 | { | ||
20 | public: | ||
21 | /** | ||
22 | * Construct a new XmlNode. | ||
23 | *@param sName The name of the node. | ||
24 | *@param pParent The parent node. | ||
25 | *@param sContent The initial content string. | ||
26 | */ | ||
27 | XmlNode( | ||
28 | const char *sName=NULL, | ||
29 | XmlNode *pParent = NULL, | ||
30 | const char *sContent=NULL | ||
31 | ); | ||
32 | |||
33 | /** | ||
34 | * Delete the node and cleanup all memory. | ||
35 | */ | ||
36 | virtual ~XmlNode(); | ||
37 | |||
38 | /** | ||
39 | * Change the name of the node. | ||
40 | *@param sName The new name of the node. | ||
41 | */ | ||
42 | void setName( const char *sName ); | ||
43 | |||
44 | /** | ||
45 | * Construct a new node and add it as a child to this node, also return a | ||
46 | * pointer to the newly constructed node. | ||
47 | *@param sName The name of the new node. | ||
48 | *@param sContent The initial content of the new node. | ||
49 | *@returns A pointer to the newly created child node. | ||
50 | */ | ||
51 | XmlNode *addChild( const char *sName, const char *sContent=NULL ); | ||
52 | |||
53 | /** | ||
54 | * Add an already created XmlNode as a child to this node. The new child | ||
55 | * XmlNode's parent will be changed appropriately and the parent XmlNode | ||
56 | * will take ownership of the child. | ||
57 | *@param pChild The child XmlNode to add to this XmlNode. | ||
58 | *@returns A pointer to the child node that was just added. | ||
59 | */ | ||
60 | XmlNode *addChild( XmlNode *pChild ); | ||
61 | |||
62 | /** | ||
63 | * Add a new property to the XmlNode. Properties are name/value pairs. | ||
64 | *@param sName The name of the property. Specifying a name that's already | ||
65 | * in use will overwrite that property. | ||
66 | *@param sValue The textual value of the property. | ||
67 | */ | ||
68 | void addProperty( const char *sName, const char *sValue ); | ||
69 | |||
70 | /** | ||
71 | * Get a pointer to the parent node, if any. | ||
72 | *@returns A pointer to the node's parent, or NULL if there isn't one. | ||
73 | */ | ||
74 | XmlNode *getParent(); | ||
75 | |||
76 | /** | ||
77 | * Tells you if this node has children. | ||
78 | *@returns True if this node has at least one child, false otherwise. | ||
79 | */ | ||
80 | bool hasChildren(); | ||
81 | |||
82 | /** | ||
83 | * Tells you how many children this node has. | ||
84 | *@returns The number of children this node has. | ||
85 | */ | ||
86 | int getNumChildren(); | ||
87 | |||
88 | /** | ||
89 | * Get a child node at a specific index. | ||
90 | *@param nIndex The zero-based index of the child to retreive. | ||
91 | *@returns A pointer to the child, or NULL if you requested an invalid | ||
92 | * index. | ||
93 | */ | ||
94 | XmlNode *getChild( int nIndex ); | ||
95 | |||
96 | /** | ||
97 | * Get a child with the specified name, and possibly skip value. For an | ||
98 | * explination of skip values see the HashTable. | ||
99 | *@param sName The name of the child to find. | ||
100 | *@param nSkip The number of nodes with that name to skip. | ||
101 | *@returns A pointer to the child, or NULL if no child with that name was | ||
102 | * found. | ||
103 | */ | ||
104 | XmlNode *getChild( const char *sName, int nSkip=0 ); | ||
105 | |||
106 | /** | ||
107 | * Get a pointer to the name of this node. Do not change this, use setName | ||
108 | * instead. | ||
109 | *@returns A pointer to the name of this node. | ||
110 | */ | ||
111 | const char *getName(); | ||
112 | |||
113 | /** | ||
114 | * Set the content of this node, optionally at a specific index. Using the | ||
115 | * default of -1 will set the content after the last added node. | ||
116 | *@param sContent The content string to use. | ||
117 | *@param nIndex The index of the content. | ||
118 | */ | ||
119 | void setContent( const char *sContent, int nIndex=-1 ); | ||
120 | |||
121 | /** | ||
122 | * Get the content string at a given index, or zero for initial content. | ||
123 | *@param nIndex The index of the content. | ||
124 | *@returns A pointer to the content at that location. | ||
125 | */ | ||
126 | const char *getContent( int nIndex = 0 ); | ||
127 | |||
128 | /** | ||
129 | * Get the number of properties in this node. | ||
130 | *@returns The number of properties in this node. | ||
131 | */ | ||
132 | int getNumProperties(); | ||
133 | |||
134 | /** | ||
135 | * Get a property's name by index. | ||
136 | *@param nIndex The index of the property to examine. | ||
137 | *@returns A pointer to the name of the property specified, or NULL if none | ||
138 | * found. | ||
139 | */ | ||
140 | const char *getPropertyName( int nIndex ); | ||
141 | |||
142 | /** | ||
143 | * Get a proprty's value by index. | ||
144 | *@param nIndex The index of the property to examine. | ||
145 | *@returns A pointer to the value of the property specified, or NULL if none | ||
146 | * found. | ||
147 | */ | ||
148 | const char *getProperty( int nIndex ); | ||
149 | |||
150 | /** | ||
151 | * Get a propery's value by name. | ||
152 | *@param sName The name of the property to examine. | ||
153 | *@returns A pointer to the value of the property specified, or NULL if none | ||
154 | * found. | ||
155 | */ | ||
156 | const char *getProperty( const char *sName ); | ||
157 | |||
158 | /** | ||
159 | * Delete a property by index. | ||
160 | *@param nIndex The index of the property to delete. | ||
161 | *@returns True if the property was found and deleted, false if it wasn't | ||
162 | * found. | ||
163 | */ | ||
164 | void deleteProperty( int nIndex ); | ||
165 | |||
166 | /** | ||
167 | * Delete a child node, possibly replacing it with some text. This actually | ||
168 | * fixes all content strings around the newly deleted child node. | ||
169 | *@param nIndex The index of the node to delete. | ||
170 | *@param sReplacementText The optional text to replace the node with. | ||
171 | *@returns True of the node was found, and deleted, false if it wasn't | ||
172 | * found. | ||
173 | */ | ||
174 | void deleteNode( int nIndex, const char *sReplacementText = NULL ); | ||
175 | |||
176 | /** | ||
177 | * Delete a given node, but move all of it's children and content up to | ||
178 | * replace the deleted node. All of the content of the child node is | ||
179 | * spliced seamlessly into place with the parent node's content. | ||
180 | *@param nIndex The node to delete. | ||
181 | *@returns True if the node was found and deleted, false if it wasn't. | ||
182 | */ | ||
183 | void deleteNodeKeepChildren( int nIndex ); | ||
184 | |||
185 | /** | ||
186 | * Detatch a given child node from this node. This effectively works just | ||
187 | * like a deleteNode, except that instead of deleting the node it is removed | ||
188 | * and returned, and all ownership is given up. | ||
189 | *@param nIndex The index of the node to detatch. | ||
190 | *@param sReplacementText The optional text to replace the detatched node | ||
191 | * with. | ||
192 | *@returns A pointer to the newly detatched node, which then passes | ||
193 | * ownership to the caller. | ||
194 | */ | ||
195 | XmlNode *detatchNode( int nIndex, const char *sReplacementText = NULL ); | ||
196 | |||
197 | /** | ||
198 | * Replace a given node with a different node that is not currently owned by | ||
199 | * this XmlNode or any ancestor. | ||
200 | *@param nIndex The index of the node to replace. | ||
201 | *@param pNewNode The new node to replace the old node with. | ||
202 | *@returns True if the node was found and replaced, false if it wasn't. | ||
203 | */ | ||
204 | void replaceNode( int nIndex, XmlNode *pNewNode ); | ||
205 | |||
206 | /** | ||
207 | * Replace a given node with the children and content of a given node. | ||
208 | *@param nIndex The index of the node to replace. | ||
209 | *@param pNewNode The node that contains the children and content that will | ||
210 | * replace the node specified by nIndex. | ||
211 | *@returns True if the node was found and replaced, false if it wasn't. | ||
212 | */ | ||
213 | void replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ); | ||
214 | |||
215 | /** | ||
216 | * Get a copy of this node and all children. getCopy is recursive, so | ||
217 | * beware copying large trees of xml. | ||
218 | *@returns A newly created copy of this node and all of it's children. | ||
219 | */ | ||
220 | XmlNode *getCopy(); | ||
221 | |||
222 | private: | ||
223 | std::string sName; /**< The name of the node. */ | ||
224 | std::string *sPreContent; /**< The content that goes before any node. */ | ||
225 | LinkedList lChildren; /**< The children. */ | ||
226 | LinkedList lPostContent; /**< The content that comes after children. */ | ||
227 | HashTable hProperties; /**< Property hashtable. */ | ||
228 | HashTable hChildren; /**< Children hashtable. */ | ||
229 | LinkedList lPropNames; /**< List of property names. */ | ||
230 | LinkedList lPropValues; /**< List of property values. */ | ||
231 | XmlNode *pParent; /**< A pointer to the parent of this node. */ | ||
232 | int nCurContent; /**< The current content we're on, for using the -1 on | ||
233 | setContent. */ | ||
234 | }; | ||
235 | |||
236 | #endif | ||
diff --git a/src/old/xmlreader.cpp b/src/old/xmlreader.cpp new file mode 100644 index 0000000..18df69c --- /dev/null +++ b/src/old/xmlreader.cpp | |||
@@ -0,0 +1,602 @@ | |||
1 | #include "xmlreader.h" | ||
2 | #include "exceptions.h" | ||
3 | #include <string.h> | ||
4 | #include "hashfunctionstring.h" | ||
5 | |||
6 | XmlReader::XmlReader( bool bStrip ) : | ||
7 | bStrip( bStrip ), | ||
8 | htEntity( new HashFunctionString(), 11 ) | ||
9 | { | ||
10 | } | ||
11 | |||
12 | XmlReader::~XmlReader() | ||
13 | { | ||
14 | void *i = htEntity.getFirstItemPos(); | ||
15 | while( (i = htEntity.getNextItemPos( i ) ) ) | ||
16 | { | ||
17 | free( (char *)(htEntity.getItemID( i )) ); | ||
18 | delete (StaticString *)htEntity.getItemData( i ); | ||
19 | } | ||
20 | } | ||
21 | |||
22 | void XmlReader::addEntity( const char *name, const char *value ) | ||
23 | { | ||
24 | if( htEntity[name] ) return; | ||
25 | |||
26 | char *sName = strdup( name ); | ||
27 | StaticString *sValue = new StaticString( value ); | ||
28 | |||
29 | htEntity.insert( sName, sValue ); | ||
30 | } | ||
31 | |||
32 | #define gcall( x ) if( x == false ) return false; | ||
33 | |||
34 | bool XmlReader::isws( char chr ) | ||
35 | { | ||
36 | return ( chr == ' ' || chr == '\t' || chr == '\n' || chr == '\r' ); | ||
37 | } | ||
38 | |||
39 | bool XmlReader::ws() | ||
40 | { | ||
41 | while( true ) | ||
42 | { | ||
43 | char chr = getChar(); | ||
44 | if( isws( chr ) ) | ||
45 | { | ||
46 | usedChar(); | ||
47 | } | ||
48 | else | ||
49 | { | ||
50 | return true; | ||
51 | } | ||
52 | } | ||
53 | return true; | ||
54 | } | ||
55 | |||
56 | bool XmlReader::buildDoc() | ||
57 | { | ||
58 | // take care of initial whitespace | ||
59 | gcall( ws() ); | ||
60 | textDecl(); | ||
61 | entity(); | ||
62 | addEntity("gt", ">"); | ||
63 | addEntity("lt", "<"); | ||
64 | addEntity("amp", "&"); | ||
65 | addEntity("apos", "\'"); | ||
66 | addEntity("quot", "\""); | ||
67 | gcall( node() ); | ||
68 | |||
69 | return true; | ||
70 | } | ||
71 | |||
72 | void XmlReader::textDecl() | ||
73 | { | ||
74 | if( getChar() == '<' && getChar( 1 ) == '?' ) | ||
75 | { | ||
76 | usedChar( 2 ); | ||
77 | for(;;) | ||
78 | { | ||
79 | if( getChar() == '?' ) | ||
80 | { | ||
81 | if( getChar( 1 ) == '>' ) | ||
82 | { | ||
83 | usedChar( 2 ); | ||
84 | return; | ||
85 | } | ||
86 | } | ||
87 | usedChar(); | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | |||
92 | void XmlReader::entity() | ||
93 | { | ||
94 | for(;;) | ||
95 | { | ||
96 | ws(); | ||
97 | |||
98 | if( getChar() == '<' && getChar( 1 ) == '!' ) | ||
99 | { | ||
100 | usedChar( 2 ); | ||
101 | ws(); | ||
102 | std::string buf; | ||
103 | for(;;) | ||
104 | { | ||
105 | char chr = getChar(); | ||
106 | usedChar(); | ||
107 | if( isws( chr ) ) break; | ||
108 | buf += chr; | ||
109 | } | ||
110 | |||
111 | if( strcmp( buf.c_str(), "ENTITY") == 0 ) | ||
112 | { | ||
113 | ws(); | ||
114 | std::string name; | ||
115 | for(;;) | ||
116 | { | ||
117 | char chr = getChar(); | ||
118 | usedChar(); | ||
119 | if( isws( chr ) ) break; | ||
120 | name += chr; | ||
121 | } | ||
122 | ws(); | ||
123 | char quot = getChar(); | ||
124 | usedChar(); | ||
125 | if( quot != '\'' && quot != '\"' ) | ||
126 | { | ||
127 | throw XmlException( | ||
128 | "Only quoted entity values are supported." | ||
129 | ); | ||
130 | } | ||
131 | std::string value; | ||
132 | for(;;) | ||
133 | { | ||
134 | char chr = getChar(); | ||
135 | usedChar(); | ||
136 | if( chr == '&' ) | ||
137 | { | ||
138 | StaticString *tmp = getEscape(); | ||
139 | if( tmp == NULL ) throw XmlException("Entity thing"); | ||
140 | value += tmp->getString(); | ||
141 | delete tmp; | ||
142 | } | ||
143 | else if( chr == quot ) | ||
144 | { | ||
145 | break; | ||
146 | } | ||
147 | else | ||
148 | { | ||
149 | value += chr; | ||
150 | } | ||
151 | } | ||
152 | ws(); | ||
153 | if( getChar() == '>' ) | ||
154 | { | ||
155 | usedChar(); | ||
156 | |||
157 | addEntity( name.c_str(), value.c_str() ); | ||
158 | } | ||
159 | else | ||
160 | { | ||
161 | throw XmlException( | ||
162 | "Malformed ENTITY: unexpected '%c' found.", | ||
163 | getChar() | ||
164 | ); | ||
165 | } | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | throw XmlException( | ||
170 | "Unsupported header symbol: %s", | ||
171 | buf.c_str() | ||
172 | ); | ||
173 | } | ||
174 | } | ||
175 | else | ||
176 | { | ||
177 | return; | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | bool XmlReader::node() | ||
183 | { | ||
184 | gcall( startNode() ) | ||
185 | |||
186 | // At this point, we are closing the startNode | ||
187 | char chr = getChar(); | ||
188 | if( chr == '>' ) | ||
189 | { | ||
190 | usedChar(); | ||
191 | |||
192 | // Now we process the guts of the node. | ||
193 | gcall( content() ); | ||
194 | } | ||
195 | else if( chr == '/' ) | ||
196 | { | ||
197 | // This is the tricky one, one more validation, then we close the node. | ||
198 | usedChar(); | ||
199 | if( getChar() == '>' ) | ||
200 | { | ||
201 | closeNode(); | ||
202 | usedChar(); | ||
203 | } | ||
204 | else | ||
205 | { | ||
206 | throw XmlException("Close node in singleNode malformed!"); | ||
207 | } | ||
208 | } | ||
209 | else | ||
210 | { | ||
211 | throw XmlException("Close node expected, but not found."); | ||
212 | return false; | ||
213 | } | ||
214 | |||
215 | return true; | ||
216 | } | ||
217 | |||
218 | bool XmlReader::startNode() | ||
219 | { | ||
220 | if( getChar() == '<' ) | ||
221 | { | ||
222 | usedChar(); | ||
223 | |||
224 | if( getChar() == '/' ) | ||
225 | { | ||
226 | // Heh, it's actually a close node, go figure | ||
227 | FlexBuf fbName; | ||
228 | usedChar(); | ||
229 | gcall( ws() ); | ||
230 | |||
231 | while( true ) | ||
232 | { | ||
233 | char chr = getChar(); | ||
234 | if( isws( chr ) || chr == '>' ) | ||
235 | { | ||
236 | // Here we actually compare the name we got to the name | ||
237 | // we already set, they have to match exactly. | ||
238 | if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) | ||
239 | { | ||
240 | closeNode(); | ||
241 | break; | ||
242 | } | ||
243 | else | ||
244 | { | ||
245 | throw XmlException("Got a mismatched node close tag."); | ||
246 | } | ||
247 | } | ||
248 | else | ||
249 | { | ||
250 | fbName.appendData( chr ); | ||
251 | usedChar(); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | gcall( ws() ); | ||
256 | if( getChar() == '>' ) | ||
257 | { | ||
258 | // Everything is cool. | ||
259 | usedChar(); | ||
260 | } | ||
261 | else | ||
262 | { | ||
263 | throw XmlException("Got extra junk data instead of node close tag."); | ||
264 | } | ||
265 | } | ||
266 | else | ||
267 | { | ||
268 | // We're good, format is consistant | ||
269 | addNode(); | ||
270 | |||
271 | // Skip extra whitespace | ||
272 | gcall( ws() ); | ||
273 | gcall( name() ); | ||
274 | gcall( ws() ); | ||
275 | gcall( paramlist() ); | ||
276 | gcall( ws() ); | ||
277 | } | ||
278 | } | ||
279 | else | ||
280 | { | ||
281 | throw XmlException("Expected to find node opening char, '<'."); | ||
282 | } | ||
283 | |||
284 | return true; | ||
285 | } | ||
286 | |||
287 | bool XmlReader::name() | ||
288 | { | ||
289 | FlexBuf fbName; | ||
290 | |||
291 | while( true ) | ||
292 | { | ||
293 | char chr = getChar(); | ||
294 | if( isws( chr ) || chr == '>' || chr == '/' ) | ||
295 | { | ||
296 | setName( fbName.getData() ); | ||
297 | return true; | ||
298 | } | ||
299 | else | ||
300 | { | ||
301 | fbName.appendData( chr ); | ||
302 | usedChar(); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | return true; | ||
307 | } | ||
308 | |||
309 | bool XmlReader::paramlist() | ||
310 | { | ||
311 | while( true ) | ||
312 | { | ||
313 | char chr = getChar(); | ||
314 | if( chr == '/' || chr == '>' ) | ||
315 | { | ||
316 | return true; | ||
317 | } | ||
318 | else | ||
319 | { | ||
320 | gcall( param() ); | ||
321 | gcall( ws() ); | ||
322 | } | ||
323 | } | ||
324 | |||
325 | return true; | ||
326 | } | ||
327 | |||
328 | StaticString *XmlReader::getEscape() | ||
329 | { | ||
330 | if( getChar( 1 ) == '#' ) | ||
331 | { | ||
332 | // If the entity starts with a # it's a character escape code | ||
333 | int base = 10; | ||
334 | usedChar( 2 ); | ||
335 | if( getChar() == 'x' ) | ||
336 | { | ||
337 | base = 16; | ||
338 | usedChar(); | ||
339 | } | ||
340 | char buf[4]; | ||
341 | int j = 0; | ||
342 | for( j = 0; getChar() != ';'; j++ ) | ||
343 | { | ||
344 | buf[j] = getChar(); | ||
345 | usedChar(); | ||
346 | } | ||
347 | usedChar(); | ||
348 | buf[j] = '\0'; | ||
349 | buf[0] = (char)strtol( buf, (char **)NULL, base ); | ||
350 | buf[1] = '\0'; | ||
351 | |||
352 | return new StaticString( buf ); | ||
353 | } | ||
354 | else | ||
355 | { | ||
356 | // ...otherwise replace with the appropriate string... | ||
357 | std::string buf; | ||
358 | usedChar(); | ||
359 | for(;;) | ||
360 | { | ||
361 | char cbuf = getChar(); | ||
362 | usedChar(); | ||
363 | if( cbuf == ';' ) break; | ||
364 | buf += cbuf; | ||
365 | } | ||
366 | |||
367 | StaticString *tmp = (StaticString *)htEntity[buf.c_str()]; | ||
368 | if( tmp == NULL ) return NULL; | ||
369 | |||
370 | StaticString *ret = new StaticString( *tmp ); | ||
371 | return ret; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | bool XmlReader::param() | ||
376 | { | ||
377 | FlexBuf fbName; | ||
378 | FlexBuf fbValue; | ||
379 | |||
380 | while( true ) | ||
381 | { | ||
382 | char chr = getChar(); | ||
383 | if( isws( chr ) || chr == '=' ) | ||
384 | { | ||
385 | break; | ||
386 | } | ||
387 | else | ||
388 | { | ||
389 | fbName.appendData( chr ); | ||
390 | usedChar(); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | gcall( ws() ); | ||
395 | |||
396 | if( getChar() == '=' ) | ||
397 | { | ||
398 | usedChar(); | ||
399 | |||
400 | gcall( ws() ); | ||
401 | |||
402 | char chr = getChar(); | ||
403 | if( chr == '"' ) | ||
404 | { | ||
405 | // Better quoted rhs | ||
406 | usedChar(); | ||
407 | |||
408 | while( true ) | ||
409 | { | ||
410 | chr = getChar(); | ||
411 | if( chr == '"' ) | ||
412 | { | ||
413 | usedChar(); | ||
414 | addProperty( fbName.getData(), fbValue.getData() ); | ||
415 | return true; | ||
416 | } | ||
417 | else | ||
418 | { | ||
419 | if( chr == '&' ) | ||
420 | { | ||
421 | StaticString *tmp = getEscape(); | ||
422 | if( tmp == NULL ) return false; | ||
423 | fbValue.appendData( tmp->getString() ); | ||
424 | delete tmp; | ||
425 | } | ||
426 | else | ||
427 | { | ||
428 | fbValue.appendData( chr ); | ||
429 | usedChar(); | ||
430 | } | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | else | ||
435 | { | ||
436 | // Simple one-word rhs | ||
437 | while( true ) | ||
438 | { | ||
439 | chr = getChar(); | ||
440 | if( isws( chr ) || chr == '/' || chr == '>' ) | ||
441 | { | ||
442 | addProperty( fbName.getData(), fbValue.getData() ); | ||
443 | return true; | ||
444 | } | ||
445 | else | ||
446 | { | ||
447 | if( chr == '&' ) | ||
448 | { | ||
449 | StaticString *tmp = getEscape(); | ||
450 | if( tmp == NULL ) return false; | ||
451 | fbValue.appendData( tmp->getString() ); | ||
452 | delete tmp; | ||
453 | } | ||
454 | else | ||
455 | { | ||
456 | fbValue.appendData( chr ); | ||
457 | usedChar(); | ||
458 | } | ||
459 | } | ||
460 | } | ||
461 | } | ||
462 | } | ||
463 | else | ||
464 | { | ||
465 | throw XmlException("Expected an equals to seperate the params."); | ||
466 | return false; | ||
467 | } | ||
468 | |||
469 | return true; | ||
470 | } | ||
471 | |||
472 | bool XmlReader::content() | ||
473 | { | ||
474 | FlexBuf fbContent; | ||
475 | |||
476 | if( bStrip ) gcall( ws() ); | ||
477 | |||
478 | while( true ) | ||
479 | { | ||
480 | char chr = getChar(); | ||
481 | if( chr == '<' ) | ||
482 | { | ||
483 | if( getChar(1) == '/' ) | ||
484 | { | ||
485 | if( fbContent.getLength() > 0 ) | ||
486 | { | ||
487 | if( bStrip ) | ||
488 | { | ||
489 | int j; | ||
490 | for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); | ||
491 | ((char *)fbContent.getData())[j+1] = '\0'; | ||
492 | } | ||
493 | setContent( fbContent.getData() ); | ||
494 | } | ||
495 | usedChar( 2 ); | ||
496 | gcall( ws() ); | ||
497 | FlexBuf fbName; | ||
498 | while( true ) | ||
499 | { | ||
500 | chr = getChar(); | ||
501 | if( isws( chr ) || chr == '>' ) | ||
502 | { | ||
503 | if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) | ||
504 | { | ||
505 | closeNode(); | ||
506 | break; | ||
507 | } | ||
508 | else | ||
509 | { | ||
510 | throw XmlException("Mismatched close tag found: <%s> to <%s>.", getCurrent()->getName(), fbName.getData() ); | ||
511 | } | ||
512 | } | ||
513 | else | ||
514 | { | ||
515 | fbName.appendData( chr ); | ||
516 | usedChar(); | ||
517 | } | ||
518 | } | ||
519 | gcall( ws() ); | ||
520 | if( getChar() == '>' ) | ||
521 | { | ||
522 | usedChar(); | ||
523 | return true; | ||
524 | } | ||
525 | else | ||
526 | { | ||
527 | throw XmlException("Malformed close tag."); | ||
528 | } | ||
529 | } | ||
530 | else if( getChar(1) == '!' ) | ||
531 | { | ||
532 | // We know it's a comment, let's see if it's proper | ||
533 | if( getChar(2) != '-' || | ||
534 | getChar(3) != '-' ) | ||
535 | { | ||
536 | // Not a valid XML comment | ||
537 | throw XmlException("Malformed comment start tag found."); | ||
538 | } | ||
539 | |||
540 | usedChar( 4 ); | ||
541 | |||
542 | // Now burn text until we find the close tag | ||
543 | for(;;) | ||
544 | { | ||
545 | if( getChar() == '-' ) | ||
546 | { | ||
547 | if( getChar( 1 ) == '-' ) | ||
548 | { | ||
549 | // The next one has to be a '>' now | ||
550 | if( getChar( 2 ) != '>' ) | ||
551 | { | ||
552 | throw XmlException("Malformed comment close tag found. You cannot have a '--' that isn't followed by a '>' in a comment."); | ||
553 | } | ||
554 | usedChar( 3 ); | ||
555 | break; | ||
556 | } | ||
557 | else | ||
558 | { | ||
559 | // Found a dash followed by a non dash, that's ok... | ||
560 | usedChar( 2 ); | ||
561 | } | ||
562 | } | ||
563 | else | ||
564 | { | ||
565 | // Burn comment chars | ||
566 | usedChar(); | ||
567 | } | ||
568 | } | ||
569 | } | ||
570 | else | ||
571 | { | ||
572 | if( fbContent.getLength() > 0 ) | ||
573 | { | ||
574 | if( bStrip ) | ||
575 | { | ||
576 | int j; | ||
577 | for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); | ||
578 | ((char *)fbContent.getData())[j+1] = '\0'; | ||
579 | } | ||
580 | setContent( fbContent.getData() ); | ||
581 | fbContent.clearData(); | ||
582 | } | ||
583 | gcall( node() ); | ||
584 | } | ||
585 | |||
586 | if( bStrip ) gcall( ws() ); | ||
587 | } | ||
588 | else if( chr == '&' ) | ||
589 | { | ||
590 | StaticString *tmp = getEscape(); | ||
591 | if( tmp == NULL ) return false; | ||
592 | fbContent.appendData( tmp->getString() ); | ||
593 | delete tmp; | ||
594 | } | ||
595 | else | ||
596 | { | ||
597 | fbContent.appendData( chr ); | ||
598 | usedChar(); | ||
599 | } | ||
600 | } | ||
601 | } | ||
602 | |||
diff --git a/src/old/xmlreader.h b/src/old/xmlreader.h new file mode 100644 index 0000000..c8f7202 --- /dev/null +++ b/src/old/xmlreader.h | |||
@@ -0,0 +1,141 @@ | |||
1 | #ifndef XMLREADER | ||
2 | #define XMLREADER | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include "xmldocument.h" | ||
6 | #include "flexbuf.h" | ||
7 | #include "hashtable.h" | ||
8 | #include "staticstring.h" | ||
9 | |||
10 | /** | ||
11 | * Takes care of reading in xml formatted data from a file. This could/should | ||
12 | * be made more arbitrary in the future so that we can read the data from any | ||
13 | * source. This is actually made quite simple already since all data read in | ||
14 | * is handled by one single helper function and then palced into a FlexBuf for | ||
15 | * easy access by the other functions. The FlexBuf also allows for block | ||
16 | * reading from disk, which improves speed by a noticable amount. | ||
17 | * <br> | ||
18 | * There are also some extra features implemented that allow you to break the | ||
19 | * standard XML reader specs and eliminate leading and trailing whitespace in | ||
20 | * all read content. This is useful in situations where you allow additional | ||
21 | * whitespace in the files to make them easily human readable. The resturned | ||
22 | * content will be NULL in sitautions where all content between nodes was | ||
23 | * stripped. | ||
24 | *@author Mike Buland | ||
25 | */ | ||
26 | class XmlReader : public XmlDocument | ||
27 | { | ||
28 | public: | ||
29 | /** | ||
30 | * Create a standard XmlReader. The optional parameter bStrip allows you to | ||
31 | * create a reader that will strip out all leading and trailing whitespace | ||
32 | * in content, a-la html. | ||
33 | *@param bStrip Strip out leading and trailing whitespace? | ||
34 | */ | ||
35 | XmlReader( bool bStrip=false ); | ||
36 | |||
37 | /** | ||
38 | * Destroy this XmlReader. | ||
39 | */ | ||
40 | virtual ~XmlReader(); | ||
41 | |||
42 | /** | ||
43 | * Build a document based on some kind of input. This is called | ||
44 | * automatically by the constructor. | ||
45 | */ | ||
46 | bool buildDoc(); | ||
47 | |||
48 | private: | ||
49 | /** | ||
50 | * This is called by the low level automoton in order to get the next | ||
51 | * character. This function should return a character at the current | ||
52 | * position plus nIndex, but does not increment the current character. | ||
53 | *@param nIndex The index of the character from the current stream position. | ||
54 | *@returns A single character at the requested position, or 0 for end of | ||
55 | * stream. | ||
56 | */ | ||
57 | virtual char getChar( int nIndex = 0 ) = 0; | ||
58 | |||
59 | /** | ||
60 | * Called to increment the current stream position by a single character. | ||
61 | */ | ||
62 | virtual void usedChar( int nAmnt = 1) = 0; | ||
63 | |||
64 | /** | ||
65 | * Automoton function: is whitespace. | ||
66 | *@param chr A character | ||
67 | *@returns True if chr is whitespace, false otherwise. | ||
68 | */ | ||
69 | bool isws( char chr ); | ||
70 | |||
71 | /** | ||
72 | * Automoton function: ws. Skips sections of whitespace. | ||
73 | *@returns True if everything was ok, False for end of stream. | ||
74 | */ | ||
75 | bool ws(); | ||
76 | |||
77 | /** | ||
78 | * Automoton function: node. Processes an XmlNode | ||
79 | *@returns True if everything was ok, False for end of stream. | ||
80 | */ | ||
81 | bool node(); | ||
82 | |||
83 | /** | ||
84 | * Automoton function: startNode. Processes the begining of a node. | ||
85 | *@returns True if everything was ok, False for end of stream. | ||
86 | */ | ||
87 | bool startNode(); | ||
88 | |||
89 | /** | ||
90 | * Automoton function: name. Processes the name of a node. | ||
91 | *@returns True if everything was ok, False for end of stream. | ||
92 | */ | ||
93 | bool name(); | ||
94 | |||
95 | /** | ||
96 | * Automoton function: textDecl. Processes the xml text decleration, if | ||
97 | * there is one. | ||
98 | */ | ||
99 | void textDecl(); | ||
100 | |||
101 | /** | ||
102 | * Automoton function: entity. Processes an entity from the header. | ||
103 | */ | ||
104 | void entity(); | ||
105 | |||
106 | /** | ||
107 | * Adds an entity to the list, if it doesn't already exist. | ||
108 | *@param name The name of the entity | ||
109 | *@param value The value of the entity | ||
110 | */ | ||
111 | void addEntity( const char *name, const char *value ); | ||
112 | |||
113 | StaticString *getEscape(); | ||
114 | |||
115 | /** | ||
116 | * Automoton function: paramlist. Processes a list of node params. | ||
117 | *@returns True if everything was ok, False for end of stream. | ||
118 | */ | ||
119 | bool paramlist(); | ||
120 | |||
121 | /** | ||
122 | * Automoton function: param. Processes a single parameter. | ||
123 | *@returns True if everything was ok, False for end of stream. | ||
124 | */ | ||
125 | bool param(); | ||
126 | |||
127 | /** | ||
128 | * Automoton function: content. Processes node content. | ||
129 | *@returns True if everything was ok, False for end of stream. | ||
130 | */ | ||
131 | bool content(); | ||
132 | |||
133 | FlexBuf fbContent; /**< buffer for the current node's content. */ | ||
134 | FlexBuf fbParamName; /**< buffer for the current param's name. */ | ||
135 | FlexBuf fbParamValue; /**< buffer for the current param's value. */ | ||
136 | bool bStrip; /**< Are we stripping whitespace? */ | ||
137 | |||
138 | HashTable htEntity; /**< Entity type definitions. */ | ||
139 | }; | ||
140 | |||
141 | #endif | ||
diff --git a/src/old/xmlstringreader.cpp b/src/old/xmlstringreader.cpp new file mode 100644 index 0000000..3956ff3 --- /dev/null +++ b/src/old/xmlstringreader.cpp | |||
@@ -0,0 +1,38 @@ | |||
1 | #include "xmlstringreader.h" | ||
2 | #include "exceptions.h" | ||
3 | #include <string.h> | ||
4 | |||
5 | XmlStringReader::XmlStringReader( const char *sString, bool bStrip ) | ||
6 | : XmlReader( bStrip ) | ||
7 | { | ||
8 | this->sString = sString; | ||
9 | |||
10 | nIndex = 0; | ||
11 | nLength = strlen( sString ); | ||
12 | |||
13 | buildDoc(); | ||
14 | } | ||
15 | |||
16 | XmlStringReader::~XmlStringReader() | ||
17 | { | ||
18 | } | ||
19 | |||
20 | char XmlStringReader::getChar( int nAdd ) | ||
21 | { | ||
22 | if( nLength >= nIndex+nAdd+1 ) | ||
23 | { | ||
24 | return sString[nIndex+nAdd]; | ||
25 | } | ||
26 | else | ||
27 | { | ||
28 | throw XmlException("End of XML stream read."); | ||
29 | } | ||
30 | } | ||
31 | |||
32 | void XmlStringReader::usedChar( int nAmnt ) | ||
33 | { | ||
34 | if( nLength >= nIndex+nAmnt ) | ||
35 | { | ||
36 | nIndex += nAmnt; | ||
37 | } | ||
38 | } | ||
diff --git a/src/old/xmlstringreader.h b/src/old/xmlstringreader.h new file mode 100644 index 0000000..1239ef4 --- /dev/null +++ b/src/old/xmlstringreader.h | |||
@@ -0,0 +1,49 @@ | |||
1 | #ifndef XMLSTRINGREADER | ||
2 | #define XMLSTRINGREADER | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include "xmlreader.h" | ||
6 | #include "flexbuf.h" | ||
7 | |||
8 | /** | ||
9 | * Takes care of reading in xml formatted data from a file. This could/should | ||
10 | * be made more arbitrary in the future so that we can read the data from any | ||
11 | * source. This is actually made quite simple already since all data read in | ||
12 | * is handled by one single helper function and then palced into a FlexBuf for | ||
13 | * easy access by the other functions. The FlexBuf also allows for block | ||
14 | * reading from disk, which improves speed by a noticable amount. | ||
15 | * <br> | ||
16 | * There are also some extra features implemented that allow you to break the | ||
17 | * standard XML reader specs and eliminate leading and trailing whitespace in | ||
18 | * all read content. This is useful in situations where you allow additional | ||
19 | * whitespace in the files to make them easily human readable. The resturned | ||
20 | * content will be NULL in sitautions where all content between nodes was | ||
21 | * stripped. | ||
22 | *@author Mike Buland | ||
23 | */ | ||
24 | class XmlStringReader : public XmlReader | ||
25 | { | ||
26 | public: | ||
27 | /** | ||
28 | * Create a new string reader around an already created and formatted | ||
29 | * null-terminated string. | ||
30 | *@param sString A pointer to the string data that will be used. This data | ||
31 | * is not changed during processing. | ||
32 | *@param bStrip Strip out leading and trailing whitespace. | ||
33 | */ | ||
34 | XmlStringReader( const char *sString, bool bStrip=false ); | ||
35 | |||
36 | /** | ||
37 | * Destroy this string reader. | ||
38 | */ | ||
39 | virtual ~XmlStringReader(); | ||
40 | |||
41 | private: | ||
42 | char getChar( int nIndex = 0 ); | ||
43 | void usedChar( int nAmnt = 1 ); | ||
44 | const char *sString; /**< Internal pointer to the input string. */ | ||
45 | int nIndex; /**< Our index into the string */ | ||
46 | int nLength; /**< The computed length of the string */ | ||
47 | }; | ||
48 | |||
49 | #endif | ||
diff --git a/src/old/xmlstringwriter.cpp b/src/old/xmlstringwriter.cpp new file mode 100644 index 0000000..adeed6a --- /dev/null +++ b/src/old/xmlstringwriter.cpp | |||
@@ -0,0 +1,23 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "xmlstringwriter.h" | ||
4 | |||
5 | XmlStringWriter::XmlStringWriter( const char *sIndent ) : | ||
6 | XmlWriter( sIndent ) | ||
7 | { | ||
8 | } | ||
9 | |||
10 | XmlStringWriter::~XmlStringWriter() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | void XmlStringWriter::writeString( const char *sString ) | ||
15 | { | ||
16 | sXml += sString; | ||
17 | } | ||
18 | |||
19 | std::string &XmlStringWriter::getString() | ||
20 | { | ||
21 | return sXml; | ||
22 | } | ||
23 | |||
diff --git a/src/old/xmlstringwriter.h b/src/old/xmlstringwriter.h new file mode 100644 index 0000000..0d567b9 --- /dev/null +++ b/src/old/xmlstringwriter.h | |||
@@ -0,0 +1,50 @@ | |||
1 | #ifndef XML_STRING_WRITER | ||
2 | #define XML_STRING_WRITER | ||
3 | |||
4 | #include "xmlnode.h" | ||
5 | #include "xmlwriter.h" | ||
6 | |||
7 | /** | ||
8 | * Implements xml writing in the XML standard format. Also allows you to | ||
9 | * break that format and auto-indent your exported xml data for ease of | ||
10 | * reading. The auto-indenting will only be applied to sections that | ||
11 | * have no content of their own already. This means that except for | ||
12 | * whitespace all of your data will be preserved perfectly. | ||
13 | * You can create an XmlWriter object around a file, or access the static | ||
14 | * write function directly and just hand it a filename and a root XmlNode. | ||
15 | * When using an XmlWriter object the interface is identicle to that of | ||
16 | * the XmlDocument class, so reference that class for API info. However | ||
17 | * when the initial (or root) node is closed, and the document is finished | ||
18 | * the file will be created and written to automatically. The user can | ||
19 | * check to see if this is actually true by calling the isFinished | ||
20 | * function in the XmlDocument class. | ||
21 | *@author Mike Buland | ||
22 | */ | ||
23 | class XmlStringWriter : public XmlWriter | ||
24 | { | ||
25 | public: | ||
26 | /** | ||
27 | * Construct a string writer using an internal string buffer. | ||
28 | *@param sIndent Optional indent to add to each line. | ||
29 | */ | ||
30 | XmlStringWriter( const char *sIndent=NULL ); | ||
31 | |||
32 | /** | ||
33 | * Destroy the string writer and the internal string. | ||
34 | */ | ||
35 | virtual ~XmlStringWriter(); | ||
36 | |||
37 | /** | ||
38 | * Get the string that was built. This is only valid after the document has | ||
39 | * been completed, so check isCompleted or be sure your addNode and | ||
40 | * closeNode calls match up. | ||
41 | *@returns A reference to the internal string object. | ||
42 | */ | ||
43 | std::string &getString(); | ||
44 | |||
45 | private: | ||
46 | void writeString( const char *sString ); | ||
47 | std::string sXml; /**< The string object we "write" to. */ | ||
48 | }; | ||
49 | |||
50 | #endif | ||
diff --git a/src/old/xmlwriter.cpp b/src/old/xmlwriter.cpp new file mode 100644 index 0000000..56880b6 --- /dev/null +++ b/src/old/xmlwriter.cpp | |||
@@ -0,0 +1,173 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "xmlwriter.h" | ||
4 | |||
5 | XmlWriter::XmlWriter( const char *sIndent, XmlNode *pRoot ) : | ||
6 | XmlDocument( pRoot ) | ||
7 | { | ||
8 | if( sIndent == NULL ) | ||
9 | { | ||
10 | this->sIndent = ""; | ||
11 | } | ||
12 | else | ||
13 | { | ||
14 | this->sIndent = sIndent; | ||
15 | } | ||
16 | } | ||
17 | |||
18 | XmlWriter::~XmlWriter() | ||
19 | { | ||
20 | } | ||
21 | |||
22 | void XmlWriter::write() | ||
23 | { | ||
24 | write( getRoot(), sIndent.c_str() ); | ||
25 | } | ||
26 | |||
27 | void XmlWriter::write( XmlNode *pRoot, const char *sIndent ) | ||
28 | { | ||
29 | writeNode( pRoot, 0, sIndent ); | ||
30 | } | ||
31 | |||
32 | void XmlWriter::closeNode() | ||
33 | { | ||
34 | XmlDocument::closeNode(); | ||
35 | |||
36 | if( isCompleted() ) | ||
37 | { | ||
38 | write( getRoot(), sIndent.c_str() ); | ||
39 | } | ||
40 | } | ||
41 | |||
42 | void XmlWriter::writeIndent( int nIndent, const char *sIndent ) | ||
43 | { | ||
44 | if( sIndent == NULL ) return; | ||
45 | for( int j = 0; j < nIndent; j++ ) | ||
46 | { | ||
47 | writeString( sIndent ); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | std::string XmlWriter::escape( std::string sIn ) | ||
52 | { | ||
53 | std::string sOut; | ||
54 | |||
55 | std::string::const_iterator i; | ||
56 | for( i = sIn.begin(); i != sIn.end(); i++ ) | ||
57 | { | ||
58 | if( ((*i >= ' ' && *i <= '9') || | ||
59 | (*i >= 'a' && *i <= 'z') || | ||
60 | (*i >= 'A' && *i <= 'Z') ) && | ||
61 | (*i != '\"' && *i != '\'' && *i != '&') | ||
62 | ) | ||
63 | { | ||
64 | sOut += *i; | ||
65 | } | ||
66 | else | ||
67 | { | ||
68 | sOut += "&#"; | ||
69 | char buf[4]; | ||
70 | sprintf( buf, "%u", (unsigned char)*i ); | ||
71 | sOut += buf; | ||
72 | sOut += ';'; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | return sOut; | ||
77 | } | ||
78 | |||
79 | void XmlWriter::writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ) | ||
80 | { | ||
81 | for( int j = 0; j < pNode->getNumProperties(); j++ ) | ||
82 | { | ||
83 | writeString(" "); | ||
84 | writeString( pNode->getPropertyName( j ) ); | ||
85 | writeString("=\""); | ||
86 | writeString( escape( pNode->getProperty( j ) ).c_str() ); | ||
87 | writeString("\""); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) | ||
92 | { | ||
93 | if( pNode->hasChildren() ) | ||
94 | { | ||
95 | writeIndent( nIndent, sIndent ); | ||
96 | writeString("<"); | ||
97 | writeString( pNode->getName() ); | ||
98 | writeNodeProps( pNode, nIndent, sIndent ); | ||
99 | if( sIndent ) | ||
100 | writeString(">\n"); | ||
101 | else | ||
102 | writeString(">"); | ||
103 | |||
104 | if( pNode->getContent( 0 ) ) | ||
105 | { | ||
106 | writeIndent( nIndent+1, sIndent ); | ||
107 | if( sIndent ) | ||
108 | { | ||
109 | writeString( pNode->getContent( 0 ) ); | ||
110 | writeString("\n"); | ||
111 | } | ||
112 | else | ||
113 | writeString( pNode->getContent( 0 ) ); | ||
114 | } | ||
115 | |||
116 | int nNumChildren = pNode->getNumChildren(); | ||
117 | for( int j = 0; j < nNumChildren; j++ ) | ||
118 | { | ||
119 | writeNode( pNode->getChild( j ), nIndent+1, sIndent ); | ||
120 | if( pNode->getContent( j+1 ) ) | ||
121 | { | ||
122 | writeIndent( nIndent+1, sIndent ); | ||
123 | if( sIndent ) | ||
124 | { | ||
125 | writeString( pNode->getContent( j+1 ) ); | ||
126 | writeString("\n"); | ||
127 | } | ||
128 | else | ||
129 | writeString( pNode->getContent( j+1 ) ); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | writeIndent( nIndent, sIndent ); | ||
134 | if( sIndent ) | ||
135 | { | ||
136 | writeString("</"); | ||
137 | writeString( pNode->getName() ); | ||
138 | writeString(">\n"); | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | writeString("</"); | ||
143 | writeString( pNode->getName() ); | ||
144 | writeString(">"); | ||
145 | } | ||
146 | } | ||
147 | else if( pNode->getContent() ) | ||
148 | { | ||
149 | writeIndent( nIndent, sIndent ); | ||
150 | writeString("<"); | ||
151 | writeString( pNode->getName() ); | ||
152 | writeNodeProps( pNode, nIndent, sIndent ); | ||
153 | writeString(">"); | ||
154 | writeString( pNode->getContent() ); | ||
155 | writeString("</"); | ||
156 | writeString( pNode->getName() ); | ||
157 | writeString(">"); | ||
158 | if( sIndent ) | ||
159 | writeString("\n"); | ||
160 | } | ||
161 | else | ||
162 | { | ||
163 | writeIndent( nIndent, sIndent ); | ||
164 | writeString("<"); | ||
165 | writeString( pNode->getName() ); | ||
166 | writeNodeProps( pNode, nIndent, sIndent ); | ||
167 | if( sIndent ) | ||
168 | writeString("/>\n"); | ||
169 | else | ||
170 | writeString("/>"); | ||
171 | } | ||
172 | } | ||
173 | |||
diff --git a/src/old/xmlwriter.h b/src/old/xmlwriter.h new file mode 100644 index 0000000..c48e810 --- /dev/null +++ b/src/old/xmlwriter.h | |||
@@ -0,0 +1,96 @@ | |||
1 | #ifndef XMLWRITER | ||
2 | #define XMLWRITER | ||
3 | |||
4 | #include "xmlnode.h" | ||
5 | #include "xmldocument.h" | ||
6 | |||
7 | /** | ||
8 | * Implements xml writing in the XML standard format. Also allows you to | ||
9 | * break that format and auto-indent your exported xml data for ease of | ||
10 | * reading. The auto-indenting will only be applied to sections that | ||
11 | * have no content of their own already. This means that except for | ||
12 | * whitespace all of your data will be preserved perfectly. | ||
13 | * You can create an XmlWriter object around a file, or access the static | ||
14 | * write function directly and just hand it a filename and a root XmlNode. | ||
15 | * When using an XmlWriter object the interface is identicle to that of | ||
16 | * the XmlDocument class, so reference that class for API info. However | ||
17 | * when the initial (or root) node is closed, and the document is finished | ||
18 | * the file will be created and written to automatically. The user can | ||
19 | * check to see if this is actually true by calling the isFinished | ||
20 | * function in the XmlDocument class. | ||
21 | *@author Mike Buland | ||
22 | */ | ||
23 | class XmlWriter : public XmlDocument | ||
24 | { | ||
25 | public: | ||
26 | /** | ||
27 | * Construct a standard XmlWriter. | ||
28 | *@param sIndent Set this to something other than NULL to include it as an | ||
29 | * indent before each node in the output that doesn't already have content. | ||
30 | * If you are using the whitespace stripping option in the XmlReader and set | ||
31 | * this to a tab or some spaces it will never effect the content of your | ||
32 | * file. | ||
33 | */ | ||
34 | XmlWriter( const char *sIndent=NULL, XmlNode *pRoot=NULL ); | ||
35 | |||
36 | /** | ||
37 | * Destroy the writer. | ||
38 | */ | ||
39 | virtual ~XmlWriter(); | ||
40 | |||
41 | /** | ||
42 | * This override of the parent class closeNode function calls the parent | ||
43 | * class, but also triggers a write operation when the final node is closed. | ||
44 | * This means that by checking the isCompleted() function the user may also | ||
45 | * check to see if their file has been written or not. | ||
46 | */ | ||
47 | void closeNode(); | ||
48 | |||
49 | void write(); | ||
50 | |||
51 | private: | ||
52 | std::string sIndent; /**< The indent string */ | ||
53 | |||
54 | std::string escape( std::string sIn ); | ||
55 | |||
56 | /** | ||
57 | * Write the file. | ||
58 | *@param pNode The root node | ||
59 | *@param sIndent The indent text. | ||
60 | */ | ||
61 | void write( XmlNode *pNode, const char *sIndent=NULL ); | ||
62 | |||
63 | /** | ||
64 | * Write a node in the file, including children. | ||
65 | *@param pNode The node to write. | ||
66 | *@param nIndent The indent level (the number of times to include sIndent) | ||
67 | *@param sIndent The indent text. | ||
68 | */ | ||
69 | void writeNode( XmlNode *pNode, int nIndent, const char *sIndent ); | ||
70 | |||
71 | /** | ||
72 | * Write the properties of a node. | ||
73 | *@param pNode The node who's properties to write. | ||
74 | *@param nIndent The indent level of the containing node | ||
75 | *@param sIndent The indent text. | ||
76 | */ | ||
77 | void writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ); | ||
78 | |||
79 | /** | ||
80 | * Called to write the actual indent. | ||
81 | *@param nIndent The indent level. | ||
82 | *@param sIndent The indent text. | ||
83 | */ | ||
84 | void writeIndent( int nIndent, const char *sIndent ); | ||
85 | |||
86 | /** | ||
87 | * This is the function that must be overridden in order to use this class. | ||
88 | * It must write the null-terminated string sString, minus the mull, | ||
89 | * verbatum to it's output device. Adding extra characters for any reason | ||
90 | * will break the XML formatting. | ||
91 | *@param sString The string data to write to the output. | ||
92 | */ | ||
93 | virtual void writeString( const char *sString ) = 0; | ||
94 | }; | ||
95 | |||
96 | #endif | ||