aboutsummaryrefslogtreecommitdiff
path: root/src/old
diff options
context:
space:
mode:
Diffstat (limited to 'src/old')
-rw-r--r--src/old/arraylist.cpp100
-rw-r--r--src/old/arraylist.h80
-rw-r--r--src/old/cgi.cpp644
-rw-r--r--src/old/cgi.h196
-rw-r--r--src/old/configmanagerbase.cpp63
-rw-r--r--src/old/configmanagerbase.h24
-rw-r--r--src/old/confpair.cpp2
-rw-r--r--src/old/confpair.h81
-rw-r--r--src/old/confpairbase.cpp17
-rw-r--r--src/old/confpairbase.h24
-rw-r--r--src/old/conftree.cpp9
-rw-r--r--src/old/conftree.h19
-rw-r--r--src/old/connection.cpp564
-rw-r--r--src/old/connection.h411
-rw-r--r--src/old/connectionmanager.cpp397
-rw-r--r--src/old/connectionmanager.h169
-rw-r--r--src/old/connectionmonitor.cpp10
-rw-r--r--src/old/connectionmonitor.h47
-rw-r--r--src/old/exceptionbase.cpp70
-rw-r--r--src/old/exceptionbase.h105
-rw-r--r--src/old/exceptions.cpp8
-rw-r--r--src/old/exceptions.h25
-rw-r--r--src/old/flexbuf.cpp229
-rw-r--r--src/old/flexbuf.h162
-rw-r--r--src/old/formula.cpp262
-rw-r--r--src/old/formula.h77
-rw-r--r--src/old/fstring.cpp13
-rw-r--r--src/old/fstring.h651
-rw-r--r--src/old/hash.cpp113
-rw-r--r--src/old/hash.h744
-rw-r--r--src/old/hashable.cpp1
-rw-r--r--src/old/hashable.h12
-rw-r--r--src/old/hashfunction.cpp10
-rw-r--r--src/old/hashfunction.h48
-rw-r--r--src/old/hashfunctioncasestring.cpp39
-rw-r--r--src/old/hashfunctioncasestring.h28
-rw-r--r--src/old/hashfunctionint.cpp20
-rw-r--r--src/old/hashfunctionint.h26
-rw-r--r--src/old/hashfunctionstring.cpp51
-rw-r--r--src/old/hashfunctionstring.h27
-rw-r--r--src/old/hashtable.cpp424
-rw-r--r--src/old/hashtable.h308
-rw-r--r--src/old/http.cpp377
-rw-r--r--src/old/http.h273
-rw-r--r--src/old/httpget.cpp263
-rw-r--r--src/old/httpget.h44
-rw-r--r--src/old/linkedlist.cpp210
-rw-r--r--src/old/linkedlist.h87
-rw-r--r--src/old/linkmessage.cpp44
-rw-r--r--src/old/linkmessage.h39
-rw-r--r--src/old/linkmessenger.cpp41
-rw-r--r--src/old/linkmessenger.h32
-rw-r--r--src/old/list.cpp10
-rw-r--r--src/old/list.h101
-rw-r--r--src/old/md5.cpp190
-rw-r--r--src/old/md5.h81
-rw-r--r--src/old/multilog.cpp102
-rw-r--r--src/old/multilog.h130
-rw-r--r--src/old/multilogchannel.cpp13
-rw-r--r--src/old/multilogchannel.h46
-rw-r--r--src/old/multilogtext.cpp188
-rw-r--r--src/old/multilogtext.h70
-rw-r--r--src/old/ordhash.cpp1
-rw-r--r--src/old/ordhash.h104
-rw-r--r--src/old/paramproc.cpp514
-rw-r--r--src/old/paramproc.h153
-rw-r--r--src/old/plugger.cpp1
-rw-r--r--src/old/plugger.h198
-rw-r--r--src/old/pqueue.cpp33
-rw-r--r--src/old/pqueue.h48
-rw-r--r--src/old/programchain.cpp96
-rw-r--r--src/old/programchain.h95
-rw-r--r--src/old/programlink.cpp54
-rw-r--r--src/old/programlink.h99
-rw-r--r--src/old/protocol.cpp20
-rw-r--r--src/old/protocol.h62
-rw-r--r--src/old/protocoltelnet.cpp316
-rw-r--r--src/old/protocoltelnet.h77
-rw-r--r--src/old/queue.cpp26
-rw-r--r--src/old/queue.h45
-rw-r--r--src/old/ringlist.cpp106
-rw-r--r--src/old/ringlist.h112
-rw-r--r--src/old/sbuffer.cpp67
-rw-r--r--src/old/sbuffer.h40
-rw-r--r--src/old/serializable.cpp8
-rw-r--r--src/old/serializable.h34
-rw-r--r--src/old/serializer.cpp338
-rw-r--r--src/old/serializer.h80
-rw-r--r--src/old/serializerbinary.cpp63
-rw-r--r--src/old/serializerbinary.h24
-rw-r--r--src/old/serializerbzip2.cpp88
-rw-r--r--src/old/serializerbzip2.h27
-rw-r--r--src/old/serializerconnection.cpp15
-rw-r--r--src/old/serializerconnection.h24
-rw-r--r--src/old/serializertext.cpp170
-rw-r--r--src/old/serializertext.h49
-rw-r--r--src/old/sfile.cpp74
-rw-r--r--src/old/sfile.h29
-rw-r--r--src/old/sha1.cpp161
-rw-r--r--src/old/sha1.h42
-rw-r--r--src/old/singleton.h59
-rw-r--r--src/old/sptr.cpp1
-rw-r--r--src/old/sptr.h99
-rw-r--r--src/old/stack.cpp33
-rw-r--r--src/old/stack.h50
-rw-r--r--src/old/staticstring.cpp282
-rw-r--r--src/old/staticstring.h63
-rw-r--r--src/old/stream.cpp10
-rw-r--r--src/old/stream.h27
-rw-r--r--src/old/stringrep.cpp19
-rw-r--r--src/old/stringrep.h17
-rw-r--r--src/old/tests/clistress.cpp20
-rw-r--r--src/old/tests/confpair.cpp19
-rw-r--r--src/old/tests/connect.cpp38
-rw-r--r--src/old/tests/exception.cpp16
-rw-r--r--src/old/tests/formula.cpp13
-rw-r--r--src/old/tests/fstring.cpp48
-rw-r--r--src/old/tests/hash.cpp116
-rw-r--r--src/old/tests/hashtest.cpp107
-rw-r--r--src/old/tests/hashtest2.cpp15
-rw-r--r--src/old/tests/httpsrv/httpconnectionmonitor.cpp88
-rw-r--r--src/old/tests/httpsrv/httpconnectionmonitor.h16
-rw-r--r--src/old/tests/httpsrv/main.cpp22
-rw-r--r--src/old/tests/log.cpp29
-rw-r--r--src/old/tests/md5test.cpp19
-rw-r--r--src/old/tests/ordhash.cpp48
-rw-r--r--src/old/tests/param.cpp46
-rw-r--r--src/old/tests/param.h21
-rw-r--r--src/old/tests/plugin/main.cpp14
-rw-r--r--src/old/tests/plugin/plugin.cpp10
-rw-r--r--src/old/tests/plugin/plugin.h14
-rw-r--r--src/old/tests/qsort.cpp228
-rw-r--r--src/old/tests/sbuffer.cpp27
-rw-r--r--src/old/tests/serialize.cpp30
-rw-r--r--src/old/tests/serializetext.cpp28
-rw-r--r--src/old/tests/sha1.cpp44
-rw-r--r--src/old/tests/sptr.cpp55
-rw-r--r--src/old/tests/srvstress.cpp91
-rw-r--r--src/old/tests/strhash.cpp12
-rw-r--r--src/old/tests/teltest/main.cpp21
-rw-r--r--src/old/tests/teltest/telnetmonitor.cpp54
-rw-r--r--src/old/tests/teltest/telnetmonitor.h26
-rw-r--r--src/old/tests/xmlreadtest.cpp29
-rw-r--r--src/old/tests/xmlrepltest.cpp31
-rw-r--r--src/old/tests/xmlwritetest.cpp48
-rw-r--r--src/old/tokenstring.cpp163
-rw-r--r--src/old/tokenstring.h114
-rw-r--r--src/old/tqsort.h207
-rw-r--r--src/old/unit/hashtable/hashtable.cpp107
-rw-r--r--src/old/unit/xml/xml.cpp59
-rw-r--r--src/old/xmldocument.cpp149
-rw-r--r--src/old/xmldocument.h171
-rw-r--r--src/old/xmlfilereader.cpp58
-rw-r--r--src/old/xmlfilereader.h47
-rw-r--r--src/old/xmlfilewriter.cpp28
-rw-r--r--src/old/xmlfilewriter.h45
-rw-r--r--src/old/xmlnode.cpp445
-rw-r--r--src/old/xmlnode.h236
-rw-r--r--src/old/xmlreader.cpp602
-rw-r--r--src/old/xmlreader.h141
-rw-r--r--src/old/xmlstringreader.cpp38
-rw-r--r--src/old/xmlstringreader.h49
-rw-r--r--src/old/xmlstringwriter.cpp23
-rw-r--r--src/old/xmlstringwriter.h50
-rw-r--r--src/old/xmlwriter.cpp173
-rw-r--r--src/old/xmlwriter.h96
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
5ArrayList::ArrayList( int initSize, int growByFactor )
6{
7 apData = new void *[initSize];
8 nSize = 0;
9 nCapacity = initSize;
10 nGrowByFactor = growByFactor;
11}
12
13ArrayList::~ArrayList( )
14{
15 delete[] apData;
16}
17
18void *ArrayList::getAt( int index )
19{
20 if( index < 0 || index > nSize )
21 return NULL;
22
23 return apData[index];
24}
25
26void ArrayList::append( void *data )
27{
28 insertBefore( data, nSize );
29}
30
31void 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
42int ArrayList::getSize( )
43{
44 return nSize;
45}
46
47bool ArrayList::isEmpty( )
48{
49 return nSize==0;
50}
51
52void 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
61void ArrayList::empty()
62{
63 // Probably the easiest as far as things go.
64 nSize = 0;
65}
66
67void 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
76void ArrayList::checkResize()
77{
78 if( nSize >= nCapacity )
79 {
80 resizeTo( nCapacity + nGrowByFactor );
81 }
82}
83
84void ArrayList::setSize( int newSize )
85{
86 if( newSize < 0 )
87 return;
88
89 nSize = newSize;
90 checkResize();
91}
92
93void 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 */
15class ArrayList : public List
16{
17public:
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
39private:
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
9Cgi::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
448Cgi::~Cgi( )
449{
450}
451
452char *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
475int 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
498void 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
512void 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
522void 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
540void 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
619void 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 */
30class Cgi
31{
32public:
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
191private:
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
7ConfigManagerBase::ConfigManagerBase()
8{
9}
10
11ConfigManagerBase::~ConfigManagerBase()
12{
13}
14
15void ConfigManagerBase::addSearchPath( const std::string &sPath )
16{
17 lSearchPath.push_back( sPath );
18}
19
20void 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
33bool 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
7class ConfigManagerBase
8{
9public:
10 ConfigManagerBase();
11 virtual ~ConfigManagerBase();
12
13public:
14 void addSearchPath( const std::string &sPath );
15 void loadConfig( const std::string &sFileName, const char *lpProfile="default" );
16
17private:
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 */
12template<class T>
13class ConfPair : public ConfPairBase
14{
15public:
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
45private:
46 std::string sName;
47 T tValue;
48};
49
50template<>
51void ConfPair<std::string>::setFromString( const std::string &sStr )
52{
53 tValue = sStr;
54}
55
56template<>
57std::string ConfPair<std::string>::getAsString()
58{
59 return tValue;
60}
61
62template<>
63void 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
73template<>
74std::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
3ConfPairBase::ConfPairBase()
4{
5}
6
7ConfPairBase::~ConfPairBase()
8{
9}
10
11ConfPairBase &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
9class ConfPairBase
10{
11public:
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
20private:
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
3ConfTree::ConfTree()
4{
5}
6
7ConfTree::~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 */
9class ConfTree
10{
11public:
12 ConfTree();
13 virtual ~ConfTree();
14
15private:
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
20Connection::Connection()
21{
22 nSocket = -1;
23 bActive = false;
24 bDisconnectMe = false;
25 pProtocol = NULL;
26}
27
28Connection::~Connection()
29{
30 if( pProtocol != NULL ) delete pProtocol;
31}
32
33void Connection::ensureCapacity( int nSize )
34{
35 xOutputBuf.ensureCapacity( nSize );
36}
37
38bool Connection::appendOutput( const char *lpOutput, int nSize )
39{
40 return xOutputBuf.appendData( lpOutput, nSize );
41}
42
43bool Connection::appendOutput( const char lOutput )
44{
45 return xOutputBuf.appendData( lOutput );
46}
47
48bool Connection::appendOutput( const short lOutput )
49{
50 return xOutputBuf.appendData( lOutput );
51}
52
53bool Connection::appendOutput( const int lOutput )
54{
55 return xOutputBuf.appendData( lOutput );
56}
57
58bool Connection::appendOutput( const long lOutput )
59{
60 return xOutputBuf.appendData( lOutput );
61}
62
63bool Connection::appendOutput( const float lOutput )
64{
65 return xOutputBuf.appendData( lOutput );
66}
67
68bool Connection::appendOutput( const double lOutput )
69{
70 return xOutputBuf.appendData( lOutput );
71}
72
73bool Connection::appendOutput( const unsigned char lOutput )
74{
75 return xOutputBuf.appendData( lOutput );
76}
77
78bool Connection::appendOutput( const unsigned short lOutput )
79{
80 return xOutputBuf.appendData( lOutput );
81}
82
83bool Connection::appendOutput( const unsigned long lOutput )
84{
85 return xOutputBuf.appendData( lOutput );
86}
87
88bool Connection::appendOutput( const unsigned int lOutput )
89{
90 return xOutputBuf.appendData( lOutput );
91}
92
93bool Connection::appendInput( const char *lpInput, int nSize )
94{
95 return xInputBuf.appendData( lpInput, nSize );
96}
97
98int 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
114const char *Connection::getOutput()
115{
116 return xOutputBuf.getData();
117}
118
119const char *Connection::getInput()
120{
121 return xInputBuf.getData();
122}
123
124void Connection::setSocket( int nNewSocket )
125{
126 nSocket = nNewSocket;
127}
128
129int Connection::getSocket()
130{
131 return nSocket;
132}
133
134bool Connection::isActive()
135{
136 return bActive;
137}
138
139void 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
159bool Connection::open( int nNewSocket )
160{
161 bActive = true;
162 setSocket( nNewSocket );
163 bDisconnectMe = false;
164
165 return true;
166}
167
168bool 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
253int 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
312bool 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
380void 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
398bool Connection::clearOutput()
399{
400 return xOutputBuf.clearData();
401}
402
403bool Connection::clearInput()
404{
405 return xInputBuf.clearData();
406}
407
408#define min( a, b ) ((a<b)?(a):(b))
409
410bool 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
435bool Connection::writeAllOutput()
436{
437 while( hasOutput() ) writeOutput();
438 return true;
439}
440
441bool Connection::hasOutput()
442{
443 if( xOutputBuf.getLength() == 0 )
444 {
445 return false;
446 }
447 else
448 {
449 return true;
450 }
451}
452
453bool Connection::hasInput()
454{
455 if( xInputBuf.getLength() == 0 )
456 {
457 return false;
458 }
459 else
460 {
461 return true;
462 }
463}
464
465bool Connection::usedInput( int nAmount )
466{
467 return xInputBuf.usedData( nAmount );
468}
469
470bool Connection::needDisconnect()
471{
472 return bDisconnectMe;
473}
474
475void Connection::disconnect()
476{
477 bDisconnectMe = true;
478}
479
480void Connection::setProtocol( class Protocol *pNewProtocol )
481{
482 pProtocol = pNewProtocol;
483 pProtocol->setConnection( this );
484}
485
486int Connection::getInputAmnt()
487{
488 return xInputBuf.getLength();
489}
490
491int Connection::getOutputAmnt()
492{
493 return xOutputBuf.getLength();
494}
495
496class Protocol *Connection::getProtocol()
497{
498 return pProtocol;
499}
500
501void 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
513void 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
525void 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 */
21class Connection
22{
23public:
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
369private:
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
16ConnectionManager::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
31ConnectionManager::~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
44bool 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
60bool 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
74bool 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
113bool 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
139bool 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
240bool 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
275bool 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
290bool 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
349void 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
369Connection *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
380Connection *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
394void 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 */
22class ConnectionManager
23{
24public:
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
123private:
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
3ConnectionMonitor::ConnectionMonitor()
4{
5}
6
7ConnectionMonitor::~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 */
13class ConnectionMonitor
14{
15public:
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
4ExceptionBase::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
15ExceptionBase::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
26ExceptionBase::ExceptionBase( int nCode ) throw() :
27 nErrorCode( nCode ),
28 sWhat( NULL )
29{
30}
31
32ExceptionBase::~ExceptionBase() throw()
33{
34 if( sWhat )
35 {
36 delete[] sWhat;
37 sWhat = NULL;
38 }
39}
40
41void 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
51void 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
61const char *ExceptionBase::what() const throw()
62{
63 return sWhat;
64}
65
66int 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 */
12class ExceptionBase : public std::exception
13{
14public:
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
69private:
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 ) \
75class 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 ) \
84name::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} \
92name::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} \
100name::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
4subExceptionDef( XmlException )
5subExceptionDef( FileException )
6subExceptionDef( ConnectionException )
7subExceptionDef( 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
7subExceptionDecl( XmlException )
8subExceptionDecl( FileException )
9subExceptionDecl( ConnectionException )
10subExceptionDecl( PluginException )
11
12enum eFileException
13{
14 excodeEOF
15};
16
17enum 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
4FlexBuf::FlexBuf()
5{
6 lpBuf = new char[1024];
7 nLastChar = 0;
8 nFirstChar = 0;
9 nSize = 1024;
10 nFill = 0;
11 clearData();
12}
13
14FlexBuf::~FlexBuf()
15{
16 delete[] lpBuf;
17}
18
19bool 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
59bool 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
89bool FlexBuf::appendData( const short lData )
90{
91 return appendData( (const char *)&lData, sizeof(short) );
92}
93
94bool FlexBuf::appendData( const int lData )
95{
96 return appendData( (const char *)&lData, sizeof(int) );
97}
98
99bool FlexBuf::appendData( const long lData )
100{
101 return appendData( (const char *)&lData, sizeof(long) );
102}
103
104bool FlexBuf::appendData( const float lData )
105{
106 return appendData( (const char *)&lData, sizeof(float) );
107}
108
109bool FlexBuf::appendData( const double lData )
110{
111 return appendData( (const char *)&lData, sizeof(double) );
112}
113
114bool FlexBuf::appendData( const unsigned char lData )
115{
116 return appendData( (const char)lData );
117}
118
119bool FlexBuf::appendData( const unsigned short lData )
120{
121 return appendData( (const char *)&lData, sizeof(short) );
122}
123
124bool FlexBuf::appendData( const unsigned long lData )
125{
126 return appendData( (const char *)&lData, sizeof(long) );
127}
128
129bool FlexBuf::appendData( const unsigned int lData )
130{
131 return appendData( (const char *)&lData, sizeof(int) );
132}
133
134bool FlexBuf::clearData()
135{
136 nFirstChar = nLastChar = nFill = 0;
137 lpBuf[nLastChar] = '\0';
138
139 return true;
140}
141
142const char *FlexBuf::getData()
143{
144 return (lpBuf+nFirstChar);
145}
146
147int FlexBuf::getLength()
148{
149 return nFill;
150}
151
152int FlexBuf::getCapacity()
153{
154 return nSize;
155}
156
157bool 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
194int 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
207void 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 */
16class FlexBuf
17{
18public:
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
149private:
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
3subExceptionDef( ParseException );
4
5Formula::Formula()
6{
7 hVars["pi"] = M_PI;
8 hVars["e"] = M_E;
9
10 hFunc["sin"] = FuncSin();
11}
12
13Formula::~Formula()
14{
15}
16
17double 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
38oppart: 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
63void 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
120uint8_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
147uint8_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
13subExceptionDecl( 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 */
20class Formula
21{
22public:
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
50private:
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
71private:
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
4template<> uint32_t __calcHashCode<FString>( const FString &k )
5{
6 return __calcHashCode( k.c_str() );
7}
8
9template<> bool __cmpHashKeys<FString>( const FString &a, const FString &b )
10{
11 return a == b;
12}
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
9template< typename chr >
10struct 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 */
28template< typename chr, typename chralloc=std::allocator<chr>, typename chunkalloc=std::allocator<struct FStringChunk<chr> > >
29class FBasicString : public Serializable
30{
31#ifndef VALTEST
32#define cpy( dest, src, size ) memcpy( dest, src, size*sizeof(chr) )
33#endif
34private:
35 typedef struct FStringChunk<chr> Chunk;
36 typedef struct FBasicString<chr, chralloc, chunkalloc> MyType;
37
38public:
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
385private:
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
634private:
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
644typedef FBasicString<char> FString;
645
646#include "hash.h"
647template<> uint32_t __calcHashCode<FString>( const FString &k );
648template<> 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
3subExceptionDef( HashException )
4
5template<> uint32_t __calcHashCode<int>( const int &k )
6{
7 return k;
8}
9
10template<> bool __cmpHashKeys<int>( const int &a, const int &b )
11{
12 return a == b;
13}
14
15template<> uint32_t __calcHashCode<unsigned int>( const unsigned int &k )
16{
17 return k;
18}
19
20template<> bool __cmpHashKeys<unsigned int>( const unsigned int &a, const unsigned int &b )
21{
22 return a == b;
23}
24
25template<>
26uint32_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
42template<> 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
54template<>
55uint32_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
71template<> 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
83template<> 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
97template<> bool __cmpHashKeys<std::string>( const std::string &a, const std::string &b )
98{
99 return a == b;
100}
101
102template<> uint32_t __calcHashCode<Hashable>( const Hashable &k )
103{
104 return 0;
105 //return k.getHashCode();
106}
107
108template<> 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
16subExceptionDecl( HashException )
17
18enum eHashException
19{
20 excodeNotFilled
21};
22
23template<typename T>
24uint32_t __calcHashCode( const T &k );
25
26template<typename T>
27bool __cmpHashKeys( const T &a, const T &b );
28
29struct __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
39template<typename key, typename value, typename sizecalc = __calcNextTSize_fast, typename keyalloc = std::allocator<key>, typename valuealloc = std::allocator<value>, typename challoc = std::allocator<uint32_t> >
40class Hash;
41
42template< typename key, typename _value, typename sizecalc = __calcNextTSize_fast, typename keyalloc = std::allocator<key>, typename valuealloc = std::allocator<_value>, typename challoc = std::allocator<uint32_t> >
43struct HashProxy
44{
45 friend class Hash<key, _value, sizecalc, keyalloc, valuealloc, challoc>;
46private:
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
71public:
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
134template<typename key, typename value, typename sizecalc, typename keyalloc, typename valuealloc, typename challoc >
135class Hash
136{
137 friend struct HashProxy<key, value, sizecalc, keyalloc, valuealloc, challoc>;
138public:
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
482protected:
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
667protected:
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
683template<> uint32_t __calcHashCode<int>( const int &k );
684template<> bool __cmpHashKeys<int>( const int &a, const int &b );
685
686template<> uint32_t __calcHashCode<unsigned int>( const unsigned int &k );
687template<> bool __cmpHashKeys<unsigned int>( const unsigned int &a, const unsigned int &b );
688
689template<> uint32_t __calcHashCode<const char *>( const char * const &k );
690template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b );
691
692template<> uint32_t __calcHashCode<char *>( char * const &k );
693template<> bool __cmpHashKeys<char *>( char * const &a, char * const &b );
694
695template<> uint32_t __calcHashCode<std::string>( const std::string &k );
696template<> bool __cmpHashKeys<std::string>( const std::string &a, const std::string &b );
697
698template<> uint32_t __calcHashCode<Hashable>( const Hashable &k );
699template<> bool __cmpHashKeys<Hashable>( const Hashable &a, const Hashable &b );
700
701template<typename key, typename value>
702Serializer &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
714template<typename key, typename value>
715Serializer &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
731template<typename key, typename value>
732Serializer &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
4class Hashable
5{
6public:
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
3HashFunction::HashFunction()
4{
5}
6
7HashFunction::~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 */
10class HashFunction
11{
12public:
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
6HashFunctionCaseString::HashFunctionCaseString()
7{
8}
9
10HashFunctionCaseString::~HashFunctionCaseString()
11{
12}
13
14unsigned 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
26bool 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 */
12class HashFunctionCaseString : public HashFunction
13{
14public:
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
3HashFunctionInt::HashFunctionInt()
4{
5}
6
7HashFunctionInt::~HashFunctionInt()
8{
9}
10
11unsigned long int HashFunctionInt::hash( const void *id )
12{
13 return (unsigned long)(id);
14}
15
16bool 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 */
10class HashFunctionInt : public HashFunction
11{
12public:
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
6HashFunctionString::HashFunctionString()
7{
8}
9
10HashFunctionString::~HashFunctionString()
11{
12}
13
14unsigned 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
29bool 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 */
11class HashFunctionString : public HashFunction
12{
13public:
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
7HashTable::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
18HashTable::~HashTable()
19{
20 delete[] aTable;
21 delete hFunc;
22}
23
24void 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
34void HashTable::clear()
35{
36 memset( aTable, 0, sizeof(HashNode) * nTableSize );
37}
38
39bool HashTable::isFilled( int j )
40{
41 return (aTable[j].id != NULL)||(aTable[j].bDeleted);
42}
43
44void 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
74unsigned 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
129HashTable::HashNode *HashTable::newTable( unsigned long int nNewSize )
130{
131 return new HashNode[nNewSize];
132}
133
134#ifdef HASH_DEBUG_VIS
135void 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
151bool 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
199const 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
248const 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
297void *HashTable::getFirstItemPos()
298{
299 HashPos *pos = new HashPos;
300 return pos;
301}
302
303const void *HashTable::getItemData( void *xPos )
304{
305 return aTable[((HashPos *)xPos)->nPos].data;
306}
307
308const void *HashTable::getItemID( void *xPos )
309{
310 return aTable[((HashPos *)xPos)->nPos].id;
311}
312
313void *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.
345bool 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)
368int HashTable::nextPrime( int base )
369{
370 int nPrime;
371 for( nPrime = base; isPrime( nPrime ) == false; nPrime++ );
372 return nPrime;
373}
374
375unsigned long int HashTable::getCapacity()
376{
377 return nTableSize;
378}
379
380unsigned long int HashTable::getSize()
381{
382 return nSize;
383}
384
385double HashTable::getLoad()
386{
387 return (double)(nFilled)/(double)(nTableSize);
388}
389
390const void *HashTable::operator[](const void *id)
391{
392 return get( id );
393}
394
395bool 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 */
55class HashTable
56{
57public:
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
187private:
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
227private:
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
6Http::Http( Connection *pConnection ) : hReqHeader( new HashFunctionString(), 100 )
7{
8 pCon = pConnection;
9 nParseState = parseInit;
10}
11
12Http::~Http()
13{
14 for( int j = 0; j < lStrings.getSize(); j++ )
15 {
16 delete (std::string *)lStrings[j];
17 }
18}
19
20bool 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
130bool 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
159bool 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
193void Http::setResponsePersistant( bool bPersistant )
194{
195 bResPersistant = bPersistant;
196}
197
198void Http::setResponseContent( const char *sMime, const char *sContent, int nLen )
199{
200 sResMime = sMime;
201 sResContent.erase();
202 sResContent.append( sContent, nLen );
203}
204
205std::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
273const char *Http::getRequestURI()
274{
275 return sReqURI.c_str();
276}
277
278short 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
319const 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
336short Http::getRequestType()
337{
338 return nReqType;
339}
340
341const char *Http::getRequestTypeStr()
342{
343 return getRequestType( nReqType );
344}
345
346void Http::setResponseStatus( short nStatus )
347{
348 nResStatus = nStatus;
349}
350
351void Http::setRequestVersion( unsigned char nMajor, unsigned char nMinor )
352{
353 cReqVersion = (nMajor<<4)|nMinor;
354}
355
356unsigned char Http::getRequestMinorVer()
357{
358 return cReqVersion&0x0F;
359}
360
361unsigned char Http::getRequestMajorVer()
362{
363 return cReqVersion>>4;
364}
365
366bool Http::checkRequestVer()
367{
368 if( cReqVersion == HTTP11 )
369 return true;
370 return false;
371}
372
373const 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 */
46class Http
47{
48public:
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
246private:
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
6char HttpGet::hexcode[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
7
8HttpGet::HttpGet() :
9 nPort( 80 ),
10 sUserAgent("libbu++; HttpGet")
11{
12}
13
14HttpGet::HttpGet( const std::string &url ) :
15 nPort( 80 )
16{
17 setURL( url );
18}
19
20HttpGet::~HttpGet()
21{
22}
23
24void 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
86void HttpGet::addParam( const std::string &key, const std::string &value )
87{
88 lParams.push_back( StringPair( key, value ) );
89}
90
91std::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
124SBuffer *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
11class HttpGet
12{
13public:
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
32private:
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
3LinkedList::LinkedList( )
4{
5 pBase = NULL;
6 pTop = NULL;
7 pLast = NULL;
8 nSize = 0;
9 nLast = -1;
10}
11
12LinkedList::~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
26void *LinkedList::getAt( int index )
27{
28 if( index < 0 || index >= nSize )
29 return NULL;
30
31 return getPtrTo( index )->pData;
32}
33
34void 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
50void 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
84int LinkedList::getSize( )
85{
86 return nSize;
87}
88
89bool LinkedList::isEmpty( )
90{
91 if( nSize == 0 )
92 return true;
93 return false;
94}
95
96void 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
142void LinkedList::empty()
143{
144 while( nSize > 0 )
145 {
146 deleteAt( 0 );
147 }
148}
149
150void 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
170void LinkedList::setAt( int index, void *data )
171{
172 if( index >= nSize || index < 0 )
173 return;
174
175 getPtrTo( index )->pData = data;
176}
177
178LinkedList::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 */
19class LinkedList : public List
20{
21public:
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
42private:
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
4LinkMessage::LinkMessage( int nNewMsg )
5{
6 nMsg = nNewMsg;
7}
8
9LinkMessage::~LinkMessage()
10{
11}
12
13/*
14void LinkMessage::setBroadcast( bool bOn )
15{
16 bBroadcast = bOn;
17}
18
19bool LinkMessage::isBroadcast()
20{
21 return bBroadcast;
22}
23
24
25void LinkMessage::setFromID( int id )
26{
27 nFromLinkID = id;
28}
29
30int LinkMessage::getFromID()
31{
32 return nFromLinkID;
33}
34
35void LinkMessage::setToID( int id )
36{
37 nTargetLinkID = id;
38}
39
40int 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 */
13class LinkMessage
14{
15public:
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
3LinkMessenger::LinkMessenger() :
4 pFirst( NULL ),
5 pLast( NULL )
6{
7}
8
9LinkMessenger::~LinkMessenger()
10{
11}
12
13void 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
30LinkMessage *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
8class LinkMessenger
9{
10public:
11 LinkMessenger();
12 virtual ~LinkMessenger();
13
14 void enqueueMessage( LinkMessage *pMsg );
15 LinkMessage *dequeueMessage();
16 bool hasMessages()
17 {
18 return (pFirst != NULL);
19 }
20
21private:
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
3List::List( )
4{
5}
6
7List::~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 */
9class List
10{
11public:
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
29inline 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
34md5::md5()
35{
36}
37
38md5::~md5()
39{
40}
41
42/*
43 * Calculate the MD5 of an array of little-endian words, and a bit length
44 */
45void 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
140long *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
161void 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
174void md5::sumString( md5sum *pSum, const char *sStr )
175{
176 sumData( pSum, sStr, strlen( sStr ) );
177}
178
179void 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
186void 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 */
7typedef 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 */
17class md5
18{
19public:
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
51private:
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
9MultiLog::MultiLog()
10{
11 lChannel = new LinkedList();
12 rEntry = new RingList( 150 );
13 nEntriesLost = 0;
14}
15
16MultiLog::~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/*
33void 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
48void 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
70void 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
85void 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
97MultiLog::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 */
33class MultiLog : public Singleton<MultiLog>
34{
35 friend class Singleton<MultiLog>;
36public:
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
53protected:
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
85public:
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 */
12class MultiLogChannel
13{
14public:
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/*
9bool 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
23MultiLogText::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
53MultiLogText::MultiLogText( int nFileDesc, const char *lpFormat )
54{
55 this->lpFormat = NULL;
56 nFD = nFileDesc;
57 setLogFormat( lpFormat );
58}
59
60MultiLogText::~MultiLogText()
61{
62 if( nFD != -1 )
63 {
64 close( nFD );
65 }
66
67 delete[] lpFormat;
68}
69
70bool 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
135bool MultiLogText::openLog()
136{
137 if( nFD == -1 )
138 {
139 return false;
140 }
141 return true;
142}
143
144bool 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
174bool 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 */
26class MultiLogText : public MultiLogChannel
27{
28public:
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
65private:
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
7template<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> >
8class OrdHash : public Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>
9{
10public:
11 OrdHash() :
12 bSorted( false ),
13 aData( NULL )
14 {
15 }
16
17 virtual ~OrdHash()
18 {
19 }
20
21protected:
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 }
93public:
94 typedef struct ind
95 {
96 value *pVal;
97 uint32_t nIndex;
98 } ind;
99private:
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
8ParamProc::ParamPtr::ParamPtr()
9{
10 val.str = NULL;
11 type = vtunset;
12}
13
14ptrtype( std::string, str );
15ptrtype( uint64_t, uint64 );
16ptrtype( uint32_t, uint32 );
17ptrtype( uint16_t, uint16 );
18ptrtype( uint8_t, uint8 );
19ptrtype( int64_t, int64 );
20ptrtype( int32_t, int32 );
21ptrtype( int16_t, int16 );
22ptrtype( int8_t, int8 );
23ptrtype( float, float32 );
24ptrtype( double, float64 );
25ptrtype( long double, float96 );
26ptrtype( bool, bln );
27
28ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( ParamProc::ParamPtr &ptr )
29{
30 val = ptr.val;
31 type = ptr.type;
32
33 return *this;
34}
35
36bool ParamProc::ParamPtr::isSet()
37{
38 return type != vtunset;
39}
40
41ParamProc::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
110ParamProc::ParamProc()
111{
112}
113
114ParamProc::~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/*
130void 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
137void 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
164void 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
171void 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
178void 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
185void 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
192void 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
199void 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
206void 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
213void 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
220void 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
387ParamProc::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
412ParamProc::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
430int ParamProc::cmdParam( int argc, char *argv[] )
431{
432 printf("Unhandled command parameter \"%s\" found!\n", argv[0] );
433 return 0;
434}
435
436int ParamProc::unknownParam( int argc, char *argv[] )
437{
438 printf("Unknown parameter \"%s\" found!\n", argv[0] );
439 return 0;
440}
441
442int 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
507void 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
9class ParamProc
10{
11public:
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
86public:
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
132private:
133 ArgSpec *checkWord( const char *arg );
134 ArgSpec *checkLetr( const char arg );
135
136public:
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
141private:
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
12typedef 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
22typedef struct PluginReg
23{
24 bool bBuiltin;
25 void *dlHandle;
26 PluginInfo *pInfo;
27} PluginReg;
28
29#define PluginInterface( classname, baseclass, name, ver, rev ) \
30extern "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 ) \
45extern "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 ) \
61extern "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
76template<class T>
77class Plugger
78{
79public:
80
81public:
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
192private:
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
3PQueue::PQueue( int nNewNumQueues )
4{
5 nNumQueues = nNewNumQueues;
6 aQueue = new Queue[nNumQueues];
7}
8
9PQueue::~PQueue()
10{
11 delete[] aQueue;
12}
13
14void PQueue::enqueue( void *pData, int nQueueLevel )
15{
16 if( nQueueLevel < 0 || nQueueLevel >= nNumQueues )
17 return;
18
19 aQueue[nQueueLevel].enqueue( pData );
20}
21
22void *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 */
11class PQueue
12{
13public:
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
36private:
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
4ProgramChain::ProgramChain() :
5 xLog( MultiLog::getInstance() )
6{
7 xLog.LineLog( MultiLog::LStatus, "Program Chain Initialized." );
8}
9
10ProgramChain::~ProgramChain()
11{
12}
13
14bool 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
29ProgramLink *ProgramChain::getLink( const char *lpName )
30{
31 char a;
32 a = lpName[0];
33 return NULL;
34}
35
36ProgramLink *ProgramChain::getBaseLink()
37{
38 return NULL;
39}
40
41bool 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
57bool ProgramChain::enterChainLoop()
58{
59 for(;;)
60 {
61 if( execChainOnce() == false )
62 {
63 return false;
64 }
65 }
66
67 return true;
68}
69
70void 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
81LinkMessage *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 */
13class ProgramChain
14{
15public:
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
86private:
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
4ProgramLink::ProgramLink()
5{
6}
7
8ProgramLink::~ProgramLink()
9{
10}
11
12LinkMessage *ProgramLink::sendIRM( LinkMessage *pMsgOut )
13{
14 return pChain->broadcastIRM( pMsgOut, this );
15}
16
17void ProgramLink::setChain( ProgramChain *pNewChain )
18{
19 pChain = pNewChain;
20}
21
22/*
23void 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
39LinkMessage *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
4class 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 */
14class ProgramLink
15{
16friend class ProgramChain;
17public:
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
71private:
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
93private:
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
3Protocol::Protocol()
4{
5 pConnection = NULL;
6}
7
8Protocol::~Protocol()
9{
10}
11
12void Protocol::setConnection( Connection *pNewConnection )
13{
14 pConnection = pNewConnection;
15}
16
17Connection *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 */
10class Protocol
11{
12public:
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
58private:
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
4ProtocolTelnet::ProtocolTelnet()
5{
6 nTermType = termUnInited;
7 bEchoOn = true;
8}
9
10ProtocolTelnet::~ProtocolTelnet()
11{
12}
13
14bool 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
49bool 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
265char *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
290char *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
313void 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 */
13class ProtocolTelnet : public Protocol
14{
15public:
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
66private:
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
3void Queue::enqueue( void *data )
4{
5 lQueueData.append( data );
6}
7
8void *Queue::dequeue()
9{
10 void *dat = lQueueData[0];
11 if( dat != NULL )
12 {
13 lQueueData.deleteAt( 0 );
14 }
15 return dat;
16}
17
18bool Queue::isEmpty()
19{
20 return lQueueData.isEmpty();
21}
22
23void 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 */
10class Queue
11{
12public:
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
42private:
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
16RingList::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
26RingList::~RingList()
27{
28 delete[] apData;
29}
30
31void *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
41void 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
60void RingList::insertBefore( void *pData, int nPos )
61{
62 // Not implemented right now, don't even try it!
63}
64
65int RingList::getSize()
66{
67 return nDataLength;
68}
69
70bool RingList::isEmpty()
71{
72 return nDataLength==0;
73}
74
75void RingList::deleteAt( int nIndex )
76{
77 // Also not implemented yet
78}
79
80void RingList::empty()
81{
82 nFirstIndex = 0;
83 nDataLength = 0;
84}
85
86void 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
98void RingList::setAt( int nIndex, void *pData )
99{
100 apData[(nIndex+nFirstIndex)%nRealLength] = pData;
101}
102
103void *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 */
18class RingList : public List
19{
20public:
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
103private:
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
4SBuffer::SBuffer() :
5 nPos( 0 ),
6 bOpen( true )
7{
8}
9
10SBuffer::~SBuffer()
11{
12}
13
14void SBuffer::close()
15{
16 bOpen = false;
17 fbData.clearData();
18}
19
20size_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
35size_t SBuffer::write( const char *pBuf, size_t nBytes )
36{
37 fbData.appendData( pBuf, nBytes );
38 nPos += nBytes;
39
40 return nBytes;
41}
42
43long SBuffer::tell()
44{
45 return nPos;
46}
47
48void SBuffer::seek( long offset )
49{
50 nPos += offset;
51}
52
53void SBuffer::setPos( long pos )
54{
55 nPos = pos;
56}
57
58void SBuffer::setPosEnd( long pos )
59{
60 nPos = fbData.getLength() - pos;
61}
62
63bool 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
9class SBuffer : public Stream
10{
11public:
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
34private:
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
3Serializable::Serializable()
4{
5}
6Serializable::~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 */
11class Serializable
12{
13public:
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
5Serializer::Serializer(bool bLoading):
6 bLoading(bLoading)
7{
8}
9Serializer::~Serializer()
10{
11}
12
13bool Serializer::isLoading()
14{
15 return bLoading;
16}
17Serializer &Serializer::operator<<(bool p)
18{
19 write( &p, sizeof(p) );
20 return *this;
21}
22Serializer &Serializer::operator<<(int8_t p)
23{
24 write( &p, sizeof(p) );
25 return *this;
26}
27Serializer &Serializer::operator<<(int16_t p)
28{
29 write( &p, sizeof(p) );
30 return *this;
31}
32Serializer &Serializer::operator<<(int32_t p)
33{
34 write( &p, sizeof(p) );
35 return *this;
36}
37Serializer &Serializer::operator<<(int64_t p)
38{
39 write( &p, sizeof(p) );
40 return *this;
41}
42Serializer &Serializer::operator<<(uint8_t p)
43{
44 write( &p, sizeof(p) );
45 return *this;
46}
47Serializer &Serializer::operator<<(uint16_t p)
48{
49 write( &p, sizeof(p) );
50 return *this;
51}
52Serializer &Serializer::operator<<(uint32_t p)
53{
54 write( &p, sizeof(p) );
55 return *this;
56}
57Serializer &Serializer::operator<<(uint64_t p)
58{
59 write( &p, sizeof(p) );
60 return *this;
61}
62Serializer &Serializer::operator<<(long p)
63{
64 write( &p, sizeof(p) );
65 return *this;
66}
67Serializer &Serializer::operator<<(float p)
68{
69 write( &p, sizeof(p) );
70 return *this;
71}
72Serializer &Serializer::operator<<(double p)
73{
74 write( &p, sizeof(p) );
75 return *this;
76}
77Serializer &Serializer::operator<<(long double p)
78{
79 write( &p, sizeof(p) );
80 return *this;
81}
82
83Serializer &Serializer::operator>>(bool &p)
84{
85 read( &p, sizeof(p) );
86 return *this;
87}
88Serializer &Serializer::operator>>(int8_t &p)
89{
90 read( &p, sizeof(p) );
91 return *this;
92}
93Serializer &Serializer::operator>>(int16_t &p)
94{
95 read( &p, sizeof(p) );
96 return *this;
97}
98Serializer &Serializer::operator>>(int32_t &p)
99{
100 read( &p, sizeof(p) );
101 return *this;
102}
103Serializer &Serializer::operator>>(int64_t &p)
104{
105 read( &p, sizeof(p) );
106 return *this;
107}
108Serializer &Serializer::operator>>(uint8_t &p)
109{
110 read( &p, sizeof(p) );
111 return *this;
112}
113Serializer &Serializer::operator>>(uint16_t &p)
114{
115 read( &p, sizeof(p) );
116 return *this;
117}
118Serializer &Serializer::operator>>(uint32_t &p)
119{
120 read( &p, sizeof(p) );
121 return *this;
122}
123Serializer &Serializer::operator>>(uint64_t &p)
124{
125 read( &p, sizeof(p) );
126 return *this;
127}
128Serializer &Serializer::operator>>(long &p)
129{
130 read( &p, sizeof(p) );
131 return *this;
132}
133Serializer &Serializer::operator>>(float &p)
134{
135 read( &p, sizeof(p) );
136 return *this;
137}
138Serializer &Serializer::operator>>(double &p)
139{
140 read( &p, sizeof(p) );
141 return *this;
142}
143Serializer &Serializer::operator>>(long double &p)
144{
145 read( &p, sizeof(p) );
146 return *this;
147}
148
149Serializer &Serializer::operator&&(bool &p)
150{
151 if (bLoading)
152 {
153 return *this >> p;
154 }
155 else
156 {
157 return *this << p;
158 }
159}
160
161Serializer &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
173Serializer &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
185Serializer &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
197Serializer &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
209Serializer &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
221Serializer &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
233Serializer &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
245Serializer &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
257Serializer &Serializer::operator&&(float &p)
258{
259 if (bLoading)
260 {
261 return *this >> p;
262 }
263 else
264 {
265 return *this << p;
266 }
267}
268
269Serializer &Serializer::operator&&(double &p)
270{
271 if (bLoading)
272 {
273 return *this >> p;
274 }
275 else
276 {
277 return *this << p;
278 }
279}
280
281Serializer &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
294Serializer &operator<<(Serializer &s, Serializable &p)
295{
296 p.serialize( s );
297 return s;
298}
299
300Serializer &operator>>(Serializer &s, Serializable &p)
301{
302 p.serialize( s );
303 return s;
304}
305
306Serializer &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
318Serializer &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
326Serializer &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
9class Serializer
10{
11private:
12 bool bLoading;
13public:
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
73Serializer &operator<<(Serializer &, class Serializable &);
74Serializer &operator>>(Serializer &, class Serializable &);
75Serializer &operator&&(Serializer &s, class Serializable &p);
76
77Serializer &operator<<(Serializer &, std::string &);
78Serializer &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
5SerializerBinary::SerializerBinary(FILE *fhFile, bool bLoading):
6 Serializer(bLoading),
7 fhFile(fhFile),
8 bCloseFile(false)
9{
10}
11
12SerializerBinary::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
30SerializerBinary::~SerializerBinary()
31{
32 close();
33}
34
35void SerializerBinary::close()
36{
37 if (fhFile != NULL && bCloseFile )
38 {
39 fclose(fhFile);
40 fhFile = NULL;
41 }
42}
43
44void SerializerBinary::write(const void * pData, int32_t nSize)
45{
46 if( nSize == 0 )
47 return;
48
49 fwrite(pData, nSize, 1, fhFile);
50}
51
52void 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
7class SerializerBinary : public Serializer
8{
9public:
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
19private:
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
6SerializerBZip2::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
23SerializerBZip2::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
41SerializerBZip2::~SerializerBZip2()
42{
43 close();
44}
45
46void SerializerBZip2::checkBZError()
47{
48}
49
50void 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
77void SerializerBZip2::write(const void * pData, int32_t nSize)
78{
79 BZ2_bzWrite( &bzerror, bzFile, (void *)pData, nSize );
80 checkBZError();
81}
82
83void 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
7class SerializerBZip2 : public Serializer
8{
9public:
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
19private:
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
3SerializerConnection::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
12SerializerConnection::~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 */
12class SerializerConnection : public Serializer
13{
14public:
15 SerializerConnection( Connection *pCon, bool bIO, int nTimeSec, int nTimeUSec );
16 virtual ~SerializerConnection();
17
18private:
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
3SerializerText::SerializerText(FILE *fhFile, bool bLoading):
4 Serializer(bLoading),
5 fhFile(fhFile),
6 bCloseFile(false)
7{
8}
9
10SerializerText::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
24SerializerText::~SerializerText()
25{
26 close();
27}
28
29void SerializerText::close()
30{
31 if (fhFile != NULL)
32 {
33 fclose(fhFile);
34 fhFile = NULL;
35 }
36}
37
38void SerializerText::write(const void * pData, int32_t nSize)
39{
40 fwrite(pData, nSize, 1, fhFile);
41 fprintf(fhFile, "\n");
42}
43
44void SerializerText::read(void * pData, int32_t nSize)
45{
46 fread(pData, nSize, 1, fhFile);
47 fgetc(fhFile);
48}
49
50Serializer &SerializerText::operator<<(bool p)
51{
52 fprintf(fhFile, "%hhd\n", p);
53 return *this;
54}
55Serializer &SerializerText::operator<<(int8_t p)
56{
57 fprintf(fhFile, "%hhd\n", p);
58 return *this;
59}
60Serializer &SerializerText::operator<<(int16_t p)
61{
62 fprintf(fhFile, "%hd\n", p);
63 return *this;
64}
65Serializer &SerializerText::operator<<(int32_t p)
66{
67 fprintf(fhFile, "%d\n", p);
68 return *this;
69}
70Serializer &SerializerText::operator<<(int64_t p)
71{
72 fprintf(fhFile, "%lld\n", p);
73 return *this;
74}
75Serializer &SerializerText::operator<<(uint8_t p)
76{
77 fprintf(fhFile, "%hhu\n", p);
78 return *this;
79}
80Serializer &SerializerText::operator<<(uint16_t p)
81{
82 fprintf(fhFile, "%hu\n", p);
83 return *this;
84}
85Serializer &SerializerText::operator<<(uint32_t p)
86{
87 fprintf(fhFile, "%u\n", p);
88 return *this;
89}
90Serializer &SerializerText::operator<<(uint64_t p)
91{
92 fprintf(fhFile, "%llu\n", p);
93 return *this;
94}
95Serializer &SerializerText::operator<<(float p)
96{
97 fprintf(fhFile, "%f\n", p);
98 return *this;
99}
100Serializer &SerializerText::operator<<(double p)
101{
102 fprintf(fhFile, "%f\n", p);
103 return *this;
104}
105Serializer &SerializerText::operator<<(long double p)
106{
107 fprintf(fhFile, "%Lf\n", p);
108 return *this;
109}
110
111Serializer &SerializerText::operator>>(bool &p)
112{
113 fscanf(fhFile, "%hhd\n", ((signed char *)&p));
114 return *this;
115}
116Serializer &SerializerText::operator>>(int8_t &p)
117{
118 fscanf(fhFile, "%hhd\n", &p);
119 return *this;
120}
121Serializer &SerializerText::operator>>(int16_t &p)
122{
123 fscanf(fhFile, "%hd\n", &p);
124 return *this;
125}
126Serializer &SerializerText::operator>>(int32_t &p)
127{
128 fscanf(fhFile, "%d\n", &p);
129 return *this;
130}
131Serializer &SerializerText::operator>>(int64_t &p)
132{
133 fscanf(fhFile, "%lld\n", &p);
134 return *this;
135}
136Serializer &SerializerText::operator>>(uint8_t &p)
137{
138 fscanf(fhFile, "%hhu\n", &p);
139 return *this;
140}
141Serializer &SerializerText::operator>>(uint16_t &p)
142{
143 fscanf(fhFile, "%hu\n", &p);
144 return *this;
145}
146Serializer &SerializerText::operator>>(uint32_t &p)
147{
148 fscanf(fhFile, "%u\n", &p);
149 return *this;
150}
151Serializer &SerializerText::operator>>(uint64_t &p)
152{
153 fscanf(fhFile, "%llu\n", &p);
154 return *this;
155}
156Serializer &SerializerText::operator>>(float &p)
157{
158 fscanf(fhFile, "%f\n", &p);
159 return *this;
160}
161Serializer &SerializerText::operator>>(double &p)
162{
163 fscanf(fhFile, "%lf\n", &p);
164 return *this;
165}
166Serializer &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
7class SerializerText : public Serializer
8{
9public:
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 &);
44private:
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
4SFile::SFile( const char *sName, const char *sFlags )
5{
6 fh = fopen( sName, sFlags );
7}
8
9SFile::~SFile()
10{
11}
12
13void SFile::close()
14{
15 if( fh )
16 {
17 fclose( fh );
18 fh = NULL;
19 }
20}
21
22size_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
30size_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
38long SFile::tell()
39{
40 if( !fh )
41 throw FileException("File not open.");
42
43 return ftell( fh );
44}
45
46void SFile::seek( long offset )
47{
48 if( !fh )
49 throw FileException("File not open.");
50
51 fseek( fh, offset, SEEK_CUR );
52}
53
54void SFile::setPos( long pos )
55{
56 if( !fh )
57 throw FileException("File not open.");
58
59 fseek( fh, pos, SEEK_SET );
60}
61
62void SFile::setPosEnd( long pos )
63{
64 if( !fh )
65 throw FileException("File not open.");
66
67 fseek( fh, pos, SEEK_END );
68}
69
70bool 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
8class SFile : public Stream
9{
10public:
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
24private:
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
7Sha1::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
18Sha1::~Sha1()
19{
20}
21
22void 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
79void 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
106unsigned 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
149uint32_t Sha1::lrot( uint32_t x, int bits )
150{
151 return (x<<bits) | (x>>(32 - bits));
152};
153
154void 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
3Copyright (c) 2005 Michael D. Leonhard
4
5http://tamale.net/
6
7This file is licensed under the terms described in the
8accompanying 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 */
20class Sha1
21{
22public:
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
33private:
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 */
29template <class T>
30class Singleton
31{
32protected:
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
40private:
41 /**
42 * Copy constructor, defined so that you could write your own as well.
43 */
44 Singleton( const Singleton& );
45
46public:
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
7template<typename T>
8class SPtr
9{
10public:
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
78private:
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
3void Stack::push( void *data )
4{
5 lStackData.append( data );
6}
7
8void *Stack::top()
9{
10 return lStackData.getAt( lStackData.getSize()-1 );
11}
12
13void Stack::pop()
14{
15 lStackData.deleteAt( lStackData.getSize()-1 );
16}
17
18void *Stack::poptop()
19{
20 void *dat = top();
21 pop();
22 return dat;
23}
24
25bool Stack::isEmpty()
26{
27 return lStackData.isEmpty();
28}
29
30void 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 */
8class Stack
9{
10public:
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
47private:
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
8StaticString::StaticString()
9{
10 lpStr = NULL;
11 nLen = 0;
12}
13
14StaticString::StaticString( int nLength )
15{
16 lpStr = new char[nLength+1];
17 nLen = nLength;
18 memset( lpStr, 0, nLength+1 );
19}
20
21StaticString::StaticString( const char *lpNewStr, int nNewLen )
22{
23 lpStr = NULL;
24 nLen = 0;
25 setString( lpNewStr, nNewLen );
26}
27
28StaticString::StaticString( const char *lpNewStr )
29{
30 lpStr = NULL;
31 nLen = 0;
32 setString( lpNewStr, -1 );
33}
34
35StaticString::StaticString( StaticString &xSrcStr, int nNewLen )
36{
37 lpStr = NULL;
38 nLen = 0;
39 setString( xSrcStr, nNewLen );
40}
41
42StaticString::StaticString( StaticString &xSrcStr )
43{
44 lpStr = NULL;
45 nLen = 0;
46 setString( xSrcStr, -1 );
47}
48
49StaticString::StaticString( const StaticString &xSrcStr )
50{
51 nLen = xSrcStr.getLength();
52 lpStr = new char[nLen];
53 memcpy( lpStr, xSrcStr.getString(), nLen );
54}
55
56StaticString::~StaticString()
57{
58 if( lpStr != NULL ) delete[] lpStr;
59}
60
61char *StaticString::getString()
62{
63 return lpStr;
64}
65
66const char *StaticString::getString() const
67{
68 return lpStr;
69}
70
71int StaticString::getLength() const
72{
73 return nLen;
74}
75
76void 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
92void 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
117void 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
142StaticString &StaticString::operator=( StaticString &lpOtherStr )
143{
144 setString( lpOtherStr );
145
146 return *this;
147}
148
149StaticString &StaticString::operator=( std::string &lpOtherStr )
150{
151 setString( lpOtherStr.c_str() );
152
153 return *this;
154}
155
156StaticString &StaticString::operator=( const char *lpNewStr )
157{
158 setString( lpNewStr );
159
160 return *this;
161}
162
163StaticString::operator const char *()
164{
165 return lpStr;
166}
167
168char StaticString::getAt( unsigned int nIndex )
169{
170 if( nIndex < 0 || nIndex >= nLen )
171 return '\0';
172
173 return lpStr[nIndex];
174}
175
176void StaticString::setAt( unsigned int nIndex, char cVal )
177{
178 if( nIndex < 0 || nIndex >= nLen )
179 return;
180
181 lpStr[nIndex] = cVal;
182}
183
184char &StaticString::operator[]( unsigned int nIndex )
185{
186 if( nIndex < 0 || nIndex >= nLen )
187 return lpStr[0];
188
189 return lpStr[nIndex];
190}
191
192StaticString::operator int()
193{
194 return nLen;
195}
196
197char *StaticString::operator+( int nAmnt )
198{
199 return lpStr + nAmnt;
200}
201
202char *StaticString::operator-( int nAmnt )
203{
204 return lpStr - nAmnt;
205}
206
207void StaticString::clear()
208{
209 memset( lpStr, 0, nLen+1 );
210}
211
212void 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
227bool 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
234bool 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
241bool 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
248bool 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/*
255unsigned 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
266bool 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 */
15class StaticString : public Serializable/*, public Hashable*/
16{
17public:
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
58private:
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
3Stream::Stream()
4{
5}
6
7Stream::~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
7class Stream
8{
9public:
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
23private:
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
3int32_t stringlen( const char *s )
4{
5 for( int32_t i = 0;; i++ )
6 if( !s[i] )
7 return i;
8}
9
10char *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 */
9int32_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 */
15char *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
3int 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
4using namespace std;
5
6int 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
7int 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
4int 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
3int 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
4FString 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
15void 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() );
21int 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
4int 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
6int 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
4int 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
6HttpConnectionMonitor::HttpConnectionMonitor()
7{
8}
9
10HttpConnectionMonitor::~HttpConnectionMonitor()
11{
12}
13
14bool 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
84bool 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
6class HttpConnectionMonitor : public ConnectionMonitor
7{
8public:
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
4int 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
7class Test
8{
9public:
10 Test()
11 {
12 MultiLineLog( 4, "Test init'd\n");
13 }
14};
15
16int 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
5int 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
4typedef 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
13struct seqcmp
14{
15 bool operator()( eldef **a, eldef **b )
16 {
17 return (*a)->nSequence < (*b)->nSequence;
18 }
19};
20
21struct namcmp
22{
23 bool operator()( eldef **a, eldef **b )
24 {
25 return (*a)->sName < (*b)->sName;
26 }
27};
28
29typedef OrdHash<int, eldef, seqcmp> AHash;
30//typedef OrdHash<int, eldef, namcmp> AHash;
31
32int 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
4Param::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
18Param::~Param()
19{
20}
21
22int 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
35int 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
8class Param : public ParamProc
9{
10public:
11 Param();
12 virtual ~Param();
13
14private:
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
4int 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
3Plugin::Plugin()
4{
5}
6
7Plugin::~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
4class Plugin
5{
6public:
7 Plugin();
8 virtual ~Plugin();
9
10private:
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).
9typedef 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
53template<typename QSORT_TYPE, typename QSORT_LTT>
54void 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
206struct cc
207{
208 bool operator()( int *a, int *b )
209 {
210 return *a < *b;
211 }
212};
213
214#include <stdio.h>
215
216int 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
3int 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
6int 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
5int 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
6int 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
4class Annoy
5{
6public:
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
25void beAnnoying( SPtr<Annoy> bob )
26{
27 printf("bob-Count: %d\n", bob.count() );
28 bob->go();
29}
30
31int 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
6class StressProtocol : public Protocol
7{
8public:
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
31class StressMonitor : public ConnectionMonitor, public ProgramLink
32{
33public:
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
74int 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
4int 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
4int 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
5TelnetMonitor::TelnetMonitor()
6{
7}
8
9TelnetMonitor::~TelnetMonitor()
10{
11}
12
13bool TelnetMonitor::init()
14{
15 return true;
16}
17
18bool TelnetMonitor::deInit()
19{
20 return true;
21}
22
23bool 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
35LinkMessage* TelnetMonitor::processIRM( LinkMessage *pMsg )
36{
37 return NULL;
38}
39
40bool 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
50bool 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
8class TelnetMonitor : public ConnectionMonitor, public ProgramLink
9{
10public:
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
22private:
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
5int 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
3int 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
5void 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
29int 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
4TokenString::TokenString( const char *lpNewTokenString )
5{
6 lpTokenString = NULL;
7 if( lpNewTokenString )
8 {
9 parseLine( lpNewTokenString );
10 }
11}
12
13TokenString::~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
23void 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
79void 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
93void 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
106int TokenString::getNumTokens()
107{
108 return lToken.getSize();
109}
110
111char *TokenString::getToken( int nIndex )
112{
113 if( nIndex >= lToken.getSize() ) return NULL;
114 return (char *)(((Token *)lToken[nIndex])->lpToken);
115}
116
117char *TokenString::getTokenString( int nIndex )
118{
119 if( nIndex >= lToken.getSize() ) return NULL;
120 return (char *)(((Token *)lToken[nIndex])->lpOrig);
121}
122
123void 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 */
23class TokenString{
24public:
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
100private:
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).
12typedef 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
56template<typename QSORT_TYPE, typename QSORT_LTT, typename CST>
57void 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
13class HashFunctionSuite : public Test::Suite
14{
15public:
16 HashFunctionSuite()
17 {
18 TEST_ADD( HashFunctionSuite::functionString )
19 TEST_ADD( HashFunctionSuite::functionCaseString )
20 TEST_ADD( HashFunctionSuite::functionInt )
21 }
22
23private:
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
101int 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
10class XmlCoreTestSuite : public Test::Suite
11{
12public:
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
24private:
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>&gt;&lt;&amp;&apos;&quot;</hello>");
43 TEST_ASSERT( strcmp( r.getRoot()->getContent(), "><&\'\"" ) == 0 );
44 }
45
46 void entityDoc01()
47 {
48 XmlStringReader r("<!ENTITY name \"bob the man\"><hello>&quot;&name;&quot;</hello>");
49 TEST_ASSERT( strcmp( r.getRoot()->getContent(), "\"bob the man\"" ) == 0 );
50 }
51};
52
53int 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
5XmlDocument::XmlDocument( XmlNode *pRoot )
6{
7 this->pRoot = pRoot;
8 pCurrent = NULL;
9 bCompleted = (pRoot!=NULL);
10}
11
12XmlDocument::~XmlDocument()
13{
14 if( pRoot )
15 {
16 delete pRoot;
17 }
18}
19
20void 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
38void XmlDocument::setName( const char *sName )
39{
40 pCurrent->setName( sName );
41}
42
43bool XmlDocument::isCompleted()
44{
45 return bCompleted;
46}
47
48XmlNode *XmlDocument::getRoot()
49{
50 return pRoot;
51}
52
53XmlNode *XmlDocument::detatchRoot()
54{
55 XmlNode *pTemp = pRoot;
56 pRoot = NULL;
57 return pTemp;
58}
59
60XmlNode *XmlDocument::getCurrent()
61{
62 return pCurrent;
63}
64
65void 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
78void XmlDocument::addProperty( const char *sName, const char *sValue )
79{
80 if( pCurrent )
81 {
82 pCurrent->addProperty( sName, sValue );
83 }
84}
85
86void 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
93void XmlDocument::addProperty( const char *sName, const char nValue )
94{
95 char buf[12];
96 sprintf( buf, "%hhi", nValue );
97 addProperty( sName, buf );
98}
99
100void 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
107void XmlDocument::addProperty( const char *sName, const short nValue )
108{
109 char buf[12];
110 sprintf( buf, "%hi", nValue );
111 addProperty( sName, buf );
112}
113
114void XmlDocument::addProperty( const char *sName, const int nValue )
115{
116 char buf[12];
117 sprintf( buf, "%d", nValue );
118 addProperty( sName, buf );
119}
120
121void 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
128void XmlDocument::addProperty( const char *sName, const long nValue )
129{
130 char buf[12];
131 sprintf( buf, "%li", nValue );
132 addProperty( sName, buf );
133}
134
135void XmlDocument::addProperty( const char *sName, const double dValue )
136{
137 char buf[40];
138 sprintf( buf, "%f", dValue );
139 addProperty( sName, buf );
140}
141
142void 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 */
14class XmlDocument
15{
16public:
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
165private:
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
5XmlFileReader::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
21XmlFileReader::~XmlFileReader()
22{
23}
24
25char 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
52void 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 */
24class XmlFileReader : public XmlReader
25{
26public:
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
40private:
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
5XmlFileWriter::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
13XmlFileWriter::XmlFileWriter( FILE *fh, const char *sIndent, XmlNode *pRoot ) :
14 XmlWriter( sIndent, pRoot ),
15 fh( fh )
16{
17}
18
19XmlFileWriter::~XmlFileWriter()
20{
21 fclose( fh );
22}
23
24void 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 */
23class XmlFileWriter : public XmlWriter
24{
25public:
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
39private:
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
4XmlNode::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
24XmlNode::~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
51void 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
77void 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
104const 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
125XmlNode *XmlNode::addChild( const char *sName, const char *sContent )
126{
127 return addChild( new XmlNode( sName, this, sContent ) );
128}
129
130XmlNode *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
140XmlNode *XmlNode::getParent()
141{
142 return pParent;
143}
144
145void 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
155int XmlNode::getNumProperties()
156{
157 return lPropNames.getSize();
158}
159
160const 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
168const 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
176const 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
184void 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
195bool XmlNode::hasChildren()
196{
197 return lChildren.getSize()>0;
198}
199
200int XmlNode::getNumChildren()
201{
202 return lChildren.getSize();
203}
204
205XmlNode *XmlNode::getChild( int nIndex )
206{
207 return (XmlNode *)lChildren[nIndex];
208}
209
210XmlNode *XmlNode::getChild( const char *sName, int nSkip )
211{
212 return (XmlNode *)hChildren.get( sName, nSkip );
213}
214
215const char *XmlNode::getName()
216{
217 return sName.c_str();
218}
219
220void 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
230XmlNode *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
315void 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
325XmlNode *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
384void 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
442void 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 */
18class XmlNode
19{
20public:
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
222private:
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
6XmlReader::XmlReader( bool bStrip ) :
7 bStrip( bStrip ),
8 htEntity( new HashFunctionString(), 11 )
9{
10}
11
12XmlReader::~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
22void 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
34bool XmlReader::isws( char chr )
35{
36 return ( chr == ' ' || chr == '\t' || chr == '\n' || chr == '\r' );
37}
38
39bool 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
56bool 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
72void 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
92void 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
182bool 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
218bool 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
287bool 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
309bool 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
328StaticString *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
375bool 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
472bool 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 */
26class XmlReader : public XmlDocument
27{
28public:
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
48private:
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
5XmlStringReader::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
16XmlStringReader::~XmlStringReader()
17{
18}
19
20char 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
32void 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 */
24class XmlStringReader : public XmlReader
25{
26public:
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
41private:
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
5XmlStringWriter::XmlStringWriter( const char *sIndent ) :
6 XmlWriter( sIndent )
7{
8}
9
10XmlStringWriter::~XmlStringWriter()
11{
12}
13
14void XmlStringWriter::writeString( const char *sString )
15{
16 sXml += sString;
17}
18
19std::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 */
23class XmlStringWriter : public XmlWriter
24{
25public:
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
45private:
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
5XmlWriter::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
18XmlWriter::~XmlWriter()
19{
20}
21
22void XmlWriter::write()
23{
24 write( getRoot(), sIndent.c_str() );
25}
26
27void XmlWriter::write( XmlNode *pRoot, const char *sIndent )
28{
29 writeNode( pRoot, 0, sIndent );
30}
31
32void XmlWriter::closeNode()
33{
34 XmlDocument::closeNode();
35
36 if( isCompleted() )
37 {
38 write( getRoot(), sIndent.c_str() );
39 }
40}
41
42void 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
51std::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
79void 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
91void 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 */
23class XmlWriter : public XmlDocument
24{
25public:
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
51private:
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